rsaenh: Infer private exponent length from data length.
[wine] / dlls / rsaenh / tests / rsaenh.c
1 /*
2  * Unit tests for rsaenh functions
3  *
4  * Copyright (c) 2004 Michael Jung
5  * Copyright (c) 2006 Juan Lang
6  * Copyright (c) 2007 Vijay Kiran Kamuju
7  *
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.
12  *
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.
17  *
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
21  */
22
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"
31
32 static HCRYPTPROV hProv;
33 static const char szContainer[] = "winetest";
34 static const char szProvider[] = MS_ENHANCED_PROV_A;
35
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;
43
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}
57 };
58
59 /*
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
64  *
65  */
66 static void uniquecontainer(char *unique)
67 {
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;
76
77     /* Get the MachineGUID */
78     ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, szCryptography, 0, KEY_READ | KEY_WOW64_64KEY, &hkey);
79     if (ret == ERROR_ACCESS_DENIED)
80     {
81         /* Windows 2000 can't handle KEY_WOW64_64KEY */
82         RegOpenKeyA(HKEY_LOCAL_MACHINE, szCryptography, &hkey);
83     }
84     RegQueryValueExA(hkey, szMachineGuid, NULL, NULL, (LPBYTE)guid, &size);
85     RegCloseKey(hkey);
86
87     lstrcpy(unique, szContainer_md5);
88     lstrcat(unique, "_");
89     lstrcat(unique, guid);
90 }
91
92 static void printBytes(const char *heading, const BYTE *pb, size_t cb)
93 {
94     size_t i;
95     printf("%s: ",heading);
96     for(i=0;i<cb;i++)
97         printf("0x%02x,",pb[i]);
98     putchar('\n');
99 }
100
101 static BOOL (WINAPI *pCryptDuplicateHash) (HCRYPTHASH, DWORD*, DWORD, HCRYPTHASH*);
102
103 /*
104 static void trace_hex(BYTE *pbData, DWORD dwLen) {
105     char szTemp[256];
106     DWORD i, j;
107
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);
113     }
114     for (j=0; i<dwLen; j++,i++) {
115         sprintf(szTemp+6*j, "0x%02x,\n", pbData[i]);
116     }
117     trace(szTemp);
118 }
119 */
120
121 static int init_base_environment(DWORD dwKeyFlags)
122 {
123     HCRYPTKEY hKey;
124     BOOL result;
125         
126     pCryptDuplicateHash = (void *)GetProcAddress(GetModuleHandleA("advapi32.dll"), "CryptDuplicateHash");
127         
128     hProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
129
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());
134     
135     if (!CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, 0))
136     {
137         ok(GetLastError()==NTE_BAD_KEYSET ||
138            broken(GetLastError() == NTE_TEMPORARY_PROFILE /* some Win7 setups */) ||
139            broken(GetLastError() == NTE_KEYSET_NOT_DEF /* Win9x/NT4 */),
140            "%08x\n", GetLastError());
141         if (GetLastError()!=NTE_BAD_KEYSET)
142         {
143             win_skip("RSA full provider not available\n");
144             return 0;
145         }
146         result = CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, 
147                                      CRYPT_NEWKEYSET);
148         ok(result, "%08x\n", GetLastError());
149         if (!result)
150         {
151             win_skip("Couldn't create crypto provider\n");
152             return 0;
153         }
154         result = CryptGenKey(hProv, AT_KEYEXCHANGE, dwKeyFlags, &hKey);
155         ok(result, "%08x\n", GetLastError());
156         if (result) CryptDestroyKey(hKey);
157         result = CryptGenKey(hProv, AT_SIGNATURE, dwKeyFlags, &hKey);
158         ok(result, "%08x\n", GetLastError());
159         if (result) CryptDestroyKey(hKey);
160     }
161     return 1;
162 }
163
164 static void clean_up_base_environment(void)
165 {
166     BOOL result;
167
168     SetLastError(0xdeadbeef);
169     result = CryptReleaseContext(hProv, 1);
170     ok(!result || broken(result) /* Win98 */, "Expected failure\n");
171     ok(GetLastError()==NTE_BAD_FLAGS, "Expected NTE_BAD_FLAGS, got %08x\n", GetLastError());
172         
173     /* Just to prove that Win98 also released the CSP */
174     SetLastError(0xdeadbeef);
175     result = CryptReleaseContext(hProv, 0);
176     ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%08x\n", GetLastError());
177
178     CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
179 }
180
181 static int init_aes_environment(void)
182 {
183     HCRYPTKEY hKey;
184     BOOL result;
185
186     pCryptDuplicateHash = (void *)GetProcAddress(GetModuleHandleA("advapi32.dll"), "CryptDuplicateHash");
187
188     hProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
189
190     /* we are using NULL as provider name for RSA_AES provider as the provider
191      * names are different in Windows XP and Vista. Its different as to what
192      * its defined in the SDK on Windows XP.
193      * This provider is available on Windows XP, Windows 2003 and Vista.      */
194
195     result = CryptAcquireContext(&hProv, szContainer, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
196     if (!result && GetLastError() == NTE_PROV_TYPE_NOT_DEF)
197     {
198         win_skip("RSA_AES provider not supported\n");
199         return 0;
200     }
201     ok(!result && GetLastError()==NTE_BAD_FLAGS, "%d, %08x\n", result, GetLastError());
202
203     if (!CryptAcquireContext(&hProv, szContainer, NULL, PROV_RSA_AES, 0))
204     {
205         ok(GetLastError()==NTE_BAD_KEYSET, "%08x\n", GetLastError());
206         if (GetLastError()!=NTE_BAD_KEYSET) return 0;
207         result = CryptAcquireContext(&hProv, szContainer, NULL, PROV_RSA_AES,
208                                      CRYPT_NEWKEYSET);
209         ok(result, "%08x\n", GetLastError());
210         if (!result) return 0;
211         result = CryptGenKey(hProv, AT_KEYEXCHANGE, 0, &hKey);
212         ok(result, "%08x\n", GetLastError());
213         if (result) CryptDestroyKey(hKey);
214         result = CryptGenKey(hProv, AT_SIGNATURE, 0, &hKey);
215         ok(result, "%08x\n", GetLastError());
216         if (result) CryptDestroyKey(hKey);
217     }
218     return 1;
219 }
220
221 static void clean_up_aes_environment(void)
222 {
223     BOOL result;
224
225     result = CryptReleaseContext(hProv, 1);
226     ok(!result && GetLastError()==NTE_BAD_FLAGS, "%08x\n", GetLastError());
227
228     CryptAcquireContext(&hProv, szContainer, NULL, PROV_RSA_AES, CRYPT_DELETEKEYSET);
229 }
230
231 static void test_prov(void) 
232 {
233     BOOL result;
234     DWORD dwLen, dwInc;
235     
236     dwLen = (DWORD)sizeof(DWORD);
237     SetLastError(0xdeadbeef);
238     result = CryptGetProvParam(hProv, PP_SIG_KEYSIZE_INC, (BYTE*)&dwInc, &dwLen, 0);
239     if (!result && GetLastError() == NTE_BAD_TYPE)
240         skip("PP_SIG_KEYSIZE_INC is not supported (win9x or NT)\n");
241     else
242         ok(result && dwInc==8, "%08x, %d\n", GetLastError(), dwInc);
243     
244     dwLen = (DWORD)sizeof(DWORD);
245     SetLastError(0xdeadbeef);
246     result = CryptGetProvParam(hProv, PP_KEYX_KEYSIZE_INC, (BYTE*)&dwInc, &dwLen, 0);
247     if (!result && GetLastError() == NTE_BAD_TYPE)
248         skip("PP_KEYX_KEYSIZE_INC is not supported (win9x or NT)\n");
249     else
250         ok(result && dwInc==8, "%08x, %d\n", GetLastError(), dwInc);
251 }
252
253 static void test_gen_random(void)
254 {
255     BOOL result;
256     BYTE rnd1[16], rnd2[16];
257
258     memset(rnd1, 0, sizeof(rnd1));
259     memset(rnd2, 0, sizeof(rnd2));
260
261     result = CryptGenRandom(hProv, sizeof(rnd1), rnd1);
262     if (!result && GetLastError() == NTE_FAIL) {
263         /* rsaenh compiled without OpenSSL */
264         return;
265     }
266     
267     ok(result, "%08x\n", GetLastError());
268
269     result = CryptGenRandom(hProv, sizeof(rnd2), rnd2);
270     ok(result, "%08x\n", GetLastError());
271
272     ok(memcmp(rnd1, rnd2, sizeof(rnd1)), "CryptGenRandom generates non random data\n");
273 }
274
275 static BOOL derive_key(ALG_ID aiAlgid, HCRYPTKEY *phKey, DWORD len) 
276 {
277     HCRYPTHASH hHash;
278     BOOL result;
279     unsigned char pbData[2000];
280     int i;
281
282     *phKey = 0;
283     for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
284     result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
285     if (!result) {
286         /* rsaenh compiled without OpenSSL */
287         ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
288         return FALSE;
289     } 
290     ok(result, "%08x\n", GetLastError());
291     result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
292     ok(result, "%08x\n", GetLastError());
293     if (!result) return FALSE;
294     result = CryptDeriveKey(hProv, aiAlgid, hHash, (len << 16) | CRYPT_EXPORTABLE, phKey);
295     ok(result, "%08x\n", GetLastError());
296     if (!result) return FALSE;
297     len = 2000;
298     result = CryptGetHashParam(hHash, HP_HASHVAL, pbData, &len, 0);
299     ok(result, "%08x\n", GetLastError());
300     CryptDestroyHash(hHash);
301     return TRUE;
302 }
303
304 static BYTE abPlainPrivateKey[596] = {
305     0x07, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
306     0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
307     0x01, 0x00, 0x01, 0x00, 0x9b, 0x64, 0xef, 0xce,
308     0x31, 0x7c, 0xad, 0x56, 0xe2, 0x1e, 0x9b, 0x96,
309     0xb3, 0xf0, 0x29, 0x88, 0x6e, 0xa8, 0xc2, 0x11,
310     0x33, 0xd6, 0xcc, 0x8c, 0x69, 0xb2, 0x1a, 0xfd,
311     0xfc, 0x23, 0x21, 0x30, 0x4d, 0x29, 0x45, 0xb6,
312     0x3a, 0x67, 0x11, 0x80, 0x1a, 0x91, 0xf2, 0x9f,
313     0x01, 0xac, 0xc0, 0x11, 0x50, 0x5f, 0xcd, 0xb9,
314     0xad, 0x76, 0x9f, 0x6e, 0x91, 0x55, 0x71, 0xda,
315     0x97, 0x96, 0x96, 0x22, 0x75, 0xb4, 0x83, 0x44,
316     0x89, 0x9e, 0xf8, 0x44, 0x40, 0x7c, 0xd6, 0xcd,
317     0x9d, 0x88, 0xd6, 0x88, 0xbc, 0x56, 0xb7, 0x64,
318     0xe9, 0x2c, 0x24, 0x2f, 0x0d, 0x78, 0x55, 0x1c,
319     0xb2, 0x67, 0xb1, 0x5e, 0xbc, 0x0c, 0xcf, 0x1c,
320     0xe9, 0xd3, 0x9e, 0xa2, 0x15, 0x24, 0x73, 0xd6,
321     0xdb, 0x6f, 0x83, 0xb2, 0xf8, 0xbc, 0xe7, 0x47,
322     0x3b, 0x01, 0xef, 0x49, 0x08, 0x98, 0xd6, 0xa3,
323     0xf9, 0x25, 0x57, 0xe9, 0x39, 0x3c, 0x53, 0x30,
324     0x1b, 0xf2, 0xc9, 0x62, 0x31, 0x43, 0x5d, 0x84,
325     0x24, 0x30, 0x21, 0x9a, 0xad, 0xdb, 0x62, 0x91,
326     0xc8, 0x07, 0xd9, 0x2f, 0xd6, 0xb5, 0x37, 0x6f,
327     0xfe, 0x7a, 0x12, 0xbc, 0xd9, 0xd2, 0x2b, 0xbf,
328     0xd7, 0xb1, 0xfa, 0x7d, 0xc0, 0x48, 0xdd, 0x74,
329     0xdd, 0x55, 0x04, 0xa1, 0x8b, 0xc1, 0x0a, 0xc4,
330     0xa5, 0x57, 0x62, 0xee, 0x08, 0x8b, 0xf9, 0x19,
331     0x6c, 0x52, 0x06, 0xf8, 0x73, 0x0f, 0x24, 0xc9,
332     0x71, 0x9f, 0xc5, 0x45, 0x17, 0x3e, 0xae, 0x06,
333     0x81, 0xa2, 0x96, 0x40, 0x06, 0xbf, 0xeb, 0x9e,
334     0x80, 0x2b, 0x27, 0x20, 0x8f, 0x38, 0xcf, 0xeb,
335     0xff, 0x3b, 0x38, 0x41, 0x35, 0x69, 0x66, 0x13,
336     0x1d, 0x3c, 0x01, 0x3b, 0xf6, 0x37, 0xca, 0x9c,
337     0x61, 0x74, 0x98, 0xcf, 0xc9, 0x6e, 0xe8, 0x90,
338     0xc7, 0xb7, 0x33, 0xc0, 0x07, 0x3c, 0xf8, 0xc8,
339     0xf6, 0xf2, 0xd7, 0xf0, 0x21, 0x62, 0x58, 0x8a,
340     0x55, 0xbf, 0xa1, 0x2d, 0x3d, 0xa6, 0x69, 0xc5,
341     0x02, 0x19, 0x31, 0xf0, 0x94, 0x0f, 0x45, 0x5c,
342     0x95, 0x1b, 0x53, 0xbc, 0xf5, 0xb0, 0x1a, 0x8f,
343     0xbf, 0x40, 0xe0, 0xc7, 0x73, 0xe7, 0x72, 0x6e,
344     0xeb, 0xb1, 0x0f, 0x38, 0xc5, 0xf8, 0xee, 0x04,
345     0xed, 0x34, 0x1a, 0x10, 0xf9, 0x53, 0x34, 0xf3,
346     0x3e, 0xe6, 0x5c, 0xd1, 0x47, 0x65, 0xcd, 0xbd,
347     0xf1, 0x06, 0xcb, 0xb4, 0xb1, 0x26, 0x39, 0x9f,
348     0x71, 0xfe, 0x3d, 0xf8, 0x62, 0xab, 0x22, 0x8b,
349     0x0e, 0xdc, 0xb9, 0xe8, 0x74, 0x06, 0xfc, 0x8c,
350     0x25, 0xa1, 0xa9, 0xcf, 0x07, 0xf9, 0xac, 0x21,
351     0x01, 0x7b, 0x1c, 0xdc, 0x94, 0xbd, 0x47, 0xe1,
352     0xa0, 0x86, 0x59, 0x35, 0x6a, 0x6f, 0xb9, 0x70,
353     0x26, 0x7c, 0x3c, 0xfd, 0xbd, 0x81, 0x39, 0x36,
354     0x42, 0xc2, 0xbd, 0xbe, 0x84, 0x27, 0x9a, 0x69,
355     0x81, 0xda, 0x99, 0x27, 0xc2, 0x4f, 0x62, 0x33,
356     0xf4, 0x79, 0x30, 0xc5, 0x63, 0x54, 0x71, 0xf1,
357     0x47, 0x22, 0x25, 0x9b, 0x6c, 0x00, 0x2f, 0x1c,
358     0xf4, 0x1f, 0x85, 0xbc, 0xf6, 0x67, 0x6a, 0xe3,
359     0xf6, 0x55, 0x8a, 0xef, 0xd0, 0x0b, 0xd3, 0xa2,
360     0xc5, 0x51, 0x70, 0x15, 0x0a, 0xf0, 0x98, 0x4c,
361     0xb7, 0x19, 0x62, 0x0e, 0x2d, 0x2a, 0x4a, 0x7d,
362     0x7a, 0x0a, 0xc4, 0x17, 0xe3, 0x5d, 0x20, 0x52,
363     0xa9, 0x98, 0xc3, 0xaa, 0x11, 0xf6, 0xbf, 0x4c,
364     0x94, 0x99, 0x81, 0x89, 0xf0, 0x7f, 0x66, 0xaa,
365     0xc8, 0x88, 0xd7, 0x31, 0x84, 0x71, 0xb6, 0x64,
366     0x09, 0x76, 0x0b, 0x7f, 0x1a, 0x1f, 0x2e, 0xfe,
367     0xcd, 0x59, 0x2a, 0x54, 0x11, 0x84, 0xd4, 0x6a,
368     0x61, 0xdf, 0xaa, 0x76, 0x66, 0x9d, 0x82, 0x11,
369     0x56, 0x3d, 0xd2, 0x52, 0xe6, 0x42, 0x5a, 0x77,
370     0x92, 0x98, 0x34, 0xf3, 0x56, 0x6c, 0x96, 0x10,
371     0x40, 0x59, 0x16, 0xcb, 0x77, 0x61, 0xe3, 0xbf,
372     0x4b, 0xd4, 0x39, 0xfb, 0xb1, 0x4e, 0xc1, 0x74,
373     0xec, 0x7a, 0xea, 0x3d, 0x68, 0xbb, 0x0b, 0xe6,
374     0xc6, 0x06, 0xbf, 0xdd, 0x7f, 0x94, 0x42, 0xc0,
375     0x0f, 0xe4, 0x92, 0x33, 0x6c, 0x6e, 0x1b, 0xba,
376     0x73, 0xf9, 0x79, 0x84, 0xdf, 0x45, 0x00, 0xe4,
377     0x94, 0x88, 0x9d, 0x08, 0x89, 0xcf, 0xf2, 0xa4,
378     0xc5, 0x47, 0x45, 0x85, 0x86, 0xa5, 0xcc, 0xa8,
379     0xf2, 0x5d, 0x58, 0x07
380 };
381
382 static void test_hashes(void)
383 {
384     static const unsigned char md2hash[16] = {
385         0x12, 0xcb, 0x1b, 0x08, 0xc8, 0x48, 0xa4, 0xa9, 
386         0xaa, 0xf3, 0xf1, 0x9f, 0xfc, 0x29, 0x28, 0x68 };
387     static const unsigned char md4hash[16] = {
388         0x8e, 0x2a, 0x58, 0xbf, 0xf2, 0xf5, 0x26, 0x23, 
389         0x79, 0xd2, 0x92, 0x36, 0x1b, 0x23, 0xe3, 0x81 };
390     static const unsigned char empty_md5hash[16] = {
391         0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
392         0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e };
393     static const unsigned char md5hash[16] = { 
394         0x15, 0x76, 0xa9, 0x4d, 0x6c, 0xb3, 0x34, 0xdd, 
395         0x12, 0x6c, 0xb1, 0xc2, 0x7f, 0x19, 0xe0, 0xf2 };    
396     static const unsigned char sha1hash[20] = { 
397         0xf1, 0x0c, 0xcf, 0xde, 0x60, 0xc1, 0x7d, 0xb2, 0x6e, 0x7d, 
398         0x85, 0xd3, 0x56, 0x65, 0xc7, 0x66, 0x1d, 0xbb, 0xeb, 0x2c };
399     static const unsigned char signed_ssl3_shamd5_hash[] = {
400         0x4f,0xcc,0x2f,0x33,0x44,0x60,0x76,0x16,0x13,0xc8,0xff,0xd4,0x59,0x19,
401         0xde,0x85,0x44,0x72,0x47,0x98,0x01,0xfb,0x67,0x5c,0x5b,0x35,0x15,0x0f,
402         0x91,0xda,0xc7,0x7c,0xfb,0xe2,0x18,0xef,0xac,0x31,0x40,0x7b,0xa9,0x83,
403         0xdb,0x30,0xcd,0x94,0x4b,0x8e,0x3b,0x6c,0x7a,0x86,0x59,0xf0,0xd1,0xd2,
404         0x5e,0xce,0xd4,0x1b,0x7f,0xed,0x24,0xee,0x53,0x5c,0x15,0x97,0x21,0x7c,
405         0x5c,0xea,0xab,0xf5,0xd6,0x4b,0xb3,0xbb,0x14,0xf5,0x59,0x9e,0x21,0x90,
406         0x21,0x99,0x19,0xad,0xa2,0xa6,0xea,0x61,0xc1,0x41,0xe2,0x70,0x77,0xf7,
407         0x15,0x68,0x96,0x1e,0x5c,0x84,0x97,0xe3,0x5c,0xd2,0xd9,0xfb,0x87,0x6f,
408         0x11,0x21,0x82,0x43,0x76,0x32,0xa4,0x38,0x7b,0x85,0x22,0x30,0x1e,0x55,
409         0x79,0x93 };
410     unsigned char pbData[2048];
411     BOOL result;
412     HCRYPTHASH hHash, hHashClone;
413     HCRYPTPROV prov;
414     BYTE pbHashValue[36];
415     BYTE pbSigValue[128];
416     HCRYPTKEY hKeyExchangeKey;
417     DWORD hashlen, len, error;
418     int i;
419
420     for (i=0; i<2048; i++) pbData[i] = (unsigned char)i;
421
422     /* MD2 Hashing */
423     result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
424     if (!result) {
425         /* rsaenh compiled without OpenSSL */
426         ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
427     } else {
428         result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
429         ok(result, "%08x\n", GetLastError());
430
431         len = sizeof(DWORD);
432         result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
433            ok(result && (hashlen == 16), "%08x, hashlen: %d\n", GetLastError(), hashlen);
434
435         len = 16;
436         result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
437         ok(result, "%08x\n", GetLastError());
438
439         ok(!memcmp(pbHashValue, md2hash, 16), "Wrong MD2 hash!\n");
440
441         result = CryptDestroyHash(hHash);
442         ok(result, "%08x\n", GetLastError());
443     } 
444
445     /* MD4 Hashing */
446     result = CryptCreateHash(hProv, CALG_MD4, 0, 0, &hHash);
447     ok(result, "%08x\n", GetLastError());
448
449     result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
450     ok(result, "%08x\n", GetLastError());
451
452     len = sizeof(DWORD);
453     result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
454     ok(result && (hashlen == 16), "%08x, hashlen: %d\n", GetLastError(), hashlen);
455
456     len = 16;
457     result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
458     ok(result, "%08x\n", GetLastError());
459
460     ok(!memcmp(pbHashValue, md4hash, 16), "Wrong MD4 hash!\n");
461
462     result = CryptDestroyHash(hHash);
463     ok(result, "%08x\n", GetLastError());
464
465     /* MD5 Hashing */
466     result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
467     ok(result, "%08x\n", GetLastError());
468
469     len = sizeof(DWORD);
470     result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
471     ok(result && (hashlen == 16), "%08x, hashlen: %d\n", GetLastError(), hashlen);
472
473     result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
474     ok(result, "%08x\n", GetLastError());
475
476     len = 16;
477     result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
478     ok(result, "%08x\n", GetLastError());
479
480     ok(!memcmp(pbHashValue, md5hash, 16), "Wrong MD5 hash!\n");
481
482     result = CryptDestroyHash(hHash);
483     ok(result, "%08x\n", GetLastError());
484
485     result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
486     ok(result, "%08x\n", GetLastError());
487
488     /* The hash is available even if CryptHashData hasn't been called */
489     len = 16;
490     result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
491     ok(result, "%08x\n", GetLastError());
492
493     ok(!memcmp(pbHashValue, empty_md5hash, 16), "Wrong MD5 hash!\n");
494
495     /* It's also stable:  getting it twice results in the same value */
496     result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
497     ok(result, "%08x\n", GetLastError());
498
499     ok(!memcmp(pbHashValue, empty_md5hash, 16), "Wrong MD5 hash!\n");
500
501     /* Can't add data after the hash been retrieved */
502     SetLastError(0xdeadbeef);
503     result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
504     ok(!result, "Expected failure\n");
505     ok(GetLastError() == NTE_BAD_HASH_STATE ||
506        GetLastError() == NTE_BAD_ALGID, /* Win9x, WinMe, NT4 */
507        "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID, got %08x\n", GetLastError());
508
509     /* You can still retrieve the hash, its value just hasn't changed */
510     result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
511     ok(result, "%08x\n", GetLastError());
512
513     ok(!memcmp(pbHashValue, empty_md5hash, 16), "Wrong MD5 hash!\n");
514
515     result = CryptDestroyHash(hHash);
516     ok(result, "%08x\n", GetLastError());
517
518     /* SHA1 Hashing */
519     result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
520     ok(result, "%08x\n", GetLastError());
521
522     result = CryptHashData(hHash, pbData, 5, 0);
523     ok(result, "%08x\n", GetLastError());
524
525     if(pCryptDuplicateHash) {
526         result = pCryptDuplicateHash(hHash, 0, 0, &hHashClone);
527         ok(result, "%08x\n", GetLastError());
528
529         result = CryptHashData(hHashClone, (BYTE*)pbData+5, sizeof(pbData)-5, 0);
530         ok(result, "%08x\n", GetLastError());
531
532         len = sizeof(DWORD);
533         result = CryptGetHashParam(hHashClone, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
534         ok(result && (hashlen == 20), "%08x, hashlen: %d\n", GetLastError(), hashlen);
535
536         len = 20;
537         result = CryptGetHashParam(hHashClone, HP_HASHVAL, pbHashValue, &len, 0);
538         ok(result, "%08x\n", GetLastError());
539
540         ok(!memcmp(pbHashValue, sha1hash, 20), "Wrong SHA1 hash!\n");
541
542         result = CryptDestroyHash(hHashClone);
543         ok(result, "%08x\n", GetLastError());
544     }
545
546     result = CryptDestroyHash(hHash);
547     ok(result, "%08x\n", GetLastError());
548
549     /* The SHA-2 variants aren't supported in the RSA full provider */
550     result = CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash);
551     ok(!result && GetLastError() == NTE_BAD_ALGID,
552        "expected NTE_BAD_ALGID, got %08x\n", GetLastError());
553     result = CryptCreateHash(hProv, CALG_SHA_384, 0, 0, &hHash);
554     ok(!result && GetLastError() == NTE_BAD_ALGID,
555        "expected NTE_BAD_ALGID, got %08x\n", GetLastError());
556     result = CryptCreateHash(hProv, CALG_SHA_512, 0, 0, &hHash);
557     ok(!result && GetLastError() == NTE_BAD_ALGID,
558        "expected NTE_BAD_ALGID, got %08x\n", GetLastError());
559
560     result = CryptAcquireContextA(&prov, NULL, szProvider, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
561     ok(result, "CryptAcquireContext failed 0x%08x\n", GetLastError());
562
563     result = CryptCreateHash(prov, CALG_SHA1, 0, 0, &hHash);
564     ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());
565
566     /* release provider before using the hash */
567     result = CryptReleaseContext(prov, 0);
568     ok(result, "CryptReleaseContext failed 0x%08x\n", GetLastError());
569
570     SetLastError(0xdeadbeef);
571     result = CryptHashData(hHash, (const BYTE *)"data", sizeof("data"), 0);
572     error = GetLastError();
573     ok(!result, "CryptHashData succeeded\n");
574     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);
575
576     SetLastError(0xdeadbeef);
577     result = CryptDestroyHash(hHash);
578     error = GetLastError();
579     ok(!result, "CryptDestroyHash succeeded\n");
580     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);
581
582     if (!pCryptDuplicateHash)
583     {
584         win_skip("CryptDuplicateHash is not available\n");
585         return;
586     }
587
588     result = CryptAcquireContextA(&prov, NULL, szProvider, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
589     ok(result, "CryptAcquireContext failed 0x%08x\n", GetLastError());
590
591     result = CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash);
592     ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());
593
594     result = CryptHashData(hHash, (const BYTE *)"data", sizeof("data"), 0);
595     ok(result, "CryptHashData failed 0x%08x\n", GetLastError());
596
597     result = pCryptDuplicateHash(hHash, NULL, 0, &hHashClone);
598     ok(result, "CryptDuplicateHash failed 0x%08x\n", GetLastError());
599
600     len = 20;
601     result = CryptGetHashParam(hHashClone, HP_HASHVAL, pbHashValue, &len, 0);
602     ok(result, "CryptGetHashParam failed 0x%08x\n", GetLastError());
603
604     /* add data after duplicating the hash */
605     result = CryptHashData(hHash, (const BYTE *)"more data", sizeof("more data"), 0);
606     ok(result, "CryptHashData failed 0x%08x\n", GetLastError());
607
608     result = CryptDestroyHash(hHash);
609     ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());
610
611     result = CryptDestroyHash(hHashClone);
612     ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());
613
614     result = CryptReleaseContext(prov, 0);
615     ok(result, "CryptReleaseContext failed 0x%08x\n", GetLastError());
616
617     /* Test CALG_SSL3_SHAMD5 */
618     result = CryptAcquireContextA(&prov, NULL, szProvider, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
619     ok(result, "CryptAcquireContext failed 0x%08x\n", GetLastError());
620
621     /* Step 1: create an MD5 hash of the data */
622     result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
623     ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());
624     result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
625     ok(result, "%08x\n", GetLastError());
626     len = 16;
627     result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
628     ok(result, "CryptGetHashParam failed 0x%08x\n", GetLastError());
629     result = CryptDestroyHash(hHash);
630     ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());
631     /* Step 2: create a SHA1 hash of the data */
632     result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
633     ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());
634     result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
635     ok(result, "%08x\n", GetLastError());
636     len = 20;
637     result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue + 16, &len, 0);
638     ok(result, "CryptGetHashParam failed 0x%08x\n", GetLastError());
639     result = CryptDestroyHash(hHash);
640     ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());
641     /* Step 3: create a CALG_SSL3_SHAMD5 hash handle */
642     result = CryptCreateHash(hProv, CALG_SSL3_SHAMD5, 0, 0, &hHash);
643     ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());
644     /* Test that CryptHashData fails on this hash */
645     result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
646     ok(!result && GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
647     result = CryptSetHashParam(hHash, HP_HASHVAL, pbHashValue, 0);
648     ok(result, "%08x\n", GetLastError());
649     len = (DWORD)sizeof(abPlainPrivateKey);
650     result = CryptImportKey(hProv, abPlainPrivateKey, len, 0, 0, &hKeyExchangeKey);
651     ok(result, "%08x\n", GetLastError());
652     len = 0;
653     result = CryptSignHash(hHash, AT_KEYEXCHANGE, NULL, 0, NULL, &len);
654     ok(result, "%08x\n", GetLastError());
655     ok(len == 128, "expected len 128, got %d\n", len);
656     result = CryptSignHash(hHash, AT_KEYEXCHANGE, NULL, 0, pbSigValue, &len);
657     ok(result, "%08x\n", GetLastError());
658     ok(!memcmp(pbSigValue, signed_ssl3_shamd5_hash, len), "unexpected value\n");
659     if (len != 128 || memcmp(pbSigValue, signed_ssl3_shamd5_hash, len))
660     {
661         printBytes("expected", signed_ssl3_shamd5_hash,
662                    sizeof(signed_ssl3_shamd5_hash));
663         printBytes("got", pbSigValue, len);
664     }
665     result = CryptDestroyKey(hKeyExchangeKey);
666     ok(result, "CryptDestroyKey failed 0x%08x\n", GetLastError());
667     result = CryptDestroyHash(hHash);
668     ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());
669     result = CryptReleaseContext(prov, 0);
670     ok(result, "CryptReleaseContext failed 0x%08x\n", GetLastError());
671 }
672
673 static void test_block_cipher_modes(void)
674 {
675     static const BYTE plain[23] = { 
676         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 
677         0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
678     static const BYTE ecb[24] = {   
679         0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11, 0xf2, 0xb2, 0x5d, 0x5f, 
680         0x08, 0xff, 0x49, 0xa4, 0x45, 0x3a, 0x68, 0x14, 0xca, 0x18, 0xe5, 0xf4 };
681     static const BYTE cbc[24] = {   
682         0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11, 0x10, 0xf5, 0xda, 0x61,
683         0x4e, 0x3d, 0xab, 0xc0, 0x97, 0x85, 0x01, 0x12, 0x97, 0xa4, 0xf7, 0xd3 };
684     static const BYTE cfb[24] = {   
685         0x29, 0xb5, 0x67, 0x85, 0x0b, 0x1b, 0xec, 0x07, 0x67, 0x2d, 0xa1, 0xa4,
686         0x1a, 0x47, 0x24, 0x6a, 0x54, 0xe1, 0xe0, 0x92, 0xf9, 0x0e, 0xf6, 0xeb };
687     HCRYPTKEY hKey;
688     BOOL result;
689     BYTE abData[24];
690     DWORD dwMode, dwLen;
691
692     result = derive_key(CALG_RC2, &hKey, 40);
693     if (!result) return;
694
695     memcpy(abData, plain, sizeof(plain));
696
697     dwMode = CRYPT_MODE_ECB;
698     result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
699     ok(result, "%08x\n", GetLastError());
700
701     result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
702     ok(result, "%08x\n", GetLastError());
703     ok(dwLen == 11 || broken(dwLen == 0 /* Win9x/NT4 */), "unexpected salt length %d\n", dwLen);
704
705     dwLen = 23;
706     result = CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwLen, 24);
707     ok(result, "CryptEncrypt failed: %08x\n", GetLastError());
708     ok(dwLen == 24, "Unexpected length %d\n", dwLen);
709
710     SetLastError(ERROR_SUCCESS);
711     dwLen = 23;
712     result = CryptEncrypt(hKey, 0, TRUE, 0, abData, &dwLen, 24);
713     ok(result && dwLen == 24 && !memcmp(ecb, abData, sizeof(ecb)), 
714        "%08x, dwLen: %d\n", GetLastError(), dwLen);
715
716     result = CryptDecrypt(hKey, 0, TRUE, 0, abData, &dwLen);
717     ok(result && dwLen == 23 && !memcmp(plain, abData, sizeof(plain)), 
718        "%08x, dwLen: %d\n", GetLastError(), dwLen);
719
720     dwMode = CRYPT_MODE_CBC;
721     result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
722     ok(result, "%08x\n", GetLastError());
723     
724     dwLen = 23;
725     result = CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwLen, 24);
726     ok(result, "CryptEncrypt failed: %08x\n", GetLastError());
727     ok(dwLen == 24, "Unexpected length %d\n", dwLen);
728
729     dwLen = 23;
730     result = CryptEncrypt(hKey, 0, TRUE, 0, abData, &dwLen, 24);
731     ok(result && dwLen == 24 && !memcmp(cbc, abData, sizeof(cbc)), 
732        "%08x, dwLen: %d\n", GetLastError(), dwLen);
733
734     result = CryptDecrypt(hKey, 0, TRUE, 0, abData, &dwLen);
735     ok(result && dwLen == 23 && !memcmp(plain, abData, sizeof(plain)), 
736        "%08x, dwLen: %d\n", GetLastError(), dwLen);
737
738     dwMode = CRYPT_MODE_CFB;
739     result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
740     ok(result, "%08x\n", GetLastError());
741     
742     dwLen = 16;
743     result = CryptEncrypt(hKey, 0, FALSE, 0, abData, &dwLen, 24);
744     ok(result && dwLen == 16, "%08x, dwLen: %d\n", GetLastError(), dwLen);
745
746     dwLen = 7;
747     result = CryptEncrypt(hKey, 0, TRUE, 0, abData+16, &dwLen, 8);
748     ok(result && dwLen == 8 && !memcmp(cfb, abData, sizeof(cfb)), 
749        "%08x, dwLen: %d\n", GetLastError(), dwLen);
750     
751     dwLen = 8;
752     result = CryptDecrypt(hKey, 0, FALSE, 0, abData, &dwLen);
753     ok(result && dwLen == 8, "%08x, dwLen: %d\n", GetLastError(), dwLen);
754
755     dwLen = 16;
756     result = CryptDecrypt(hKey, 0, TRUE, 0, abData+8, &dwLen);
757     ok(result && dwLen == 15 && !memcmp(plain, abData, sizeof(plain)), 
758        "%08x, dwLen: %d\n", GetLastError(), dwLen);
759
760     dwMode = CRYPT_MODE_OFB;
761     result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
762     ok(result, "%08x\n", GetLastError());
763     
764     dwLen = 23;
765     result = CryptEncrypt(hKey, 0, TRUE, 0, abData, &dwLen, 24);
766     ok(!result && GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
767
768     CryptDestroyKey(hKey);
769 }
770
771 static void test_3des112(void)
772 {
773     HCRYPTKEY hKey;
774     BOOL result;
775     DWORD dwLen;
776     unsigned char pbData[16];
777     int i;
778
779     result = derive_key(CALG_3DES_112, &hKey, 0);
780     if (!result) {
781         /* rsaenh compiled without OpenSSL */
782         ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
783         return;
784     }
785
786     for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
787     
788     dwLen = 13;
789     result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
790     ok(result, "%08x\n", GetLastError());
791     
792     result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
793     ok(result, "%08x\n", GetLastError());
794
795     for (i=0; i<4; i++)
796     {
797       memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);
798
799       dwLen = cTestData[i].enclen;
800       result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
801       ok(result, "%08x\n", GetLastError());
802       ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
803
804       result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
805       ok(result, "%08x\n", GetLastError());
806       ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
807       ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
808       if((dwLen != cTestData[i].enclen) ||
809          memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
810       {
811           printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
812           printBytes("got",pbData,dwLen);
813       }
814     }
815     result = CryptDestroyKey(hKey);
816     ok(result, "%08x\n", GetLastError());
817 }
818
819 static void test_des(void) 
820 {
821     HCRYPTKEY hKey;
822     BOOL result;
823     DWORD dwLen, dwMode;
824     unsigned char pbData[16];
825     int i;
826
827     result = derive_key(CALG_DES, &hKey, 56);
828     if (!result) {
829         /* rsaenh compiled without OpenSSL */
830         ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
831         return;
832     }
833
834     dwMode = CRYPT_MODE_ECB;
835     result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
836     ok(result, "%08x\n", GetLastError());
837     
838     dwLen = sizeof(DWORD);
839     result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
840     ok(result, "%08x\n", GetLastError());
841     
842     for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
843     
844     dwLen = 13;
845     result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
846     ok(result, "%08x\n", GetLastError());
847     
848     result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
849     ok(result, "%08x\n", GetLastError());
850
851     for (i=0; i<4; i++)
852     {
853       memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);
854
855       dwLen = cTestData[i].enclen;
856       result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
857       ok(result, "%08x\n", GetLastError());
858       ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
859
860       result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
861       ok(result, "%08x\n", GetLastError());
862       ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
863       ok(memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen)==0,"decryption incorrect %d\n",i);
864       if((dwLen != cTestData[i].enclen) ||
865          memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
866       {
867           printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
868           printBytes("got",pbData,dwLen);
869       }
870     }
871
872     result = CryptDestroyKey(hKey);
873     ok(result, "%08x\n", GetLastError());
874 }
875
876 static void test_3des(void)
877 {
878     HCRYPTKEY hKey;
879     BOOL result;
880     DWORD dwLen;
881     unsigned char pbData[16];
882     static const BYTE des3[16] = { 
883         0x7b, 0xba, 0xdd, 0xa2, 0x39, 0xd3, 0x7b, 0xb3, 
884         0xc7, 0x51, 0x81, 0x41, 0x53, 0xe8, 0xcf, 0xeb };
885     int i;
886
887     result = derive_key(CALG_3DES, &hKey, 0);
888     if (!result) return;
889
890     for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
891     
892     dwLen = 13;
893     result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
894     ok(result, "%08x\n", GetLastError());
895
896     ok(!memcmp(pbData, des3, sizeof(des3)), "3DES encryption failed!\n");
897
898     result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
899     ok(result, "%08x\n", GetLastError());
900
901     for (i=0; i<4; i++)
902     {
903       memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);
904
905       dwLen = cTestData[i].enclen;
906       result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
907       ok(result, "%08x\n", GetLastError());
908       ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
909
910       result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
911       ok(result, "%08x\n", GetLastError());
912       ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
913       ok(memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen)==0,"decryption incorrect %d\n",i);
914       if((dwLen != cTestData[i].enclen) ||
915          memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
916       {
917           printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
918           printBytes("got",pbData,dwLen);
919       }
920     }
921     result = CryptDestroyKey(hKey);
922     ok(result, "%08x\n", GetLastError());
923 }
924
925 static void test_aes(int keylen)
926 {
927     HCRYPTKEY hKey;
928     BOOL result;
929     DWORD dwLen;
930     unsigned char pbData[16];
931     int i;
932
933     switch (keylen)
934     {
935         case 256:
936             result = derive_key(CALG_AES_256, &hKey, 0);
937             break;
938         case 192:
939             result = derive_key(CALG_AES_192, &hKey, 0);
940             break;
941         default:
942         case 128:
943             result = derive_key(CALG_AES_128, &hKey, 0);
944             break;
945     }
946     if (!result) return;
947
948     for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
949
950     /* Does AES provider support salt? */
951     result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
952     ok((!result && GetLastError() == NTE_BAD_KEY) || result /* Win7 */,
953        "expected NTE_BAD_KEY, got %08x\n", GetLastError());
954     if (result)
955         ok(!dwLen, "unexpected salt length %d\n", dwLen);
956
957     dwLen = 13;
958     result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
959     ok(result, "%08x\n", GetLastError());
960
961     result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
962     ok(result, "%08x\n", GetLastError());
963
964     for (i=0; i<4; i++)
965     {
966       memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);
967
968       dwLen = cTestData[i].enclen;
969       result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
970       ok(result, "%08x\n", GetLastError());
971       ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
972
973       result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
974       ok(result, "%08x\n", GetLastError());
975       ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
976       ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
977       if((dwLen != cTestData[i].enclen) ||
978          memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
979       {
980           printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
981           printBytes("got",pbData,dwLen);
982       }
983     }
984     result = CryptDestroyKey(hKey);
985     ok(result, "%08x\n", GetLastError());
986 }
987
988 static void test_sha2(void)
989 {
990     static const unsigned char sha256hash[32] = {
991         0x10, 0xfc, 0x3c, 0x51, 0xa1, 0x52, 0xe9, 0x0e, 0x5b, 0x90,
992         0x31, 0x9b, 0x60, 0x1d, 0x92, 0xcc, 0xf3, 0x72, 0x90, 0xef,
993         0x53, 0xc3, 0x5f, 0xf9, 0x25, 0x07, 0x68, 0x7d, 0x8a, 0x91,
994         0x1a, 0x08
995     };
996     static const unsigned char sha384hash[48] = {
997         0x98, 0xd3, 0x3f, 0x89, 0x0b, 0x23, 0x33, 0x44, 0x61, 0x32,
998         0x5a, 0x7c, 0xa3, 0x03, 0x89, 0xb5, 0x11, 0xd7, 0x41, 0xc8,
999         0x54, 0x6b, 0x12, 0x0c, 0x40, 0x15, 0xb6, 0x2a, 0x03, 0x43,
1000         0xe5, 0x64, 0x7f, 0x10, 0x1e, 0xae, 0x47, 0xa9, 0x39, 0x05,
1001         0x6f, 0x40, 0x60, 0x94, 0xd6, 0xad, 0x80, 0x55
1002     };
1003     static const unsigned char sha512hash[64] = {
1004         0x37, 0x86, 0x0e, 0x7d, 0x25, 0xd9, 0xf9, 0x84, 0x3e, 0x3d,
1005         0xc7, 0x13, 0x95, 0x73, 0x42, 0x04, 0xfd, 0x13, 0xad, 0x23,
1006         0x39, 0x16, 0x32, 0x5f, 0x99, 0x3e, 0x3c, 0xee, 0x3f, 0x11,
1007         0x36, 0xf9, 0xc9, 0x66, 0x08, 0x70, 0xcc, 0x49, 0xd8, 0xe0,
1008         0x7d, 0xa1, 0x57, 0x62, 0x71, 0xa6, 0xc9, 0xa4, 0x24, 0x60,
1009         0xfc, 0xde, 0x9d, 0xb2, 0xf1, 0xd2, 0xc2, 0xfb, 0x2d, 0xbf,
1010         0xb7, 0xf4, 0x81, 0xd4
1011     };
1012     unsigned char pbData[2048];
1013     BOOL result;
1014     HCRYPTHASH hHash;
1015     BYTE pbHashValue[64];
1016     DWORD hashlen, len;
1017     int i;
1018
1019     for (i=0; i<2048; i++) pbData[i] = (unsigned char)i;
1020
1021     /* SHA-256 hash */
1022     SetLastError(0xdeadbeef);
1023     result = CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash);
1024     if (!result && GetLastError() == NTE_BAD_ALGID) {
1025         win_skip("SHA-256/384/512 hashes are not supported before Windows XP SP3\n");
1026         return;
1027     }
1028     ok(result, "%08x\n", GetLastError());
1029     if (result) {
1030         len = sizeof(DWORD);
1031         result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
1032         ok(result && (hashlen == 32), "%08x, hashlen: %d\n", GetLastError(), hashlen);
1033
1034         result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1035         ok(result, "%08x\n", GetLastError());
1036
1037         len = 32;
1038         result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
1039         ok(result, "%08x\n", GetLastError());
1040
1041         ok(!memcmp(pbHashValue, sha256hash, 32), "Wrong SHA-256 hash!\n");
1042
1043         result = CryptDestroyHash(hHash);
1044         ok(result, "%08x\n", GetLastError());
1045     }
1046
1047     /* SHA-384 hash */
1048     result = CryptCreateHash(hProv, CALG_SHA_384, 0, 0, &hHash);
1049     ok(result, "%08x\n", GetLastError());
1050     if (result) {
1051         len = sizeof(DWORD);
1052         result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
1053         ok(result && (hashlen == 48), "%08x, hashlen: %d\n", GetLastError(), hashlen);
1054
1055         result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1056         ok(result, "%08x\n", GetLastError());
1057
1058         len = 48;
1059         result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
1060         ok(result, "%08x\n", GetLastError());
1061
1062         ok(!memcmp(pbHashValue, sha384hash, 48), "Wrong SHA-384 hash!\n");
1063
1064         result = CryptDestroyHash(hHash);
1065         ok(result, "%08x\n", GetLastError());
1066     }
1067
1068     /* SHA-512 hash */
1069     result = CryptCreateHash(hProv, CALG_SHA_512, 0, 0, &hHash);
1070     ok(result, "%08x\n", GetLastError());
1071     if (result) {
1072         len = sizeof(DWORD);
1073         result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
1074         ok(result && (hashlen == 64), "%08x, hashlen: %d\n", GetLastError(), hashlen);
1075
1076         result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1077         ok(result, "%08x\n", GetLastError());
1078
1079         len = 64;
1080         result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
1081         ok(result, "%08x\n", GetLastError());
1082
1083         ok(!memcmp(pbHashValue, sha512hash, 64), "Wrong SHA-512 hash!\n");
1084
1085         result = CryptDestroyHash(hHash);
1086         ok(result, "%08x\n", GetLastError());
1087     }
1088 }
1089
1090 static void test_rc2(void)
1091 {
1092     static const BYTE rc2_40_encrypted[16] = {
1093         0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11,
1094         0xfb, 0x18, 0x87, 0xce, 0x0c, 0x75, 0x07, 0xb1 };
1095     static const BYTE rc2_128_encrypted[] = {
1096         0x82,0x81,0xf7,0xff,0xdd,0xd7,0x88,0x8c,0x2a,0x2a,0xc0,0xce,0x4c,0x89,
1097         0xb6,0x66 };
1098     HCRYPTHASH hHash;
1099     HCRYPTKEY hKey;
1100     BOOL result;
1101     DWORD dwLen, dwKeyLen, dwDataLen, dwMode, dwModeBits;
1102     BYTE *pbTemp;
1103     unsigned char pbData[2000], pbHashValue[16];
1104     int i;
1105     
1106     for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
1107
1108     /* MD2 Hashing */
1109     result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
1110     if (!result) {
1111         ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
1112     } else {
1113         CRYPT_INTEGER_BLOB salt;
1114
1115         result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1116         ok(result, "%08x\n", GetLastError());
1117
1118         dwLen = 16;
1119         result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &dwLen, 0);
1120         ok(result, "%08x\n", GetLastError());
1121
1122         result = CryptDeriveKey(hProv, CALG_RC2, hHash, 40 << 16, &hKey);
1123         ok(result, "%08x\n", GetLastError());
1124
1125         dwLen = sizeof(DWORD);
1126         result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
1127         ok(result, "%08x\n", GetLastError());
1128
1129         dwMode = CRYPT_MODE_CBC;
1130         result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
1131         ok(result, "%08x\n", GetLastError());
1132
1133         dwLen = sizeof(DWORD);
1134         result = CryptGetKeyParam(hKey, KP_MODE_BITS, (BYTE*)&dwModeBits, &dwLen, 0);
1135         ok(result, "%08x\n", GetLastError());
1136
1137         dwModeBits = 0xdeadbeef;
1138         dwLen = sizeof(DWORD);
1139         result = CryptGetKeyParam(hKey, KP_PERMISSIONS, (BYTE*)&dwModeBits, &dwLen, 0);
1140         ok(result, "%08x\n", GetLastError());
1141         ok(dwModeBits ==
1142             (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
1143             broken(dwModeBits == 0xffffffff), /* Win9x/NT4 */
1144             "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
1145             " got %08x\n", dwModeBits);
1146
1147         dwLen = sizeof(DWORD);
1148         result = CryptGetKeyParam(hKey, KP_PERMISSIONS, (BYTE*)&dwModeBits, &dwLen, 0);
1149         ok(result, "%08x\n", GetLastError());
1150
1151         dwLen = sizeof(DWORD);
1152         result = CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&dwModeBits, &dwLen, 0);
1153         ok(result, "%08x\n", GetLastError());
1154
1155         result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
1156         ok(result, "%08x\n", GetLastError());
1157         pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
1158         CryptGetKeyParam(hKey, KP_IV, pbTemp, &dwLen, 0);
1159         HeapFree(GetProcessHeap(), 0, pbTemp);
1160
1161         result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1162         ok(result, "%08x\n", GetLastError());
1163         /* The default salt length is always 11... */
1164         ok(dwLen == 11, "unexpected salt length %d\n", dwLen);
1165         /* and the default salt is always empty. */
1166         pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
1167         CryptGetKeyParam(hKey, KP_SALT, pbTemp, &dwLen, 0);
1168         for (i=0; i<dwLen; i++)
1169             ok(!pbTemp[i], "unexpected salt value %02x @ %d\n", pbTemp[i], i);
1170         HeapFree(GetProcessHeap(), 0, pbTemp);
1171
1172         dwLen = sizeof(DWORD);
1173         CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
1174
1175         result = CryptDestroyHash(hHash);
1176         ok(result, "%08x\n", GetLastError());
1177
1178         dwDataLen = 13;
1179         result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
1180         ok(result, "%08x\n", GetLastError());
1181
1182         ok(!memcmp(pbData, rc2_40_encrypted, 16), "RC2 encryption failed!\n");
1183
1184         result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
1185         ok(result, "%08x\n", GetLastError());
1186         pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
1187         CryptGetKeyParam(hKey, KP_IV, pbTemp, &dwLen, 0);
1188         HeapFree(GetProcessHeap(), 0, pbTemp);
1189
1190         result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen);
1191         ok(result, "%08x\n", GetLastError());
1192
1193         /* Setting the salt also succeeds... */
1194         result = CryptSetKeyParam(hKey, KP_SALT, pbData, 0);
1195         ok(result, "setting salt failed: %08x\n", GetLastError());
1196         /* but the resulting salt length is now zero? */
1197         dwLen = 0;
1198         result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1199         ok(result, "%08x\n", GetLastError());
1200         ok(dwLen == 0 ||
1201            broken(dwLen == 11), /* Win9x/WinMe/NT4 */
1202            "unexpected salt length %d\n", dwLen);
1203         /* What sizes salt can I set? */
1204         salt.pbData = pbData;
1205         for (i=0; i<24; i++)
1206         {
1207             salt.cbData = i;
1208             result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
1209             ok(result, "setting salt failed for size %d: %08x\n", i, GetLastError());
1210             /* The returned salt length is the same as the set salt length */
1211             result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1212             ok(result, "%08x\n", GetLastError());
1213             ok(dwLen == i, "size %d: unexpected salt length %d\n", i, dwLen);
1214         }
1215         salt.cbData = 25;
1216         SetLastError(0xdeadbeef);
1217         result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
1218         ok(!result ||
1219            broken(result), /* Win9x, WinMe, NT4, W2K */
1220            "%08x\n", GetLastError());
1221
1222         result = CryptDestroyKey(hKey);
1223         ok(result, "%08x\n", GetLastError());
1224     }
1225
1226     /* Again, but test setting the effective key len */
1227     for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
1228
1229     result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
1230     if (!result) {
1231         ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
1232     } else {
1233         result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1234         ok(result, "%08x\n", GetLastError());
1235
1236         dwLen = 16;
1237         result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &dwLen, 0);
1238         ok(result, "%08x\n", GetLastError());
1239
1240         result = CryptDeriveKey(hProv, CALG_RC2, hHash, 56 << 16, &hKey);
1241         ok(result, "%08x\n", GetLastError());
1242
1243         SetLastError(0xdeadbeef);
1244         result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, NULL, 0);
1245         ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%08x\n", GetLastError());
1246         dwKeyLen = 0;
1247         SetLastError(0xdeadbeef);
1248         result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1249         ok(!result && GetLastError()==NTE_BAD_DATA, "%08x\n", GetLastError());
1250         dwKeyLen = 1025;
1251         SetLastError(0xdeadbeef);
1252         result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1253         ok(!result, "CryptSetKeyParam failed: %08x\n", GetLastError());
1254
1255         dwLen = sizeof(dwKeyLen);
1256         CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1257         ok(dwKeyLen == 56, "%d (%08x)\n", dwKeyLen, GetLastError());
1258         CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1259         ok(dwKeyLen == 56 || broken(dwKeyLen == 40), "%d (%08x)\n", dwKeyLen, GetLastError());
1260
1261         dwKeyLen = 128;
1262         result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1263         ok(result, "%d\n", GetLastError());
1264
1265         dwLen = sizeof(dwKeyLen);
1266         CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1267         ok(dwKeyLen == 56, "%d (%08x)\n", dwKeyLen, GetLastError());
1268         CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1269         ok(dwKeyLen == 128, "%d (%08x)\n", dwKeyLen, GetLastError());
1270
1271         result = CryptDestroyHash(hHash);
1272         ok(result, "%08x\n", GetLastError());
1273
1274         dwDataLen = 13;
1275         result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
1276         ok(result, "%08x\n", GetLastError());
1277
1278         ok(!memcmp(pbData, rc2_128_encrypted, sizeof(rc2_128_encrypted)),
1279                 "RC2 encryption failed!\n");
1280
1281         /* Oddly enough this succeeds, though it should have no effect */
1282         dwKeyLen = 40;
1283         result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1284         ok(result, "%d\n", GetLastError());
1285
1286         result = CryptDestroyKey(hKey);
1287         ok(result, "%08x\n", GetLastError());
1288     }
1289 }
1290
1291 static void test_rc4(void)
1292 {
1293     static const BYTE rc4[16] = { 
1294         0x17, 0x0c, 0x44, 0x8e, 0xae, 0x90, 0xcd, 0xb0, 
1295         0x7f, 0x87, 0xf5, 0x7a, 0xec, 0xb2, 0x2e, 0x35 };    
1296     BOOL result;
1297     HCRYPTHASH hHash;
1298     HCRYPTKEY hKey;
1299     DWORD dwDataLen = 5, dwKeyLen, dwLen = sizeof(DWORD), dwMode;
1300     unsigned char pbData[2000], *pbTemp;
1301     unsigned char pszBuffer[256];
1302     int i;
1303
1304     for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
1305
1306     /* MD2 Hashing */
1307     result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
1308     if (!result) {
1309         /* rsaenh compiled without OpenSSL */
1310         ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
1311     } else {
1312         CRYPT_INTEGER_BLOB salt;
1313
1314         result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1315            ok(result, "%08x\n", GetLastError());
1316
1317         dwLen = 16;
1318         result = CryptGetHashParam(hHash, HP_HASHVAL, pszBuffer, &dwLen, 0);
1319         ok(result, "%08x\n", GetLastError());
1320
1321         result = CryptDeriveKey(hProv, CALG_RC4, hHash, 56 << 16, &hKey);
1322         ok(result, "%08x\n", GetLastError());
1323
1324         dwLen = sizeof(DWORD);
1325         result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
1326         ok(result, "%08x\n", GetLastError());
1327
1328         dwLen = sizeof(DWORD);
1329         result = CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
1330         ok(result, "%08x\n", GetLastError());
1331
1332         result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
1333         ok(result, "%08x\n", GetLastError());
1334         pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
1335         CryptGetKeyParam(hKey, KP_IV, pbTemp, &dwLen, 0);
1336         HeapFree(GetProcessHeap(), 0, pbTemp);
1337
1338         result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1339         ok(result, "%08x\n", GetLastError());
1340         pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
1341         CryptGetKeyParam(hKey, KP_SALT, pbTemp, &dwLen, 0);
1342         HeapFree(GetProcessHeap(), 0, pbTemp);
1343
1344         dwLen = sizeof(DWORD);
1345         CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
1346
1347         result = CryptDestroyHash(hHash);
1348         ok(result, "%08x\n", GetLastError());
1349
1350         dwDataLen = 16;
1351         result = CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwDataLen, 24);
1352         ok(result, "%08x\n", GetLastError());
1353         dwDataLen = 16;
1354         result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
1355         ok(result, "%08x\n", GetLastError());
1356
1357         ok(!memcmp(pbData, rc4, dwDataLen), "RC4 encryption failed!\n");
1358
1359         result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen);
1360         ok(result, "%08x\n", GetLastError());
1361
1362         /* Setting the salt also succeeds... */
1363         result = CryptSetKeyParam(hKey, KP_SALT, pbData, 0);
1364         ok(result, "setting salt failed: %08x\n", GetLastError());
1365         /* but the resulting salt length is now zero? */
1366         dwLen = 0;
1367         result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1368         ok(result, "%08x\n", GetLastError());
1369         ok(dwLen == 0 ||
1370            broken(dwLen == 11), /* Win9x/WinMe/NT4 */
1371            "unexpected salt length %d\n", dwLen);
1372         /* What sizes salt can I set? */
1373         salt.pbData = pbData;
1374         for (i=0; i<24; i++)
1375         {
1376             salt.cbData = i;
1377             result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
1378             ok(result, "setting salt failed for size %d: %08x\n", i, GetLastError());
1379             /* The returned salt length is the same as the set salt length */
1380             result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1381             ok(result, "%08x\n", GetLastError());
1382             ok(dwLen == i, "size %d: unexpected salt length %d\n", i, dwLen);
1383         }
1384         salt.cbData = 25;
1385         SetLastError(0xdeadbeef);
1386         result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
1387         ok(!result ||
1388            broken(result), /* Win9x, WinMe, NT4, W2K */
1389            "%08x\n", GetLastError());
1390
1391         result = CryptDestroyKey(hKey);
1392         ok(result, "%08x\n", GetLastError());
1393     }
1394 }
1395
1396 static void test_hmac(void) {
1397     HCRYPTKEY hKey;
1398     HCRYPTHASH hHash;
1399     BOOL result;
1400     /* Using CALG_MD2 here fails on Windows 2003, why ? */
1401     HMAC_INFO hmacInfo = { CALG_MD5, NULL, 0, NULL, 0 };
1402     DWORD dwLen;
1403     BYTE abData[256];
1404     static const BYTE hmac[16] = { 
1405         0x1a, 0x7d, 0x49, 0xc5, 0x9b, 0x2d, 0x0b, 0x9c, 
1406         0xcf, 0x10, 0x6b, 0xb6, 0x7d, 0x0f, 0x13, 0x32 };
1407     int i;
1408
1409     for (i=0; i<sizeof(abData)/sizeof(BYTE); i++) abData[i] = (BYTE)i;
1410
1411     if (!derive_key(CALG_RC2, &hKey, 56)) return;
1412
1413     result = CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHash);
1414     ok(result, "%08x\n", GetLastError());
1415     if (!result) return;
1416
1417     result = CryptSetHashParam(hHash, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0);
1418     ok(result, "%08x\n", GetLastError());
1419
1420     result = CryptHashData(hHash, abData, sizeof(abData), 0);
1421     ok(result, "%08x\n", GetLastError());
1422
1423     dwLen = sizeof(abData)/sizeof(BYTE);
1424     result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
1425     ok(result, "%08x\n", GetLastError());
1426
1427     ok(!memcmp(abData, hmac, sizeof(hmac)), "HMAC failed!\n");
1428     
1429     result = CryptDestroyHash(hHash);
1430     ok(result, "%08x\n", GetLastError());
1431     
1432     result = CryptDestroyKey(hKey);
1433     ok(result, "%08x\n", GetLastError());
1434
1435     /* Provoke errors */
1436     result = CryptCreateHash(hProv, CALG_HMAC, 0, 0, &hHash);
1437     ok(!result && GetLastError() == NTE_BAD_KEY, "%08x\n", GetLastError());
1438 }
1439
1440 static void test_mac(void) {
1441     HCRYPTKEY hKey;
1442     HCRYPTHASH hHash;
1443     BOOL result;
1444     DWORD dwLen;
1445     BYTE abData[256], abEnc[264];
1446     static const BYTE mac_40[8] = { 0xb7, 0xa2, 0x46, 0xe9, 0x11, 0x31, 0xe0, 0xad};
1447     int i;
1448
1449     for (i=0; i<sizeof(abData)/sizeof(BYTE); i++) abData[i] = (BYTE)i;
1450     for (i=0; i<sizeof(abData)/sizeof(BYTE); i++) abEnc[i] = (BYTE)i;
1451
1452     if (!derive_key(CALG_RC2, &hKey, 40)) return;
1453
1454     dwLen = 256;
1455     result = CryptEncrypt(hKey, 0, TRUE, 0, abEnc, &dwLen, 264);
1456     ok (result && dwLen == 264, "%08x, dwLen: %d\n", GetLastError(), dwLen);
1457     
1458     result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
1459     ok(result, "%08x\n", GetLastError());
1460     if (!result) return;
1461
1462     result = CryptHashData(hHash, abData, sizeof(abData), 0);
1463     ok(result, "%08x\n", GetLastError());
1464
1465     dwLen = sizeof(abData)/sizeof(BYTE);
1466     result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
1467     ok(result && dwLen == 8, "%08x, dwLen: %d\n", GetLastError(), dwLen);
1468
1469     ok(!memcmp(abData, mac_40, sizeof(mac_40)), "MAC failed!\n");
1470     
1471     result = CryptDestroyHash(hHash);
1472     ok(result, "%08x\n", GetLastError());
1473     
1474     result = CryptDestroyKey(hKey);
1475     ok(result, "%08x\n", GetLastError());
1476     
1477     /* Provoke errors */
1478     if (!derive_key(CALG_RC4, &hKey, 56)) return;
1479
1480     SetLastError(0xdeadbeef);
1481     result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
1482     ok((!result && GetLastError() == NTE_BAD_KEY) ||
1483             broken(result), /* Win9x, WinMe, NT4, W2K */
1484             "%08x\n", GetLastError());
1485
1486     result = CryptDestroyKey(hKey);
1487     ok(result, "%08x\n", GetLastError());
1488 }
1489
1490 static void test_import_private(void) 
1491 {
1492     DWORD dwLen, dwVal;
1493     HCRYPTKEY hKeyExchangeKey, hSessionKey;
1494     BOOL result;
1495     static BYTE abSessionKey[148] = {
1496         0x01, 0x02, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00,
1497         0x00, 0xa4, 0x00, 0x00, 0xb8, 0xa4, 0xdf, 0x5e,
1498         0x9e, 0xb1, 0xbf, 0x85, 0x3d, 0x24, 0x2d, 0x1e,
1499         0x69, 0xb7, 0x67, 0x13, 0x8e, 0x78, 0xf2, 0xdf,
1500         0xc6, 0x69, 0xce, 0x46, 0x7e, 0xf2, 0xf2, 0x33,
1501         0x20, 0x6f, 0xa1, 0xa5, 0x59, 0x83, 0x25, 0xcb,
1502         0x3a, 0xb1, 0x8a, 0x12, 0x63, 0x02, 0x3c, 0xfb,
1503         0x4a, 0xfa, 0xef, 0x8e, 0xf7, 0x29, 0x57, 0xb1,
1504         0x9e, 0xa7, 0xf3, 0x02, 0xfd, 0xca, 0xdf, 0x5a,
1505         0x1f, 0x71, 0xb6, 0x26, 0x09, 0x24, 0x39, 0xda,
1506         0xc0, 0xde, 0x2a, 0x0e, 0xcd, 0x1f, 0xe5, 0xb6,
1507         0x4f, 0x82, 0xa0, 0xa9, 0x90, 0xd3, 0xd9, 0x6a,
1508         0x43, 0x14, 0x2a, 0xf7, 0xac, 0xd5, 0xa0, 0x54,
1509         0x93, 0xc4, 0xb9, 0xe7, 0x24, 0x84, 0x4d, 0x69,
1510         0x5e, 0xcc, 0x2a, 0x32, 0xb5, 0xfb, 0xe4, 0xb4,
1511         0x08, 0xd5, 0x36, 0x58, 0x59, 0x40, 0xfb, 0x29,
1512         0x7f, 0xa7, 0x17, 0x25, 0xc4, 0x0d, 0x78, 0x37,
1513         0x04, 0x8c, 0x49, 0x92
1514     };
1515     static BYTE abEncryptedMessage[12] = {
1516         0x40, 0x64, 0x28, 0xe8, 0x8a, 0xe7, 0xa4, 0xd4,
1517         0x1c, 0xfd, 0xde, 0x71
1518     };
1519     BLOBHEADER *blobHeader = (BLOBHEADER *)abPlainPrivateKey;
1520     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(blobHeader+1);
1521
1522     dwLen = (DWORD)sizeof(abPlainPrivateKey);
1523     result = CryptImportKey(hProv, abPlainPrivateKey, dwLen, 0, 0, &hKeyExchangeKey);
1524     if (!result) {
1525         /* rsaenh compiled without OpenSSL */
1526         ok(GetLastError() == NTE_FAIL, "%08x\n", GetLastError());
1527         return;
1528     }
1529
1530     dwLen = (DWORD)sizeof(abSessionKey);
1531     result = CryptImportKey(hProv, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
1532     ok(result, "%08x\n", GetLastError());
1533     if (!result) return;
1534
1535     dwVal = 0xdeadbeef;
1536     dwLen = sizeof(DWORD);
1537     result = CryptGetKeyParam(hSessionKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
1538     ok(result, "%08x\n", GetLastError());
1539     ok(dwVal ==
1540         (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
1541         broken(dwVal == 0xffffffff), /* Win9x/NT4 */
1542         "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
1543         " got %08x\n", dwVal);
1544
1545     dwLen = (DWORD)sizeof(abEncryptedMessage);
1546     result = CryptDecrypt(hSessionKey, 0, TRUE, 0, abEncryptedMessage, &dwLen);
1547     ok(result && dwLen == 12 && !memcmp(abEncryptedMessage, "Wine rocks!",12), 
1548        "%08x, len: %d\n", GetLastError(), dwLen);
1549     CryptDestroyKey(hSessionKey);
1550     
1551     if (!derive_key(CALG_RC4, &hSessionKey, 56)) return;
1552
1553     dwLen = (DWORD)sizeof(abSessionKey);
1554     result = CryptExportKey(hSessionKey, hKeyExchangeKey, SIMPLEBLOB, 0, abSessionKey, &dwLen);
1555     ok(result, "%08x\n", GetLastError());
1556     CryptDestroyKey(hSessionKey);
1557     if (!result) return;
1558
1559     dwLen = (DWORD)sizeof(abSessionKey);
1560     result = CryptImportKey(hProv, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
1561     ok(result, "%08x\n", GetLastError());
1562     if (!result) return;
1563
1564     CryptDestroyKey(hSessionKey);
1565     CryptDestroyKey(hKeyExchangeKey);
1566
1567     /* Test importing a private key with a buffer that's smaller than the
1568      * actual buffer.  The private exponent can be omitted, its length is
1569      * inferred from the passed-in length parameter.
1570      */
1571     dwLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1572         rsaPubKey->bitlen / 8 + 5 * rsaPubKey->bitlen / 16;
1573     for (; dwLen < sizeof(abPlainPrivateKey); dwLen++)
1574     {
1575         result = CryptImportKey(hProv, abPlainPrivateKey, dwLen, 0, 0, &hKeyExchangeKey);
1576         ok(result, "CryptImportKey failed at size %d: %d (%08x)\n", dwLen,
1577            GetLastError(), GetLastError());
1578         if (result)
1579             CryptDestroyKey(hKeyExchangeKey);
1580     }
1581 }
1582
1583 static void test_verify_signature(void) {
1584     HCRYPTHASH hHash;
1585     HCRYPTKEY hPubSignKey;
1586     BYTE abData[] = "Wine rocks!";
1587     BOOL result;
1588     BYTE abPubKey[148] = {
1589         0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 
1590         0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 
1591         0x01, 0x00, 0x01, 0x00, 0x71, 0x64, 0x9f, 0x19, 
1592         0x89, 0x1c, 0x21, 0xcc, 0x36, 0xa3, 0xc9, 0x27, 
1593         0x08, 0x8a, 0x09, 0xc6, 0xbe, 0xeb, 0xd3, 0xf8, 
1594         0x19, 0xa9, 0x92, 0x57, 0xe4, 0xb9, 0x5d, 0xda, 
1595         0x88, 0x93, 0xe4, 0x6b, 0x38, 0x77, 0x14, 0x8a, 
1596         0x96, 0xc0, 0xb6, 0x4e, 0x42, 0xf5, 0x01, 0xdc, 
1597         0xf0, 0xeb, 0x3c, 0xc7, 0x7b, 0xc4, 0xfd, 0x7c, 
1598         0xde, 0x93, 0x34, 0x0a, 0x92, 0xe5, 0x97, 0x9c, 
1599         0x3e, 0x65, 0xb8, 0x91, 0x2f, 0xe3, 0xf3, 0x89, 
1600         0xcd, 0x6c, 0x26, 0xa4, 0x6c, 0xc7, 0x6d, 0x0b, 
1601         0x2c, 0xa2, 0x0b, 0x29, 0xe2, 0xfc, 0x30, 0xfa, 
1602         0x20, 0xdb, 0x4c, 0xb8, 0x91, 0xb8, 0x69, 0x63, 
1603         0x96, 0x41, 0xc2, 0xb4, 0x60, 0xeb, 0xcd, 0xff, 
1604         0x3a, 0x1f, 0x94, 0xb1, 0x23, 0xcf, 0x0f, 0x49, 
1605         0xad, 0xd5, 0x33, 0x85, 0x71, 0xaf, 0x12, 0x87, 
1606         0x84, 0xef, 0xa0, 0xea, 0xe1, 0xc1, 0xd4, 0xc7, 
1607         0xe1, 0x21, 0x50, 0xac
1608     };
1609     /* md2 with hash oid */
1610     BYTE abSignatureMD2[128] = {
1611         0x4a, 0x4e, 0xb7, 0x5e, 0x32, 0xda, 0xdb, 0x67, 
1612         0x9f, 0x77, 0x84, 0x32, 0x00, 0xba, 0x5f, 0x6b, 
1613         0x0d, 0xcf, 0xd9, 0x99, 0xbd, 0x96, 0x31, 0xda, 
1614         0x23, 0x4c, 0xd9, 0x4a, 0x90, 0x84, 0x20, 0x59, 
1615         0x51, 0xdc, 0xd4, 0x93, 0x3a, 0xae, 0x0a, 0x0a, 
1616         0xa1, 0x76, 0xfa, 0xb5, 0x68, 0xee, 0xc7, 0x34, 
1617         0x41, 0xd3, 0xe7, 0x5a, 0x0e, 0x22, 0x61, 0x40, 
1618         0xea, 0x24, 0x56, 0xf1, 0x91, 0x5a, 0xf7, 0xa7, 
1619         0x5b, 0xf4, 0x98, 0x6b, 0xc3, 0xef, 0xad, 0xc0, 
1620         0x5e, 0x6b, 0x87, 0x76, 0xcb, 0x1f, 0x62, 0x06, 
1621         0x7c, 0xf6, 0x48, 0x97, 0x81, 0x8d, 0xef, 0x51, 
1622         0x51, 0xdc, 0x21, 0x91, 0x57, 0x1e, 0x79, 0x6f, 
1623         0x49, 0xb5, 0xde, 0x31, 0x07, 0x45, 0x99, 0x46, 
1624         0xc3, 0x4f, 0xca, 0x2d, 0x0e, 0x4c, 0x10, 0x25, 
1625         0xcb, 0x1a, 0x98, 0x63, 0x41, 0x93, 0x47, 0xc0, 
1626         0xb2, 0xbc, 0x10, 0x3c, 0xe7, 0xd4, 0x3c, 0x1e
1627     };
1628     /* md2 without hash oid */
1629     BYTE abSignatureMD2NoOID[128] = {
1630         0x0c, 0x21, 0x3e, 0x60, 0xf9, 0xd0, 0x36, 0x2d, 
1631         0xe1, 0x10, 0x45, 0x45, 0x85, 0x03, 0x29, 0x19, 
1632         0xef, 0x19, 0xd9, 0xa6, 0x7e, 0x9c, 0x0d, 0xbd, 
1633         0x03, 0x0e, 0xb9, 0x51, 0x9e, 0x74, 0x79, 0xc4, 
1634         0xde, 0x25, 0xf2, 0x35, 0x74, 0x55, 0xbc, 0x65, 
1635         0x7e, 0x33, 0x28, 0xa8, 0x1e, 0x72, 0xaa, 0x99, 
1636         0xdd, 0xf5, 0x26, 0x20, 0x29, 0xf8, 0xa6, 0xdf, 
1637         0x28, 0x4b, 0x1c, 0xdb, 0xa1, 0x41, 0x56, 0xbc, 
1638         0xf9, 0x9c, 0x66, 0xc0, 0x37, 0x41, 0x55, 0xa0, 
1639         0xe2, 0xec, 0xbf, 0x71, 0xf0, 0x5d, 0x25, 0x01, 
1640         0x75, 0x91, 0xe2, 0x81, 0xb2, 0x9f, 0x57, 0xa7, 
1641         0x5c, 0xd2, 0xfa, 0x66, 0xdb, 0x71, 0x2b, 0x1f, 
1642         0xad, 0x30, 0xde, 0xea, 0x49, 0x73, 0x30, 0x6a, 
1643         0x22, 0x54, 0x49, 0x4e, 0xae, 0xf6, 0x88, 0xc9, 
1644         0xff, 0x71, 0xba, 0xbf, 0x27, 0xc5, 0xfa, 0x06, 
1645         0xe2, 0x91, 0x71, 0x8a, 0x7e, 0x0c, 0xc2, 0x07
1646     };
1647     /* md4 with hash oid */
1648     BYTE abSignatureMD4[128] = {
1649         0x1c, 0x78, 0xaa, 0xea, 0x74, 0xf4, 0x83, 0x51, 
1650         0xae, 0x66, 0xe3, 0xa9, 0x1c, 0x03, 0x39, 0x1b, 
1651         0xac, 0x7e, 0x4e, 0x85, 0x7e, 0x1c, 0x38, 0xd2, 
1652         0x82, 0x43, 0xb3, 0x6f, 0x6f, 0x46, 0x45, 0x8e, 
1653         0x17, 0x74, 0x58, 0x29, 0xca, 0xe1, 0x03, 0x13, 
1654         0x45, 0x79, 0x34, 0xdf, 0x5c, 0xd6, 0xc3, 0xf9, 
1655         0x7a, 0x1c, 0x9d, 0xff, 0x6f, 0x03, 0x7d, 0x0f, 
1656         0x59, 0x1a, 0x2d, 0x0e, 0x94, 0xb4, 0x75, 0x96, 
1657         0xd1, 0x48, 0x63, 0x6e, 0xb2, 0xc4, 0x5c, 0xd9, 
1658         0xab, 0x49, 0xb4, 0x90, 0xd9, 0x57, 0x04, 0x6e, 
1659         0x4c, 0xb6, 0xea, 0x00, 0x94, 0x4a, 0x34, 0xa0, 
1660         0xd9, 0x63, 0xef, 0x2c, 0xde, 0x5b, 0xb9, 0xbe, 
1661         0x35, 0xc8, 0xc1, 0x31, 0xb5, 0x31, 0x15, 0x18, 
1662         0x90, 0x39, 0xf5, 0x2a, 0x34, 0x6d, 0xb4, 0xab, 
1663         0x09, 0x34, 0x69, 0x54, 0x4d, 0x11, 0x2f, 0xf3, 
1664         0xa2, 0x36, 0x0e, 0xa8, 0x45, 0xe7, 0x36, 0xac
1665     };
1666     /* md4 without hash oid */
1667     BYTE abSignatureMD4NoOID[128] = {
1668         0xd3, 0x60, 0xb2, 0xb0, 0x22, 0x0a, 0x99, 0xda, 
1669         0x04, 0x85, 0x64, 0xc6, 0xc6, 0xdb, 0x11, 0x24, 
1670         0xe9, 0x68, 0x2d, 0xf7, 0x09, 0xef, 0xb6, 0xa0, 
1671         0xa2, 0xfe, 0x45, 0xee, 0x85, 0x49, 0xcd, 0x36, 
1672         0xf7, 0xc7, 0x9d, 0x2b, 0x4c, 0x68, 0xda, 0x85, 
1673         0x8c, 0x50, 0xcc, 0x4f, 0x4b, 0xe1, 0x82, 0xc3, 
1674         0xbe, 0xa3, 0xf1, 0x78, 0x6b, 0x60, 0x42, 0x3f, 
1675         0x67, 0x22, 0x14, 0xe4, 0xe1, 0xa4, 0x6e, 0xa9, 
1676         0x4e, 0xf1, 0xd4, 0xb0, 0xce, 0x82, 0xac, 0x06, 
1677         0xba, 0x2c, 0xbc, 0xf7, 0xcb, 0xf6, 0x0c, 0x3f, 
1678         0xf6, 0x79, 0xfe, 0xb3, 0xd8, 0x5a, 0xbc, 0xdb, 
1679         0x05, 0x41, 0xa4, 0x07, 0x57, 0x9e, 0xa2, 0x96, 
1680         0xfc, 0x60, 0x4b, 0xf7, 0x6f, 0x86, 0x26, 0x1f, 
1681         0xc2, 0x2c, 0x67, 0x08, 0xcd, 0x7f, 0x91, 0xe9, 
1682         0x16, 0xb5, 0x0e, 0xd9, 0xc4, 0xc4, 0x97, 0xeb, 
1683         0x91, 0x3f, 0x20, 0x6c, 0xf0, 0x68, 0x86, 0x7f
1684     }; 
1685     /* md5 with hash oid */
1686     BYTE abSignatureMD5[128] = {
1687         0x4f, 0xe0, 0x8c, 0x9b, 0x43, 0xdd, 0x02, 0xe5, 
1688         0xf4, 0xa1, 0xdd, 0x88, 0x4c, 0x9c, 0x40, 0x0f, 
1689         0x6c, 0x43, 0x86, 0x64, 0x00, 0xe6, 0xac, 0xf7, 
1690         0xd0, 0x92, 0xaa, 0xc4, 0x62, 0x9a, 0x48, 0x98, 
1691         0x1a, 0x56, 0x6d, 0x75, 0xec, 0x04, 0x89, 0xec, 
1692         0x69, 0x93, 0xd6, 0x61, 0x37, 0xb2, 0x36, 0xb5, 
1693         0xb2, 0xba, 0xf2, 0xf5, 0x21, 0x0c, 0xf1, 0x04, 
1694         0xc8, 0x2d, 0xf5, 0xa0, 0x8d, 0x6d, 0x10, 0x0b, 
1695         0x68, 0x63, 0xf2, 0x08, 0x68, 0xdc, 0xbd, 0x95, 
1696         0x25, 0x7d, 0xee, 0x63, 0x5c, 0x3b, 0x98, 0x4c, 
1697         0xea, 0x41, 0xdc, 0x6a, 0x8b, 0x6c, 0xbb, 0x29, 
1698         0x2b, 0x1c, 0x5c, 0x8b, 0x7d, 0x94, 0x24, 0xa9, 
1699         0x7a, 0x62, 0x94, 0xf3, 0x3a, 0x6a, 0xb2, 0x4c, 
1700         0x33, 0x59, 0x00, 0xcd, 0x7d, 0x37, 0x79, 0x90, 
1701         0x31, 0xd1, 0xd9, 0x84, 0x12, 0xe5, 0x08, 0x5e, 
1702         0xb3, 0x60, 0x61, 0x27, 0x78, 0x37, 0x63, 0x01
1703     };
1704     /* md5 without hash oid */
1705     BYTE abSignatureMD5NoOID[128] = {
1706         0xc6, 0xad, 0x5c, 0x2b, 0x9b, 0xe0, 0x99, 0x2f, 
1707         0x5e, 0x55, 0x04, 0x32, 0x65, 0xe0, 0xb5, 0x75, 
1708         0x01, 0x9a, 0x11, 0x4d, 0x0e, 0x9a, 0xe1, 0x9f, 
1709         0xc7, 0xbf, 0x77, 0x6d, 0xa9, 0xfd, 0xcc, 0x9d, 
1710         0x8b, 0xd1, 0x31, 0xed, 0x5a, 0xd2, 0xe5, 0x5f, 
1711         0x42, 0x3b, 0xb5, 0x3c, 0x32, 0x30, 0x88, 0x49, 
1712         0xcb, 0x67, 0xb8, 0x2e, 0xc9, 0xf5, 0x2b, 0xc8, 
1713         0x35, 0x71, 0xb5, 0x1b, 0x32, 0x3f, 0x44, 0x4c, 
1714         0x66, 0x93, 0xcb, 0xe8, 0x48, 0x7c, 0x14, 0x23, 
1715         0xfb, 0x12, 0xa5, 0xb7, 0x86, 0x94, 0x6b, 0x19, 
1716         0x17, 0x20, 0xc6, 0xb8, 0x09, 0xe8, 0xbb, 0xdb, 
1717         0x00, 0x2b, 0x96, 0x4a, 0x93, 0x00, 0x26, 0xd3, 
1718         0x07, 0xa0, 0x06, 0xce, 0x5a, 0x13, 0x69, 0x6b, 
1719         0x62, 0x5a, 0x56, 0x61, 0x6a, 0xd8, 0x11, 0x3b, 
1720         0xd5, 0x67, 0xc7, 0x4d, 0xf6, 0x66, 0x63, 0xc5, 
1721         0xe3, 0x8f, 0x7c, 0x7c, 0xb1, 0x3e, 0x55, 0x43
1722     };
1723     /* sha with hash oid */
1724     BYTE abSignatureSHA[128] = {
1725         0x5a, 0x4c, 0x66, 0xc9, 0x30, 0x67, 0xcb, 0x91, 
1726         0x3c, 0x4d, 0xd5, 0x8d, 0xea, 0x4e, 0x85, 0xcd, 
1727         0xd9, 0x68, 0x3a, 0xf3, 0x24, 0x3c, 0x99, 0x24, 
1728         0x25, 0x32, 0x93, 0x3d, 0xd6, 0x2f, 0x86, 0x94, 
1729         0x23, 0x09, 0xee, 0x02, 0xd4, 0x15, 0xdc, 0x5f, 
1730         0x0e, 0x44, 0x45, 0x13, 0x5f, 0x18, 0x5d, 0x1a, 
1731         0xd7, 0x0b, 0xd1, 0x23, 0xd6, 0x35, 0x98, 0x52, 
1732         0x57, 0x45, 0x74, 0x92, 0xe3, 0x50, 0xb4, 0x20, 
1733         0x28, 0x2a, 0x11, 0xbf, 0x49, 0xb4, 0x2c, 0xc5, 
1734         0xd4, 0x1a, 0x27, 0x4e, 0xdf, 0xa0, 0xb5, 0x7a, 
1735         0xc8, 0x14, 0xdd, 0x9b, 0xb6, 0xca, 0xd6, 0xff, 
1736         0xb2, 0x6b, 0xd8, 0x98, 0x67, 0x80, 0xab, 0x53, 
1737         0x52, 0xbb, 0xe1, 0x2a, 0xce, 0x79, 0x2f, 0x00, 
1738         0x53, 0x26, 0xd8, 0xa7, 0x43, 0xca, 0x72, 0x0e, 
1739         0x68, 0x97, 0x37, 0x71, 0x87, 0xc2, 0x6a, 0x98, 
1740         0xbb, 0x6c, 0xa0, 0x01, 0xff, 0x04, 0x9d, 0xa6
1741     };
1742     /* sha without hash oid */
1743     BYTE abSignatureSHANoOID[128] = {
1744         0x86, 0xa6, 0x2b, 0x9a, 0x04, 0xda, 0x47, 0xc6, 
1745         0x4f, 0x97, 0x8a, 0x8a, 0xf4, 0xfa, 0x63, 0x1a, 
1746         0x32, 0x89, 0x56, 0x41, 0x37, 0x91, 0x15, 0x2f, 
1747         0x2d, 0x1c, 0x8f, 0xdc, 0x88, 0x40, 0xbb, 0x37, 
1748         0x3e, 0x06, 0x33, 0x1b, 0xde, 0xda, 0x7c, 0x65, 
1749         0x91, 0x35, 0xca, 0x45, 0x17, 0x0e, 0x24, 0xbe, 
1750         0x9e, 0xf6, 0x4e, 0x8a, 0xa4, 0x3e, 0xca, 0xe6, 
1751         0x11, 0x36, 0xb8, 0x3a, 0xf0, 0xde, 0x71, 0xfe, 
1752         0xdd, 0xb3, 0xcb, 0x6c, 0x39, 0xe0, 0x5f, 0x0c, 
1753         0x9e, 0xa8, 0x40, 0x26, 0x9c, 0x81, 0xe9, 0xc4, 
1754         0x15, 0x90, 0xbf, 0x4f, 0xd2, 0xc1, 0xa1, 0x80, 
1755         0x52, 0xfd, 0xf6, 0x3d, 0x99, 0x1b, 0x9c, 0x8a, 
1756         0x27, 0x1b, 0x0c, 0x9a, 0xf3, 0xf9, 0xa2, 0x00, 
1757         0x3e, 0x5b, 0xdf, 0xc2, 0xb4, 0x71, 0xa5, 0xbd, 
1758         0xf8, 0xae, 0x63, 0xbb, 0x4a, 0xc9, 0xdd, 0x67, 
1759         0xc1, 0x3e, 0x93, 0xee, 0xf1, 0x1f, 0x24, 0x5b
1760     }; 
1761     
1762     result = CryptImportKey(hProv, abPubKey, 148, 0, 0, &hPubSignKey);
1763     ok(result, "%08x\n", GetLastError());
1764     if (!result) return;
1765
1766     result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
1767     ok(result, "%08x\n", GetLastError());
1768     if (!result) return;
1769
1770     result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
1771     ok(result, "%08x\n", GetLastError());
1772     if (!result) return;
1773
1774     /*check that a NULL pointer signature is correctly handled*/
1775     result = CryptVerifySignature(hHash, NULL, 128, hPubSignKey, NULL, 0);
1776     ok(!result && ERROR_INVALID_PARAMETER == GetLastError(),
1777      "Expected ERROR_INVALID_PARAMETER error, got %08x\n", GetLastError());
1778     if (result) return;
1779
1780     /* check that we get a bad signature error when the signature is too short*/
1781     SetLastError(0xdeadbeef);
1782     result = CryptVerifySignature(hHash, abSignatureMD2, 64, hPubSignKey, NULL, 0);
1783     ok((!result && NTE_BAD_SIGNATURE == GetLastError()) ||
1784      broken(result), /* Win9x, WinMe, NT4 */
1785      "Expected NTE_BAD_SIGNATURE, got %08x\n",  GetLastError());
1786
1787     result = CryptVerifySignature(hHash, abSignatureMD2, 128, hPubSignKey, NULL, 0);
1788     ok(result, "%08x\n", GetLastError());
1789     if (!result) return;
1790
1791     /* It seems that CPVerifySignature doesn't care about the OID at all. */
1792     result = CryptVerifySignature(hHash, abSignatureMD2NoOID, 128, hPubSignKey, NULL, 0);
1793     ok(result, "%08x\n", GetLastError());
1794     if (!result) return;
1795
1796     result = CryptVerifySignature(hHash, abSignatureMD2NoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
1797     ok(result, "%08x\n", GetLastError());
1798     if (!result) return;
1799
1800     CryptDestroyHash(hHash);
1801
1802     result = CryptCreateHash(hProv, CALG_MD4, 0, 0, &hHash);
1803     ok(result, "%08x\n", GetLastError());
1804     if (!result) return;
1805
1806     result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
1807     ok(result, "%08x\n", GetLastError());
1808     if (!result) return;
1809
1810     result = CryptVerifySignature(hHash, abSignatureMD4, 128, hPubSignKey, NULL, 0);
1811     ok(result, "%08x\n", GetLastError());
1812     if (!result) return;
1813
1814     result = CryptVerifySignature(hHash, abSignatureMD4NoOID, 128, hPubSignKey, NULL, 0);
1815     ok(result, "%08x\n", GetLastError());
1816     if (!result) return;
1817
1818     result = CryptVerifySignature(hHash, abSignatureMD4NoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
1819     ok(result, "%08x\n", GetLastError());
1820     if (!result) return;
1821
1822     CryptDestroyHash(hHash);
1823
1824     result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
1825     ok(result, "%08x\n", GetLastError());
1826     if (!result) return;
1827
1828     result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
1829     ok(result, "%08x\n", GetLastError());
1830     if (!result) return;
1831
1832     result = CryptVerifySignature(hHash, abSignatureMD5, 128, hPubSignKey, NULL, 0);
1833     ok(result, "%08x\n", GetLastError());
1834     if (!result) return;
1835
1836     result = CryptVerifySignature(hHash, abSignatureMD5NoOID, 128, hPubSignKey, NULL, 0);
1837     ok(result, "%08x\n", GetLastError());
1838     if (!result) return;
1839
1840     result = CryptVerifySignature(hHash, abSignatureMD5NoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
1841     ok(result, "%08x\n", GetLastError());
1842     if (!result) return;
1843
1844     CryptDestroyHash(hHash);
1845
1846     result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
1847     ok(result, "%08x\n", GetLastError());
1848     if (!result) return;
1849
1850     result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
1851     ok(result, "%08x\n", GetLastError());
1852     if (!result) return;
1853
1854     result = CryptVerifySignature(hHash, abSignatureSHA, 128, hPubSignKey, NULL, 0);
1855     ok(result, "%08x\n", GetLastError());
1856     if (!result) return;
1857
1858     result = CryptVerifySignature(hHash, abSignatureSHANoOID, 128, hPubSignKey, NULL, 0);
1859     ok(result, "%08x\n", GetLastError());
1860     if (!result) return;
1861
1862     result = CryptVerifySignature(hHash, abSignatureSHANoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
1863     ok(result, "%08x\n", GetLastError());
1864     if (!result) return;
1865
1866     CryptDestroyHash(hHash);
1867     CryptDestroyKey(hPubSignKey);
1868 }
1869
1870 static void test_rsa_encrypt(void)
1871 {
1872     HCRYPTKEY hRSAKey;
1873     BYTE abData[2048] = "Wine rocks!";
1874     BOOL result;
1875     DWORD dwVal, dwLen;
1876
1877     /* It is allowed to use the key exchange key for encryption/decryption */
1878     result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hRSAKey);
1879     ok (result, "%08x\n", GetLastError());
1880     if (!result) return;
1881
1882     dwLen = 12;
1883     result = CryptEncrypt(hRSAKey, 0, TRUE, 0, NULL, &dwLen, (DWORD)sizeof(abData));
1884     ok(result, "CryptEncrypt failed: %08x\n", GetLastError());
1885     ok(dwLen == 128, "Unexpected length %d\n", dwLen);
1886     dwLen = 12;
1887     result = CryptEncrypt(hRSAKey, 0, TRUE, 0, abData, &dwLen, (DWORD)sizeof(abData));
1888     ok (result, "%08x\n", GetLastError());
1889     if (!result) return;
1890
1891     result = CryptDecrypt(hRSAKey, 0, TRUE, 0, abData, &dwLen);
1892     ok (result && dwLen == 12 && !memcmp(abData, "Wine rocks!", 12), "%08x\n", GetLastError());
1893     
1894     dwVal = 0xdeadbeef;
1895     dwLen = sizeof(DWORD);
1896     result = CryptGetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
1897     ok(result, "%08x\n", GetLastError());
1898     ok(dwVal ==
1899         (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
1900         broken(dwVal == 0xffffffff), /* Win9x/NT4 */
1901         "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
1902         " got %08x\n", dwVal);
1903
1904     /* An RSA key doesn't support salt */
1905     result = CryptGetKeyParam(hRSAKey, KP_SALT, NULL, &dwLen, 0);
1906     ok(!result && (GetLastError() == NTE_BAD_KEY || GetLastError() == NTE_NOT_FOUND /* Win7 */),
1907        "expected NTE_BAD_KEY or NTE_NOT_FOUND, got %08x\n", GetLastError());
1908
1909     /* The key exchange key's public key may be exported.. */
1910     result = CryptExportKey(hRSAKey, 0, PUBLICKEYBLOB, 0, NULL, &dwLen);
1911     ok(result, "%08x\n", GetLastError());
1912     /* but its private key may not be. */
1913     SetLastError(0xdeadbeef);
1914     result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
1915     ok((!result && GetLastError() == NTE_BAD_KEY_STATE) ||
1916         broken(result), /* Win9x/NT4 */
1917         "expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
1918     /* Setting the permissions of the key exchange key isn't allowed, either. */
1919     dwVal |= CRYPT_EXPORT;
1920     SetLastError(0xdeadbeef);
1921     result = CryptSetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE *)&dwVal, 0);
1922     ok(!result &&
1923         (GetLastError() == NTE_BAD_DATA || GetLastError() == NTE_BAD_FLAGS),
1924         "expected NTE_BAD_DATA or NTE_BAD_FLAGS, got %08x\n", GetLastError());
1925
1926     CryptDestroyKey(hRSAKey);
1927
1928     /* It is not allowed to use the signature key for encryption/decryption */
1929     result = CryptGetUserKey(hProv, AT_SIGNATURE, &hRSAKey);
1930     ok (result, "%08x\n", GetLastError());
1931     if (!result) return;
1932
1933     dwVal = 0xdeadbeef;
1934     dwLen = sizeof(DWORD);
1935     result = CryptGetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
1936     ok(result, "%08x\n", GetLastError());
1937     ok(dwVal ==
1938         (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
1939         broken(dwVal == 0xffffffff), /* Win9x/NT4 */
1940         "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
1941         " got %08x\n", dwVal);
1942
1943     /* The signature key's public key may also be exported.. */
1944     result = CryptExportKey(hRSAKey, 0, PUBLICKEYBLOB, 0, NULL, &dwLen);
1945     ok(result, "%08x\n", GetLastError());
1946     /* but its private key may not be. */
1947     SetLastError(0xdeadbeef);
1948     result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
1949     ok((!result && GetLastError() == NTE_BAD_KEY_STATE) ||
1950         broken(result), /* Win9x/NT4 */
1951         "expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
1952     /* Setting the permissions of the signature key isn't allowed, either. */
1953     dwVal |= CRYPT_EXPORT;
1954     SetLastError(0xdeadbeef);
1955     result = CryptSetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE *)&dwVal, 0);
1956     ok(!result &&
1957         (GetLastError() == NTE_BAD_DATA || GetLastError() == NTE_BAD_FLAGS),
1958         "expected NTE_BAD_DATA or NTE_BAD_FLAGS, got %08x\n", GetLastError());
1959
1960     dwLen = 12;
1961     result = CryptEncrypt(hRSAKey, 0, TRUE, 0, abData, &dwLen, (DWORD)sizeof(abData));
1962     ok (!result && GetLastError() == NTE_BAD_KEY, "%08x\n", GetLastError());
1963
1964     CryptDestroyKey(hRSAKey);
1965 }
1966
1967 static void test_import_export(void)
1968 {
1969     DWORD dwLen, dwDataLen, dwVal;
1970     HCRYPTKEY hPublicKey, hPrivKey;
1971     BOOL result;
1972     ALG_ID algID;
1973     BYTE emptyKey[2048], *exported_key;
1974     static BYTE abPlainPublicKey[84] = {
1975         0x06, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
1976         0x52, 0x53, 0x41, 0x31, 0x00, 0x02, 0x00, 0x00,
1977         0x01, 0x00, 0x01, 0x00, 0x11, 0x11, 0x11, 0x11,
1978         0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1979         0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1980         0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1981         0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1982         0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1983         0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1984         0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1985         0x11, 0x11, 0x11, 0x11
1986     };
1987     static BYTE priv_key_with_high_bit[] = {
1988         0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
1989         0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
1990         0x01, 0x00, 0x01, 0x00, 0xd5, 0xa2, 0x0d, 0x66,
1991         0xfe, 0x65, 0xb5, 0xf1, 0xc9, 0x6b, 0xf5, 0x58,
1992         0x04, 0x38, 0x2d, 0xf4, 0xa3, 0x5a, 0xda, 0x9e,
1993         0x95, 0x81, 0x85, 0x3d, 0x01, 0x07, 0xb2, 0x03,
1994         0x77, 0x70, 0x79, 0x6e, 0x6c, 0x26, 0x42, 0xa4,
1995         0x12, 0xfd, 0xaa, 0x29, 0x83, 0x04, 0xce, 0x91,
1996         0x90, 0x39, 0x5e, 0x49, 0x56, 0xfd, 0x0a, 0xe5,
1997         0xb1, 0xea, 0x3b, 0xb2, 0x70, 0xb0, 0x20, 0xc1,
1998         0x1f, 0x22, 0x07, 0x3e, 0x4d, 0xc0, 0x73, 0xfd,
1999         0x92, 0x8f, 0x87, 0xd8, 0xd1, 0xd1, 0x28, 0xd8,
2000         0x19, 0xd1, 0x93, 0x83, 0xe0, 0xb8, 0x9f, 0x53,
2001         0xf4, 0x6a, 0x7c, 0xcb, 0x10, 0x53, 0xd0, 0x37,
2002         0x02, 0xb4, 0xa5, 0xf7, 0xa2, 0x28, 0x6e, 0x26,
2003         0xef, 0x5c, 0x14, 0x01, 0x40, 0x1e, 0xa3, 0xe1,
2004         0xda, 0x76, 0xd0, 0x12, 0x84, 0xb7, 0x48, 0x7d,
2005         0xc8, 0x67, 0x5c, 0xb2, 0xd5, 0x2e, 0xaf, 0x8e,
2006         0x7d, 0x32, 0x59, 0x92, 0x01, 0xd6, 0x5b, 0x68,
2007         0x28, 0x9b, 0xb1, 0x6c, 0x69, 0xeb, 0x61, 0x5b,
2008         0x4b, 0x13, 0xe2, 0xbd, 0x7d, 0xbe, 0xce, 0xe8,
2009         0x41, 0x54, 0xca, 0xa8, 0xdd, 0xc7, 0xfe, 0x8b,
2010         0xdf, 0xf6, 0x55, 0x6c, 0x50, 0x11, 0xc8, 0x15,
2011         0x13, 0x42, 0x59, 0x9f, 0xbb, 0xea, 0x73, 0x78,
2012         0x7b, 0x22, 0x8d, 0x96, 0x62, 0xe5, 0xda, 0xa2,
2013         0x85, 0x5c, 0x20, 0x74, 0x9f, 0x1c, 0x12, 0xf2,
2014         0x48, 0x06, 0x1a, 0xc6, 0xd5, 0x94, 0xec, 0x31,
2015         0x6b, 0xb6, 0x7b, 0x54, 0x61, 0x77, 0xec, 0x7c,
2016         0x6f, 0xb7, 0x55, 0x3d, 0x6b, 0x98, 0x05, 0xd7,
2017         0x8a, 0x73, 0x25, 0xf2, 0x8f, 0xe4, 0xb8, 0x8d,
2018         0x27, 0x18, 0x0d, 0x05, 0xba, 0x23, 0x54, 0x37,
2019         0x10, 0xf0, 0x1c, 0x41, 0xa6, 0xae, 0x4c, 0x2a,
2020         0x6a, 0x2f, 0x7f, 0x68, 0x43, 0x86, 0xe7, 0x9c,
2021         0xfd, 0x9e, 0xf1, 0xfe, 0x84, 0xe3, 0xb6, 0x99,
2022         0x51, 0xfe, 0x1e, 0xbd, 0x01, 0xc6, 0x10, 0xef,
2023         0x88, 0xa4, 0xd8, 0x53, 0x14, 0x88, 0x15, 0xc9,
2024         0xe5, 0x86, 0xe2, 0x8d, 0x85, 0x2e, 0x0d, 0xec,
2025         0x15, 0xa7, 0x48, 0xfa, 0x18, 0xfb, 0x01, 0x8d,
2026         0x2b, 0x90, 0x70, 0x7f, 0x78, 0xb1, 0x33, 0x7e,
2027         0xfe, 0x82, 0x40, 0x5f, 0x4a, 0x97, 0xc2, 0x42,
2028         0x22, 0xd5, 0x5f, 0xbc, 0xbd, 0xab, 0x26, 0x98,
2029         0xcd, 0xb5, 0xdf, 0x7e, 0xa0, 0x68, 0xa7, 0x12,
2030         0x9e, 0xa5, 0xa2, 0x90, 0x85, 0xc5, 0xca, 0x73,
2031         0x4a, 0x59, 0x8a, 0xec, 0xcf, 0xdd, 0x65, 0x5d,
2032         0xc1, 0xaa, 0x86, 0x53, 0xd5, 0xde, 0xbb, 0x23,
2033         0x24, 0xb8, 0x9b, 0x74, 0x03, 0x20, 0xb4, 0xf0,
2034         0xe4, 0xdd, 0xd2, 0x03, 0xfd, 0x67, 0x55, 0x19,
2035         0x28, 0x1d, 0xc1, 0xb8, 0xa5, 0x89, 0x0e, 0xc0,
2036         0x80, 0x9d, 0xdd, 0xda, 0x9d, 0x30, 0x5c, 0xc8,
2037         0xbb, 0xfe, 0x8f, 0xce, 0xd5, 0xf6, 0xdf, 0xfa,
2038         0x14, 0xaf, 0xe4, 0xba, 0xb0, 0x84, 0x45, 0xd8,
2039         0x67, 0xa7, 0xd0, 0xce, 0x89, 0x2a, 0x30, 0x8c,
2040         0xfa, 0xe9, 0x65, 0xa4, 0x21, 0x2d, 0x6b, 0xa2,
2041         0x9b, 0x8f, 0x92, 0xbd, 0x3a, 0x10, 0x71, 0x12,
2042         0xc2, 0x02, 0x3d, 0xd5, 0x83, 0x1d, 0xfa, 0x42,
2043         0xb7, 0x48, 0x1b, 0x31, 0xe3, 0x82, 0x90, 0x2d,
2044         0x91, 0x59, 0xf9, 0x38, 0x52, 0xe5, 0xdb, 0xc1,
2045         0x4d, 0x3a, 0xe6, 0x9b, 0x6a, 0xbb, 0xea, 0xa4,
2046         0x8d, 0x5e, 0xc4, 0x00, 0x01, 0xb8, 0xec, 0x91,
2047         0xc1, 0xdb, 0x63, 0xbd, 0x57, 0xb6, 0x26, 0x15,
2048         0xb6, 0x3e, 0xa2, 0xdf, 0x62, 0x8d, 0xa8, 0xbe,
2049         0xe1, 0xf1, 0x39, 0xbd, 0x18, 0xd2, 0x6f, 0xd7,
2050         0xda, 0xdc, 0x71, 0x30, 0xf1, 0x21, 0x71, 0xa4,
2051         0x08, 0x43, 0x46, 0xdf, 0x50, 0xbd, 0x3c, 0x60,
2052         0x5b, 0x63, 0x35, 0xe3, 0x37, 0x5b, 0x25, 0x17,
2053         0x54, 0x5e, 0x68, 0x60, 0xb6, 0x49, 0xef, 0x6e,
2054         0x09, 0xef, 0xda, 0x90, 0x3e, 0xd4, 0x09, 0x33,
2055         0x36, 0x57, 0x9a, 0x14, 0xbd, 0xf7, 0xb1, 0x98,
2056         0x30, 0x42, 0x03, 0x84, 0x61, 0xeb, 0x8e, 0x50,
2057         0xdc, 0x6a, 0x93, 0x1b, 0x32, 0x51, 0xf9, 0xc6,
2058         0xc2, 0x19, 0xb3, 0x5d, 0xe2, 0xf8, 0xc5, 0x8f,
2059         0x68, 0xaa, 0x1d, 0xdb, 0xd3, 0x7f, 0x8d, 0x98,
2060         0x9c, 0x16, 0x8c, 0xc3, 0xcd, 0xd9, 0xdb, 0x08,
2061         0xe6, 0x36, 0x60, 0xb6, 0x36, 0xdc, 0x1d, 0x59,
2062         0xb6, 0x5f, 0x01, 0x5e
2063     };
2064     static const BYTE expected_exported_priv_key[] = {
2065         0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
2066         0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
2067         0x01, 0x00, 0x01, 0x00, 0xd5, 0xa2, 0x0d, 0x66,
2068         0xfe, 0x65, 0xb5, 0xf1, 0xc9, 0x6b, 0xf5, 0x58,
2069         0x04, 0x38, 0x2d, 0xf4, 0xa3, 0x5a, 0xda, 0x9e,
2070         0x95, 0x81, 0x85, 0x3d, 0x01, 0x07, 0xb2, 0x03,
2071         0x77, 0x70, 0x79, 0x6e, 0x6c, 0x26, 0x42, 0xa4,
2072         0x12, 0xfd, 0xaa, 0x29, 0x83, 0x04, 0xce, 0x91,
2073         0x90, 0x39, 0x5e, 0x49, 0x56, 0xfd, 0x0a, 0xe5,
2074         0xb1, 0xea, 0x3b, 0xb2, 0x70, 0xb0, 0x20, 0xc1,
2075         0x1f, 0x22, 0x07, 0x3e, 0x4d, 0xc0, 0x73, 0xfd,
2076         0x92, 0x8f, 0x87, 0xd8, 0xd1, 0xd1, 0x28, 0xd8,
2077         0x19, 0xd1, 0x93, 0x83, 0xe0, 0xb8, 0x9f, 0x53,
2078         0xf4, 0x6a, 0x7c, 0xcb, 0x10, 0x53, 0xd0, 0x37,
2079         0x02, 0xb4, 0xa5, 0xf7, 0xa2, 0x28, 0x6e, 0x26,
2080         0xef, 0x5c, 0x14, 0x01, 0x40, 0x1e, 0xa3, 0xe1,
2081         0xda, 0x76, 0xd0, 0x12, 0x84, 0xb7, 0x48, 0x7d,
2082         0xc8, 0x67, 0x5c, 0xb2, 0xd5, 0x2e, 0xaf, 0x8e,
2083         0x7d, 0x32, 0x59, 0x92, 0x01, 0xd6, 0x5b, 0x68,
2084         0x28, 0x9b, 0xb1, 0x6c, 0x69, 0xeb, 0x61, 0x5b,
2085         0x4b, 0x13, 0xe2, 0xbd, 0x7d, 0xbe, 0xce, 0xe8,
2086         0x41, 0x54, 0xca, 0xa8, 0xdd, 0xc7, 0xfe, 0x8b,
2087         0xdf, 0xf6, 0x55, 0x6c, 0x50, 0x11, 0xc8, 0x15,
2088         0x13, 0x42, 0x59, 0x9f, 0xbb, 0xea, 0x73, 0x78,
2089         0x7b, 0x22, 0x8d, 0x96, 0x62, 0xe5, 0xda, 0xa2,
2090         0x85, 0x5c, 0x20, 0x74, 0x9f, 0x1c, 0x12, 0xf2,
2091         0x48, 0x06, 0x1a, 0xc6, 0xd5, 0x94, 0xec, 0x31,
2092         0x6b, 0xb6, 0x7b, 0x54, 0x61, 0x77, 0xec, 0x7c,
2093         0x6f, 0xb7, 0x55, 0x3d, 0x6b, 0x98, 0x05, 0xd7,
2094         0x8a, 0x73, 0x25, 0xf2, 0x8f, 0xe4, 0xb8, 0x8d,
2095         0x27, 0x18, 0x0d, 0x05, 0xba, 0x23, 0x54, 0x37,
2096         0x10, 0xf0, 0x1c, 0x41, 0xa6, 0xae, 0x4c, 0x2a,
2097         0x6a, 0x2f, 0x7f, 0x68, 0x43, 0x86, 0xe7, 0x9c,
2098         0xfd, 0x9e, 0xf1, 0xfe, 0x84, 0xe3, 0xb6, 0x99,
2099         0x51, 0xfe, 0x1e, 0xbd, 0x01, 0xc6, 0x10, 0xef,
2100         0x88, 0xa4, 0xd8, 0x53, 0x14, 0x88, 0x15, 0xc9,
2101         0xe5, 0x86, 0xe2, 0x8d, 0x85, 0x2e, 0x0d, 0xec,
2102         0x15, 0xa7, 0x48, 0xfa, 0x18, 0xfb, 0x01, 0x8d,
2103         0x2b, 0x90, 0x70, 0x7f, 0x78, 0xb1, 0x33, 0x7e,
2104         0xfe, 0x82, 0x40, 0x5f, 0x4a, 0x97, 0xc2, 0x42,
2105         0x22, 0xd5, 0x5f, 0xbc, 0xbd, 0xab, 0x26, 0x98,
2106         0xcd, 0xb5, 0xdf, 0x7e, 0xa0, 0x68, 0xa7, 0x12,
2107         0x9e, 0xa5, 0xa2, 0x90, 0x85, 0xc5, 0xca, 0x73,
2108         0x4a, 0x59, 0x8a, 0xec, 0xcf, 0xdd, 0x65, 0x5d,
2109         0xc1, 0xaa, 0x86, 0x53, 0xd5, 0xde, 0xbb, 0x23,
2110         0x24, 0xb8, 0x9b, 0x74, 0x03, 0x20, 0xb4, 0xf0,
2111         0xe4, 0xdd, 0xd2, 0x03, 0xfd, 0x67, 0x55, 0x19,
2112         0x28, 0x1d, 0xc1, 0xb8, 0xa5, 0x89, 0x0e, 0xc0,
2113         0x80, 0x9d, 0xdd, 0xda, 0x9d, 0x30, 0x5c, 0xc8,
2114         0xbb, 0xfe, 0x8f, 0xce, 0xd5, 0xf6, 0xdf, 0xfa,
2115         0x14, 0xaf, 0xe4, 0xba, 0xb0, 0x84, 0x45, 0xd8,
2116         0x67, 0xa7, 0xd0, 0xce, 0x89, 0x2a, 0x30, 0x8c,
2117         0xfa, 0xe9, 0x65, 0xa4, 0x21, 0x2d, 0x6b, 0xa2,
2118         0x9b, 0x8f, 0x92, 0xbd, 0x3a, 0x10, 0x71, 0x12,
2119         0xc2, 0x02, 0x3d, 0xd5, 0x83, 0x1d, 0xfa, 0x42,
2120         0xb7, 0x48, 0x1b, 0x31, 0xe3, 0x82, 0x90, 0x2d,
2121         0x91, 0x59, 0xf9, 0x38, 0x52, 0xe5, 0xdb, 0xc1,
2122         0x4d, 0x3a, 0xe6, 0x9b, 0x6a, 0xbb, 0xea, 0xa4,
2123         0x8d, 0x5e, 0xc4, 0x00, 0x01, 0xb8, 0xec, 0x91,
2124         0xc1, 0xdb, 0x63, 0xbd, 0x57, 0xb6, 0x26, 0x15,
2125         0xb6, 0x3e, 0xa2, 0xdf, 0x62, 0x8d, 0xa8, 0xbe,
2126         0xe1, 0xf1, 0x39, 0xbd, 0x18, 0xd2, 0x6f, 0xd7,
2127         0xda, 0xdc, 0x71, 0x30, 0xf1, 0x21, 0x71, 0xa4,
2128         0x08, 0x43, 0x46, 0xdf, 0x50, 0xbd, 0x3c, 0x60,
2129         0x5b, 0x63, 0x35, 0xe3, 0x37, 0x5b, 0x25, 0x17,
2130         0x54, 0x5e, 0x68, 0x60, 0xb6, 0x49, 0xef, 0x6e,
2131         0x09, 0xef, 0xda, 0x90, 0x3e, 0xd4, 0x09, 0x33,
2132         0x36, 0x57, 0x9a, 0x14, 0xbd, 0xf7, 0xb1, 0x98,
2133         0x30, 0x42, 0x03, 0x84, 0x61, 0xeb, 0x8e, 0x50,
2134         0xdc, 0x6a, 0x93, 0x1b, 0x32, 0x51, 0xf9, 0xc6,
2135         0xc2, 0x19, 0xb3, 0x5d, 0xe2, 0xf8, 0xc5, 0x8f,
2136         0x68, 0xaa, 0x1d, 0xdb, 0xd3, 0x7f, 0x8d, 0x98,
2137         0x9c, 0x16, 0x8c, 0xc3, 0xcd, 0xd9, 0xdb, 0x08,
2138         0xe6, 0x36, 0x60, 0xb6, 0x36, 0xdc, 0x1d, 0x59,
2139         0xb6, 0x5f, 0x01, 0x5e
2140     };
2141
2142     dwLen=84;
2143     result = CryptImportKey(hProv, abPlainPublicKey, dwLen, 0, 0, &hPublicKey);
2144     ok(result, "failed to import the public key\n");
2145
2146     dwDataLen=sizeof(algID);
2147     result = CryptGetKeyParam(hPublicKey, KP_ALGID, (LPBYTE)&algID, &dwDataLen, 0);
2148     ok(result, "failed to get the KP_ALGID from the imported public key\n");
2149     ok(algID == CALG_RSA_KEYX, "Expected CALG_RSA_KEYX, got %x\n", algID);
2150         
2151     dwVal = 0xdeadbeef;
2152     dwDataLen = sizeof(DWORD);
2153     result = CryptGetKeyParam(hPublicKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwDataLen, 0);
2154     ok(result, "%08x\n", GetLastError());
2155     ok(dwVal ==
2156         (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
2157         broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2158         "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
2159         " got %08x\n", dwVal);
2160     result = CryptExportKey(hPublicKey, 0, PUBLICKEYBLOB, 0, emptyKey, &dwLen);
2161     ok(result, "failed to export the fresh imported public key\n");
2162     ok(dwLen == 84, "Expected exported key to be 84 bytes long but got %d bytes.\n",dwLen);
2163     ok(!memcmp(emptyKey, abPlainPublicKey, dwLen), "exported key is different from the imported key\n");
2164
2165     CryptDestroyKey(hPublicKey);
2166
2167     result = CryptImportKey(hProv, priv_key_with_high_bit,
2168         sizeof(priv_key_with_high_bit), 0, CRYPT_EXPORTABLE, &hPrivKey);
2169     ok(result, "CryptImportKey failed: %08x\n", GetLastError());
2170
2171     result = CryptExportKey(hPrivKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwDataLen);
2172     ok(result, "CryptExportKey failed: %08x\n", GetLastError());
2173     exported_key = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
2174     result = CryptExportKey(hPrivKey, 0, PRIVATEKEYBLOB, 0, exported_key,
2175         &dwDataLen);
2176     ok(result, "CryptExportKey failed: %08x\n", GetLastError());
2177
2178     ok(dwDataLen == sizeof(expected_exported_priv_key), "unexpected size %d\n",
2179         dwDataLen);
2180     ok(!memcmp(exported_key, expected_exported_priv_key, dwDataLen),
2181         "unexpected value\n");
2182
2183     HeapFree(GetProcessHeap(), 0, exported_key);
2184
2185     CryptDestroyKey(hPrivKey);
2186 }
2187
2188 static void test_import_hmac(void)
2189 {
2190     /* Test cases from RFC 2202, section 3 */
2191     static const struct rfc2202_test_case {
2192         const char *key;
2193         DWORD key_len;
2194         const char *data;
2195         const DWORD data_len;
2196         const char *digest;
2197     } cases[] = {
2198         { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
2199           "\x0b\x0b\x0b\x0b", 20,
2200           "Hi There", 8,
2201           "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e"
2202           "\xf1\x46\xbe\x00" },
2203         { "Jefe", 4,
2204           "what do ya want for nothing?", 28,
2205           "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c"
2206           "\x25\x9a\x7c\x79" },
2207         { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
2208           "\xaa\xaa\xaa\xaa", 20,
2209           "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
2210           "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
2211           "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
2212           "\xdd\xdd", 50,
2213           "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f"
2214           "\x63\xf1\x75\xd3" },
2215         { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
2216           "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
2217           "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
2218           "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
2219           "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
2220           "\xcd\xcd", 50,
2221           "\x4c\x90\x07\xF4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c"
2222           "\x2d\x72\x35\xda" },
2223         { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
2224           "\x0c\x0c\x0c\x0c", 20,
2225           "Test With Truncation", 20,
2226           "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32"
2227           "\x4a\x9a\x5a\x04" },
2228         { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
2229           "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
2230           "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
2231           "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
2232           "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
2233           80,
2234           "Test Using Larger Than Block-Size Key - Hash Key First", 54,
2235           "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55"
2236           "\xed\x40\x21\x12" },
2237         { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
2238           "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
2239           "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
2240           "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
2241           "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
2242           80,
2243           "Test Using Larger Than Block-Size Key and Larger "
2244           "Than One Block-Size Data", 73,
2245           "\xe8\xe9\x9D\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08"
2246           "\xbb\xff\x1a\x91" }
2247     };
2248     DWORD i;
2249
2250     for (i = 0; i < sizeof(cases) / sizeof(cases[0]); i++)
2251     {
2252         const struct rfc2202_test_case *test_case = &cases[i];
2253         DWORD size = sizeof(BLOBHEADER) + sizeof(DWORD) + test_case->key_len;
2254         BYTE *blob = HeapAlloc(GetProcessHeap(), 0, size);
2255
2256         if (blob)
2257         {
2258             BLOBHEADER *header = (BLOBHEADER *)blob;
2259             DWORD *key_len = (DWORD *)(header + 1);
2260             BYTE *key_bytes = (BYTE *)(key_len + 1);
2261             BOOL result;
2262             HCRYPTKEY key;
2263
2264             header->bType = PLAINTEXTKEYBLOB;
2265             header->bVersion = CUR_BLOB_VERSION;
2266             header->reserved = 0;
2267             header->aiKeyAlg = CALG_RC2;
2268             *key_len = test_case->key_len;
2269             memcpy(key_bytes, test_case->key, *key_len);
2270             result = CryptImportKey(hProv, blob, size, 0, CRYPT_IPSEC_HMAC_KEY, &key);
2271             ok(result || broken(GetLastError() == NTE_BAD_FLAGS /* Win2k */), "CryptImportKey failed on test case %d: %08x\n", i, GetLastError());
2272             if (result)
2273             {
2274                 HCRYPTHASH hash;
2275                 HMAC_INFO hmac_info = { CALG_SHA1, 0 };
2276                 BYTE digest[20];
2277                 DWORD digest_size;
2278
2279                 result = CryptCreateHash(hProv, CALG_HMAC, key, 0, &hash);
2280                 ok(result, "CryptCreateHash failed on test case %d: %08x\n", i, GetLastError());
2281                 result = CryptSetHashParam(hash, HP_HMAC_INFO, (BYTE *)&hmac_info, 0);
2282                 ok(result, "CryptSetHashParam failed on test case %d: %08x\n", i, GetLastError());
2283                 result = CryptHashData(hash, (const BYTE *)test_case->data, test_case->data_len, 0);
2284                 ok(result, "CryptHashData failed on test case %d: %08x\n", i, GetLastError());
2285                 digest_size = sizeof(digest);
2286                 result = CryptGetHashParam(hash, HP_HASHVAL, digest, &digest_size, 0);
2287                 ok(result, "CryptGetHashParam failed on test case %d: %08x\n", i, GetLastError());
2288                 ok(!memcmp(digest, test_case->digest, sizeof(digest)), "Unexpected value on test case %d\n", i);
2289                 CryptDestroyHash(hash);
2290                 CryptDestroyKey(key);
2291             }
2292             HeapFree(GetProcessHeap(), 0, blob);
2293         }
2294     }
2295 }
2296         
2297 static void test_schannel_provider(void)
2298 {
2299     HCRYPTPROV hProv;
2300     HCRYPTKEY hRSAKey, hMasterSecret, hServerWriteKey, hServerWriteMACKey;
2301     HCRYPTHASH hMasterHash, hTLS1PRF, hHMAC;
2302     BOOL result;
2303     DWORD dwLen;
2304     SCHANNEL_ALG saSChannelAlg;
2305     CRYPT_DATA_BLOB data_blob;
2306     HMAC_INFO hmacInfo = { CALG_MD5, NULL, 0, NULL, 0 };
2307     BYTE abTLS1Master[140] = {
2308         0x01, 0x02, 0x00, 0x00, 0x06, 0x4c, 0x00, 0x00, 
2309         0x00, 0xa4, 0x00, 0x00, 0x5b, 0x13, 0xc7, 0x68, 
2310         0xd8, 0x55, 0x23, 0x5d, 0xbc, 0xa6, 0x9d, 0x97, 
2311         0x0e, 0xcd, 0x6b, 0xcf, 0xc0, 0xdc, 0xc5, 0x53, 
2312         0x28, 0xa0, 0xca, 0xc1, 0x63, 0x4e, 0x3a, 0x24, 
2313         0x22, 0xe5, 0x4d, 0x15, 0xbb, 0xa5, 0x06, 0xc3, 
2314         0x98, 0x25, 0xdc, 0x35, 0xd3, 0xdb, 0xab, 0xb8, 
2315         0x44, 0x1b, 0xfe, 0x63, 0x88, 0x7c, 0x2e, 0x6d, 
2316         0x34, 0xd9, 0x0f, 0x7e, 0x2f, 0xc2, 0xb2, 0x6e, 
2317         0x56, 0xfa, 0xab, 0xb2, 0x88, 0xf6, 0x15, 0x6e, 
2318         0xa8, 0xcd, 0x70, 0x16, 0x94, 0x61, 0x07, 0x40, 
2319         0x9e, 0x25, 0x22, 0xf8, 0x64, 0x9f, 0xcc, 0x0b, 
2320         0xf1, 0x92, 0x4d, 0xfe, 0xc3, 0x5d, 0x52, 0xdb, 
2321         0x0f, 0xff, 0x12, 0x0f, 0x49, 0x43, 0x7d, 0xc6, 
2322         0x52, 0x61, 0xb0, 0x06, 0xc8, 0x1b, 0x90, 0xac, 
2323         0x09, 0x7e, 0x4b, 0x95, 0x69, 0x3b, 0x0d, 0x41, 
2324         0x1b, 0x4c, 0x65, 0x75, 0x4d, 0x85, 0x16, 0xc4, 
2325         0xd3, 0x1e, 0x82, 0xb3
2326     };
2327     BYTE abServerSecret[33] = "Super Secret Server Secret 12345";
2328     BYTE abClientSecret[33] = "Super Secret Client Secret 12345";
2329     BYTE abHashedHandshakes[37] = "123456789012345678901234567890123456";
2330     BYTE abClientFinished[16] = "client finished";
2331     BYTE abData[16] = "Wine rocks!";
2332     BYTE abMD5Hash[16];
2333     static const BYTE abEncryptedData[16] = {
2334         0x13, 0xd2, 0xdd, 0xeb, 0x6c, 0x3f, 0xbe, 0xb2,
2335         0x04, 0x86, 0xb5, 0xe5, 0x08, 0xe5, 0xf3, 0x0d    
2336     };
2337     static const BYTE abPRF[16] = {
2338         0xa8, 0xb2, 0xa6, 0xef, 0x83, 0x4e, 0x74, 0xb1,
2339         0xf3, 0xb1, 0x51, 0x5a, 0x1a, 0x2b, 0x11, 0x31
2340     };
2341     static const BYTE abMD5[16] = {
2342         0xe1, 0x65, 0x3f, 0xdb, 0xbb, 0x3d, 0x99, 0x3c,
2343         0x3d, 0xca, 0x6a, 0x6f, 0xfa, 0x15, 0x4e, 0xaa
2344     };
2345     
2346     result = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET);
2347     if (!result)
2348     {
2349         win_skip("no PROV_RSA_SCHANNEL support\n");
2350         return;
2351     }
2352     ok (result, "%08x\n", GetLastError());
2353     if (result)
2354         CryptReleaseContext(hProv, 0);
2355
2356     result = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_VERIFYCONTEXT);
2357     ok (result, "%08x\n", GetLastError());
2358     if (!result) return;
2359     
2360     /* To get deterministic results, we import the TLS1 master secret (which
2361      * is typically generated from a random generator). Therefore, we need
2362      * an RSA key. */
2363     dwLen = (DWORD)sizeof(abPlainPrivateKey);
2364     result = CryptImportKey(hProv, abPlainPrivateKey, dwLen, 0, 0, &hRSAKey);
2365     ok (result, "%08x\n", GetLastError());
2366     if (!result) return;
2367
2368     dwLen = (DWORD)sizeof(abTLS1Master);
2369     result = CryptImportKey(hProv, abTLS1Master, dwLen, hRSAKey, 0, &hMasterSecret);
2370     ok (result, "%08x\n", GetLastError());
2371     if (!result) return;    
2372
2373     /* Deriving a hash from the master secret. This is due to the CryptoAPI architecture.
2374      * (Keys can only be derived from hashes, not from other keys.)
2375      * The hash can't be created yet because the key doesn't have the client
2376      * random or server random set.
2377      */
2378     result = CryptCreateHash(hProv, CALG_SCHANNEL_MASTER_HASH, hMasterSecret, 0, &hMasterHash);
2379     ok (!result && GetLastError() == ERROR_INVALID_PARAMETER,
2380         "expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2381
2382     /* Setting the TLS1 client and server random parameters, as well as the 
2383      * MAC and encryption algorithm parameters. */
2384     data_blob.cbData = 33;
2385     data_blob.pbData = abClientSecret;
2386     result = CryptSetKeyParam(hMasterSecret, KP_CLIENT_RANDOM, (BYTE*)&data_blob, 0);
2387     ok (result, "%08x\n", GetLastError());
2388     if (!result) return;
2389
2390     data_blob.cbData = 33;
2391     data_blob.pbData = abServerSecret;
2392     result = CryptSetKeyParam(hMasterSecret, KP_SERVER_RANDOM, (BYTE*)&data_blob, 0);
2393     ok (result, "%08x\n", GetLastError());
2394     if (!result) return;
2395
2396     result = CryptCreateHash(hProv, CALG_SCHANNEL_MASTER_HASH, hMasterSecret, 0, &hMasterHash);
2397     ok (result, "%08x\n", GetLastError());
2398     if (!result) return;
2399
2400     /* Deriving the server write encryption key from the master hash can't
2401      * succeed before the encryption key algorithm is set.
2402      */
2403     result = CryptDeriveKey(hProv, CALG_SCHANNEL_ENC_KEY, hMasterHash, CRYPT_SERVER, &hServerWriteKey);
2404     ok (!result && GetLastError() == NTE_BAD_FLAGS,
2405         "expected NTE_BAD_FLAGS, got %08x\n", GetLastError());
2406
2407     CryptDestroyHash(hMasterHash);
2408
2409     saSChannelAlg.dwUse = SCHANNEL_ENC_KEY;
2410     saSChannelAlg.Algid = CALG_DES;
2411     saSChannelAlg.cBits = 64;
2412     saSChannelAlg.dwFlags = 0;
2413     saSChannelAlg.dwReserved = 0;
2414     result = CryptSetKeyParam(hMasterSecret, KP_SCHANNEL_ALG, (PBYTE)&saSChannelAlg, 0);
2415     ok (result, "%08x\n", GetLastError());
2416     if (!result) return;
2417
2418     saSChannelAlg.dwUse = SCHANNEL_MAC_KEY;
2419     saSChannelAlg.Algid = CALG_MD5;
2420     saSChannelAlg.cBits = 128;
2421     saSChannelAlg.dwFlags = 0;
2422     saSChannelAlg.dwReserved = 0;
2423     result = CryptSetKeyParam(hMasterSecret, KP_SCHANNEL_ALG, (PBYTE)&saSChannelAlg, 0);
2424     ok (result, "%08x\n", GetLastError());
2425     if (!result) return;
2426
2427     result = CryptCreateHash(hProv, CALG_SCHANNEL_MASTER_HASH, hMasterSecret, 0, &hMasterHash);
2428     ok (result, "%08x\n", GetLastError());
2429     if (!result) return;
2430
2431     /* Deriving the server write encryption key from the master hash */
2432     result = CryptDeriveKey(hProv, CALG_SCHANNEL_ENC_KEY, hMasterHash, CRYPT_SERVER, &hServerWriteKey);
2433     ok (result, "%08x\n", GetLastError());
2434     if (!result) return;
2435
2436     /* Encrypting some data with the server write encryption key and checking the result. */
2437     dwLen = 12;
2438     result = CryptEncrypt(hServerWriteKey, 0, TRUE, 0, abData, &dwLen, 16);
2439     ok (result && (dwLen == 16) && !memcmp(abData, abEncryptedData, 16), "%08x\n", GetLastError());
2440
2441     /* Second test case: Test the TLS1 pseudo random number function. */
2442     result = CryptCreateHash(hProv, CALG_TLS1PRF, hMasterSecret, 0, &hTLS1PRF);
2443     ok (result, "%08x\n", GetLastError());
2444     if (!result) return;
2445
2446     /* Set the label and seed parameters for the random number function */
2447     data_blob.cbData = 36;
2448     data_blob.pbData = abHashedHandshakes;
2449     result = CryptSetHashParam(hTLS1PRF, HP_TLS1PRF_SEED, (BYTE*)&data_blob, 0);
2450     ok (result, "%08x\n", GetLastError());
2451     if (!result) return;
2452
2453     data_blob.cbData = 15;
2454     data_blob.pbData = abClientFinished;
2455     result = CryptSetHashParam(hTLS1PRF, HP_TLS1PRF_LABEL, (BYTE*)&data_blob, 0);
2456     ok (result, "%08x\n", GetLastError());
2457     if (!result) return;
2458
2459     /* Generate some pseudo random bytes and check if they are correct. */
2460     dwLen = (DWORD)sizeof(abData);
2461     result = CryptGetHashParam(hTLS1PRF, HP_HASHVAL, abData, &dwLen, 0);
2462     ok (result && (dwLen==(DWORD)sizeof(abData)) && !memcmp(abData, abPRF, sizeof(abData)), 
2463         "%08x\n", GetLastError());
2464
2465     /* Third test case. Derive the server write mac key. Derive an HMAC object from this one.
2466      * Hash some data with the HMAC. Compare results. */
2467     result = CryptDeriveKey(hProv, CALG_SCHANNEL_MAC_KEY, hMasterHash, CRYPT_SERVER, &hServerWriteMACKey);
2468     ok (result, "%08x\n", GetLastError());
2469     if (!result) return;
2470     
2471     result = CryptCreateHash(hProv, CALG_HMAC, hServerWriteMACKey, 0, &hHMAC);
2472     ok (result, "%08x\n", GetLastError());
2473     if (!result) return;
2474
2475     result = CryptSetHashParam(hHMAC, HP_HMAC_INFO, (PBYTE)&hmacInfo, 0);
2476     ok (result, "%08x\n", GetLastError());
2477     if (!result) return;
2478
2479     result = CryptHashData(hHMAC, abData, (DWORD)sizeof(abData), 0);
2480     ok (result, "%08x\n", GetLastError());
2481     if (!result) return;
2482
2483     dwLen = (DWORD)sizeof(abMD5Hash);
2484     result = CryptGetHashParam(hHMAC, HP_HASHVAL, abMD5Hash, &dwLen, 0);
2485     ok (result && (dwLen == 16) && !memcmp(abMD5Hash, abMD5, 16), "%08x\n", GetLastError());
2486
2487     CryptDestroyHash(hHMAC);
2488     CryptDestroyHash(hTLS1PRF);
2489     CryptDestroyHash(hMasterHash);
2490     CryptDestroyKey(hServerWriteMACKey);
2491     CryptDestroyKey(hServerWriteKey);
2492     CryptDestroyKey(hRSAKey);
2493     CryptDestroyKey(hMasterSecret);
2494     CryptReleaseContext(hProv, 0);
2495     CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_DELETEKEYSET);
2496 }
2497
2498 /* Test that a key can be used to encrypt data and exported, and that, when
2499  * the exported key is imported again, can be used to decrypt the original
2500  * data again.
2501  */
2502 static void test_rsa_round_trip(void)
2503 {
2504     static const char test_string[] = "Well this is a fine how-do-you-do.";
2505     HCRYPTPROV prov;
2506     HCRYPTKEY signKey, keyExchangeKey;
2507     BOOL result;
2508     BYTE data[256], *exportedKey;
2509     DWORD dataLen, keyLen;
2510
2511     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2512      CRYPT_DELETEKEYSET);
2513
2514     /* Generate a new key... */
2515     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2516      CRYPT_NEWKEYSET);
2517     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2518     result = CryptGenKey(prov, CALG_RSA_KEYX, CRYPT_EXPORTABLE, &signKey);
2519     ok(result, "CryptGenKey with CALG_RSA_KEYX failed with error %08x\n", GetLastError());
2520     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &keyExchangeKey);
2521     ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
2522     /* encrypt some data with it... */
2523     memcpy(data, test_string, strlen(test_string) + 1);
2524     dataLen = strlen(test_string) + 1;
2525     result = CryptEncrypt(keyExchangeKey, 0, TRUE, 0, data, &dataLen,
2526                           sizeof(data));
2527     ok(result || broken(GetLastError() == NTE_BAD_KEY /* Win9x/2000 */) ||
2528        broken(GetLastError() == NTE_PERM /* NT4 */),
2529        "CryptEncrypt failed: %08x\n", GetLastError());
2530     /* export the key... */
2531     result = CryptExportKey(keyExchangeKey, 0, PRIVATEKEYBLOB, 0, NULL,
2532                             &keyLen);
2533     ok(result, "CryptExportKey failed: %08x\n", GetLastError());
2534     exportedKey = HeapAlloc(GetProcessHeap(), 0, keyLen);
2535     result = CryptExportKey(keyExchangeKey, 0, PRIVATEKEYBLOB, 0, exportedKey,
2536                             &keyLen);
2537     ok(result, "CryptExportKey failed: %08x\n", GetLastError());
2538     /* destroy the key... */
2539     CryptDestroyKey(keyExchangeKey);
2540     CryptDestroyKey(signKey);
2541     /* import the key again... */
2542     result = CryptImportKey(prov, exportedKey, keyLen, 0, 0, &keyExchangeKey);
2543     ok(result, "CryptImportKey failed: %08x\n", GetLastError());
2544     HeapFree(GetProcessHeap(), 0, exportedKey);
2545     /* and decrypt the data encrypted with the original key with the imported
2546      * key.
2547      */
2548     result = CryptDecrypt(keyExchangeKey, 0, TRUE, 0, data, &dataLen);
2549     ok(result || broken(GetLastError() == NTE_BAD_KEY /* Win9x/2000 */) ||
2550        broken(GetLastError() == NTE_PERM /* NT4 */),
2551        "CryptDecrypt failed: %08x\n", GetLastError());
2552     if (result)
2553     {
2554         ok(dataLen == sizeof(test_string), "unexpected size %d\n", dataLen);
2555         ok(!memcmp(data, test_string, sizeof(test_string)), "unexpected value\n");
2556     }
2557     CryptDestroyKey(keyExchangeKey);
2558     CryptReleaseContext(prov, 0);
2559
2560     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2561      CRYPT_DELETEKEYSET);
2562 }
2563
2564 static void test_enum_container(void)
2565 {
2566     BYTE abContainerName[MAX_PATH + 2]; /* Larger than maximum name len */
2567     DWORD dwBufferLen;
2568     BOOL result, fFound = FALSE;
2569
2570     /* If PP_ENUMCONTAINERS is queried with CRYPT_FIRST and abData == NULL, it returns
2571      * the maximum legal length of container names (which is MAX_PATH + 1 == 261) */
2572     SetLastError(0xdeadbeef);
2573     result = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, NULL, &dwBufferLen, CRYPT_FIRST);
2574     ok (result, "%08x\n", GetLastError());
2575     ok (dwBufferLen == MAX_PATH + 1 ||
2576         broken(dwBufferLen != MAX_PATH + 1), /* Win9x, WinMe, NT4 */
2577         "Expected dwBufferLen to be (MAX_PATH + 1), it was : %d\n", dwBufferLen);
2578
2579     /* If the result fits into abContainerName dwBufferLen is left untouched */
2580     dwBufferLen = (DWORD)sizeof(abContainerName);
2581     result = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, abContainerName, &dwBufferLen, CRYPT_FIRST);
2582     ok (result && dwBufferLen == (DWORD)sizeof(abContainerName), "%08x\n", GetLastError());
2583     
2584     /* We only check, if the currently open 'winetest' container is among the enumerated. */
2585     do {
2586         if (!strcmp((const char*)abContainerName, "winetest")) fFound = TRUE;
2587         dwBufferLen = (DWORD)sizeof(abContainerName);
2588     } while (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, abContainerName, &dwBufferLen, 0));
2589         
2590     ok (fFound && GetLastError() == ERROR_NO_MORE_ITEMS, "%d, %08x\n", fFound, GetLastError());
2591 }
2592
2593 static BYTE signBlob[] = {
2594 0x07,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x32,0x00,0x02,0x00,0x00,
2595 0x01,0x00,0x01,0x00,0xf1,0x82,0x9e,0x84,0xb5,0x79,0x9a,0xbe,0x4d,0x06,0x20,0x21,
2596 0xb1,0x89,0x0c,0xca,0xb0,0x35,0x72,0x18,0xc6,0x92,0xa8,0xe2,0xb1,0xe1,0xf6,0x56,
2597 0x53,0x99,0x47,0x10,0x6e,0x1c,0x81,0xaf,0xb8,0xf9,0x5f,0xfe,0x76,0x7f,0x2c,0x93,
2598 0xec,0x54,0x7e,0x5e,0xc2,0x25,0x3c,0x50,0x56,0x10,0x20,0x72,0x4a,0x93,0x03,0x12,
2599 0x29,0x98,0xcc,0xc9,0x47,0xbf,0xbf,0x93,0xcc,0xb0,0xe5,0x53,0x14,0xc8,0x7e,0x1f,
2600 0xa4,0x03,0x2d,0x8e,0x84,0x7a,0xd2,0xeb,0xf7,0x92,0x5e,0xa2,0xc7,0x6b,0x35,0x7d,
2601 0xcb,0x60,0xae,0xfb,0x07,0x78,0x11,0x73,0xb5,0x79,0xe5,0x7e,0x96,0xe3,0x50,0x95,
2602 0x80,0x0e,0x1c,0xf6,0x56,0xc6,0xe9,0x0a,0xaf,0x03,0xc6,0xdc,0x9a,0x81,0xcf,0x7a,
2603 0x63,0x16,0x43,0xcd,0xab,0x74,0xa1,0x7d,0xe7,0xe0,0x75,0x6d,0xbd,0x19,0xae,0x0b,
2604 0xa3,0x7f,0x6a,0x7b,0x05,0x4e,0xbc,0xec,0x18,0xfc,0x19,0xc2,0x00,0xf0,0x6a,0x2e,
2605 0xc4,0x31,0x73,0xba,0x07,0xcc,0x9d,0x57,0xeb,0xc7,0x7c,0x00,0x7d,0x5d,0x11,0x16,
2606 0x42,0x4b,0xe5,0x3a,0xf5,0xc7,0xf8,0xee,0xc3,0x2c,0x0d,0x86,0x03,0xe2,0xaf,0xb2,
2607 0xd2,0x91,0xdb,0x71,0xcd,0xdf,0x81,0x5f,0x06,0xfc,0x48,0x0d,0xb6,0x88,0x9f,0xc1,
2608 0x5e,0x24,0xa2,0x05,0x4f,0x30,0x2e,0x8f,0x8b,0x0d,0x76,0xa1,0x84,0xda,0x7b,0x44,
2609 0x70,0x85,0xf1,0x50,0xb1,0x21,0x3d,0xe2,0x57,0x3d,0xd0,0x01,0x93,0x49,0x8e,0xc5,
2610 0x0b,0x8b,0x0d,0x7b,0x08,0xe9,0x14,0xec,0x20,0x0d,0xea,0x02,0x00,0x63,0xe8,0x0a,
2611 0x52,0xe8,0xfb,0x21,0xbd,0x37,0xde,0x4c,0x4d,0xc2,0xf6,0xb9,0x0d,0x2a,0xc3,0xe2,
2612 0xc9,0xdf,0x48,0x3e,0x55,0x3d,0xe3,0xc0,0x22,0x37,0xf9,0x52,0xc0,0xd7,0x61,0x22,
2613 0xb6,0x85,0x86,0x07 };
2614
2615 static void test_null_provider(void)
2616 {
2617     HCRYPTPROV prov;
2618     HCRYPTKEY key;
2619     BOOL result;
2620     DWORD keySpec, dataLen,dwParam;
2621     char szName[MAX_PATH];
2622
2623     result = CryptAcquireContext(NULL, szContainer, NULL, 0, 0);
2624     ok(!result && GetLastError() == NTE_BAD_PROV_TYPE,
2625      "Expected NTE_BAD_PROV_TYPE, got %08x\n", GetLastError());
2626     result = CryptAcquireContext(NULL, szContainer, NULL, PROV_RSA_FULL, 0);
2627     ok(!result && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_KEYSET),
2628      "Expected ERROR_INVALID_PARAMETER or NTE_BAD_KEYSET, got %08x\n", GetLastError());
2629     result = CryptAcquireContext(NULL, szContainer, NULL, PROV_RSA_FULL,
2630      CRYPT_DELETEKEYSET);
2631     ok(!result && ( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_KEYSET),
2632      "Expected ERROR_INVALID_PARAMETER or NTE_BAD_KEYSET, got %08x\n", GetLastError());
2633     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2634      CRYPT_DELETEKEYSET);
2635     ok(!result && GetLastError() == NTE_BAD_KEYSET,
2636      "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2637     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, 0);
2638     ok(!result && GetLastError() == NTE_BAD_KEYSET,
2639      "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2640
2641     /* Delete the default container. */
2642     CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
2643     /* Once you've deleted the default container you can't open it as if it
2644      * already exists.
2645      */
2646     result = CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0);
2647     ok(!result && GetLastError() == NTE_BAD_KEYSET,
2648      "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2649     /* But you can always open the default container for CRYPT_VERIFYCONTEXT. */
2650     result = CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL,
2651      CRYPT_VERIFYCONTEXT);
2652     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2653     if (!result) return;
2654     dataLen = sizeof(keySpec);
2655     result = CryptGetProvParam(prov, PP_KEYSPEC, (LPBYTE)&keySpec, &dataLen, 0);
2656     if (result)
2657         ok(keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
2658          "Expected AT_KEYEXCHANGE | AT_SIGNATURE, got %08x\n", keySpec);
2659     /* Even though PP_KEYSPEC says both AT_KEYEXCHANGE and AT_SIGNATURE are
2660      * supported, you can't get the keys from this container.
2661      */
2662     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2663     ok(!result && GetLastError() == NTE_NO_KEY,
2664      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2665     result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2666     ok(!result && GetLastError() == NTE_NO_KEY,
2667      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2668     result = CryptReleaseContext(prov, 0);
2669     ok(result, "CryptReleaseContext failed: %08x\n", GetLastError());
2670     /* You can create a new default container. */
2671     result = CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL,
2672      CRYPT_NEWKEYSET);
2673     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2674     /* But you still can't get the keys (until one's been generated.) */
2675     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2676     ok(!result && GetLastError() == NTE_NO_KEY,
2677      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2678     result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2679     ok(!result && GetLastError() == NTE_NO_KEY,
2680      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2681     CryptReleaseContext(prov, 0);
2682     CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
2683
2684     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2685      CRYPT_DELETEKEYSET);
2686     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, 0);
2687     ok(!result && GetLastError() == NTE_BAD_KEYSET,
2688      "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2689     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2690      CRYPT_VERIFYCONTEXT);
2691     ok(!result && GetLastError() == NTE_BAD_FLAGS,
2692      "Expected NTE_BAD_FLAGS, got %08x\n", GetLastError());
2693     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2694      CRYPT_NEWKEYSET);
2695     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2696     if (!result) return;
2697     /* Test provider parameters getter */
2698     dataLen = sizeof(dwParam);
2699     result = CryptGetProvParam(prov, PP_PROVTYPE, (LPBYTE)&dwParam, &dataLen, 0);
2700     ok(result && dataLen == sizeof(dwParam) && dwParam == PROV_RSA_FULL,
2701         "Expected PROV_RSA_FULL, got 0x%08X\n",dwParam);
2702     dataLen = sizeof(dwParam);
2703     result = CryptGetProvParam(prov, PP_KEYSET_TYPE, (LPBYTE)&dwParam, &dataLen, 0);
2704     ok(result && dataLen == sizeof(dwParam) && dwParam == 0,
2705         "Expected 0, got 0x%08X\n",dwParam);
2706     dataLen = sizeof(dwParam);
2707     result = CryptGetProvParam(prov, PP_KEYSTORAGE, (LPBYTE)&dwParam, &dataLen, 0);
2708     ok(result && dataLen == sizeof(dwParam) && (dwParam & CRYPT_SEC_DESCR),
2709         "Expected CRYPT_SEC_DESCR to be set, got 0x%08X\n",dwParam);
2710     dataLen = sizeof(keySpec);
2711     SetLastError(0xdeadbeef);
2712     result = CryptGetProvParam(prov, PP_KEYSPEC, (LPBYTE)&keySpec, &dataLen, 0);
2713     if (!result && GetLastError() == NTE_BAD_TYPE)
2714         skip("PP_KEYSPEC is not supported (win9x or NT)\n");
2715     else
2716         ok(result && keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
2717             "Expected AT_KEYEXCHANGE | AT_SIGNATURE, got %08x\n", keySpec);
2718     /* PP_CONTAINER parameter */
2719     dataLen = sizeof(szName);
2720     result = CryptGetProvParam(prov, PP_CONTAINER, (LPBYTE)szName, &dataLen, 0);
2721     ok(result && dataLen == strlen(szContainer)+1 && strcmp(szContainer,szName) == 0,
2722         "failed getting PP_CONTAINER. result = %s. Error 0x%08X. returned length = %d\n",
2723         (result)? "TRUE":"FALSE",GetLastError(),dataLen);
2724     /* PP_UNIQUE_CONTAINER parameter */
2725     dataLen = sizeof(szName);
2726     SetLastError(0xdeadbeef);
2727     result = CryptGetProvParam(prov, PP_UNIQUE_CONTAINER, (LPBYTE)szName, &dataLen, 0);
2728     if (!result && GetLastError() == NTE_BAD_TYPE)
2729     {
2730         skip("PP_UNIQUE_CONTAINER is not supported (win9x or NT)\n");
2731     }
2732     else
2733     {
2734         char container[MAX_PATH];
2735
2736         ok(result, "failed getting PP_UNIQUE_CONTAINER : 0x%08X\n", GetLastError());
2737         uniquecontainer(container);
2738         todo_wine
2739         {
2740             ok(dataLen == strlen(container)+1 ||
2741                broken(dataLen == strlen(szContainer)+1) /* WinME */,
2742                "Expected a param length of 70, got %d\n", dataLen);
2743             ok(!strcmp(container, szName) ||
2744                broken(!strcmp(szName, szContainer)) /* WinME */,
2745                "Wrong container name : %s\n", szName);
2746         }
2747     }
2748     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2749     ok(!result && GetLastError() == NTE_NO_KEY,
2750      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2751     result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2752     ok(!result && GetLastError() == NTE_NO_KEY,
2753      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2754
2755     /* Importing a key exchange blob.. */
2756     result = CryptImportKey(prov, abPlainPrivateKey, sizeof(abPlainPrivateKey),
2757      0, 0, &key);
2758     ok(result, "CryptImportKey failed: %08x\n", GetLastError());
2759     CryptDestroyKey(key);
2760     /* allows access to the key exchange key.. */
2761     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2762     ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
2763     CryptDestroyKey(key);
2764     /* but not to the private key. */
2765     result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2766     ok(!result && GetLastError() == NTE_NO_KEY,
2767      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2768     CryptReleaseContext(prov, 0);
2769     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2770      CRYPT_DELETEKEYSET);
2771
2772     /* Whereas importing a sign blob.. */
2773     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2774      CRYPT_NEWKEYSET);
2775     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2776     if (!result) return;
2777     result = CryptImportKey(prov, signBlob, sizeof(signBlob), 0, 0, &key);
2778     ok(result, "CryptImportKey failed: %08x\n", GetLastError());
2779     CryptDestroyKey(key);
2780     /* doesn't allow access to the key exchange key.. */
2781     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2782     ok(!result && GetLastError() == NTE_NO_KEY,
2783      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2784     /* but does to the private key. */
2785     result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2786     ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
2787     CryptDestroyKey(key);
2788     CryptReleaseContext(prov, 0);
2789
2790     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2791      CRYPT_DELETEKEYSET);
2792
2793     /* Test for being able to get a key generated with CALG_RSA_SIGN. */
2794     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2795      CRYPT_NEWKEYSET);
2796     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2797     result = CryptGenKey(prov, CALG_RSA_SIGN, 0, &key);
2798     ok(result, "CryptGenKey with CALG_RSA_SIGN failed with error %08x\n", GetLastError());
2799     CryptDestroyKey(key);
2800     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2801     ok(!result, "expected CryptGetUserKey to fail\n");
2802     result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2803     ok(result, "CryptGetUserKey with AT_SIGNATURE failed: %08x\n", GetLastError());
2804     CryptDestroyKey(key);
2805     CryptReleaseContext(prov, 0);
2806
2807     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2808      CRYPT_DELETEKEYSET);
2809
2810     /* Test for being able to get a key generated with CALG_RSA_KEYX. */
2811     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2812      CRYPT_NEWKEYSET);
2813     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2814     result = CryptGenKey(prov, CALG_RSA_KEYX, 0, &key);
2815     ok(result, "CryptGenKey with CALG_RSA_KEYX failed with error %08x\n", GetLastError());
2816     CryptDestroyKey(key);
2817     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2818     ok(result, "CryptGetUserKey with AT_KEYEXCHANGE failed: %08x\n", GetLastError());
2819     CryptDestroyKey(key);
2820     result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2821     ok(!result, "expected CryptGetUserKey to fail\n");
2822     CryptReleaseContext(prov, 0);
2823
2824     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2825      CRYPT_DELETEKEYSET);
2826
2827     /* test for the bug in accessing the user key in a container
2828      */
2829     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2830      CRYPT_NEWKEYSET);
2831     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2832     result = CryptGenKey(prov, AT_KEYEXCHANGE, 0, &key);
2833     ok(result, "CryptGenKey with AT_KEYEXCHANGE failed with error %08x\n", GetLastError());
2834     CryptDestroyKey(key);
2835     CryptReleaseContext(prov,0);
2836     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,0);
2837     ok(result, "CryptAcquireContext failed: 0x%08x\n", GetLastError());
2838     result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2839     ok (result, "CryptGetUserKey failed with error %08x\n", GetLastError());
2840     CryptDestroyKey(key);
2841     CryptReleaseContext(prov, 0);
2842
2843     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2844      CRYPT_DELETEKEYSET);
2845
2846     /* test the machine key set */
2847     CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2848      CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET);
2849     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2850      CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET);
2851     ok(result, "CryptAcquireContext with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError());
2852     CryptReleaseContext(prov, 0);
2853     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2854      CRYPT_MACHINE_KEYSET);
2855     ok(result, "CryptAcquireContext with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError());
2856     CryptReleaseContext(prov,0);
2857     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2858        CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET);
2859     ok(result, "CryptAcquireContext with CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET failed: %08x\n",
2860                 GetLastError());
2861     result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2862      CRYPT_MACHINE_KEYSET);
2863     ok(!result && GetLastError() == NTE_BAD_KEYSET ,
2864         "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2865
2866 }
2867
2868 static void test_key_permissions(void)
2869 {
2870     HCRYPTKEY hKey1, hKey2;
2871     DWORD dwVal, dwLen;
2872     BOOL result;
2873
2874     /* Create keys that are exportable */
2875     if (!init_base_environment(CRYPT_EXPORTABLE))
2876         return;
2877
2878     result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey1);
2879     ok (result, "%08x\n", GetLastError());
2880     if (!result) return;
2881
2882     dwVal = 0xdeadbeef;
2883     dwLen = sizeof(DWORD);
2884     result = CryptGetKeyParam(hKey1, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
2885     ok(result, "%08x\n", GetLastError());
2886     ok(dwVal ==
2887         (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
2888         broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2889         "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
2890         " got %08x\n", dwVal);
2891
2892     /* The key exchange key's public key may be exported.. */
2893     result = CryptExportKey(hKey1, 0, PUBLICKEYBLOB, 0, NULL, &dwLen);
2894     ok(result, "%08x\n", GetLastError());
2895     /* and its private key may be too. */
2896     result = CryptExportKey(hKey1, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
2897     ok(result, "%08x\n", GetLastError());
2898     /* Turning off the key's export permissions is "allowed".. */
2899     dwVal &= ~CRYPT_EXPORT;
2900     result = CryptSetKeyParam(hKey1, KP_PERMISSIONS, (BYTE *)&dwVal, 0);
2901     ok(result ||
2902         broken(!result && GetLastError() == NTE_BAD_DATA) || /* W2K */
2903         broken(!result && GetLastError() == NTE_BAD_FLAGS), /* Win9x/WinME/NT4 */
2904         "%08x\n", GetLastError());
2905     /* but it has no effect. */
2906     dwVal = 0xdeadbeef;
2907     dwLen = sizeof(DWORD);
2908     result = CryptGetKeyParam(hKey1, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
2909     ok(result, "%08x\n", GetLastError());
2910     ok(dwVal ==
2911         (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
2912         broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2913         "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
2914         " got %08x\n", dwVal);
2915     /* Thus, changing the export flag of the key doesn't affect whether the key
2916      * may be exported.
2917      */
2918     result = CryptExportKey(hKey1, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
2919     ok(result, "%08x\n", GetLastError());
2920
2921     result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey2);
2922     ok (result, "%08x\n", GetLastError());
2923
2924     /* A subsequent get of the same key, into a different handle, also doesn't
2925      * show that the permissions have been changed.
2926      */
2927     dwVal = 0xdeadbeef;
2928     dwLen = sizeof(DWORD);
2929     result = CryptGetKeyParam(hKey2, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
2930     ok(result, "%08x\n", GetLastError());
2931     ok(dwVal ==
2932         (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
2933         broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2934         "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
2935         " got %08x\n", dwVal);
2936
2937     CryptDestroyKey(hKey2);
2938     CryptDestroyKey(hKey1);
2939
2940     clean_up_base_environment();
2941 }
2942
2943 static void test_key_initialization(void)
2944 {
2945     DWORD dwLen;
2946     HCRYPTPROV prov1, prov2;
2947     HCRYPTKEY hKeyExchangeKey, hSessionKey, hKey;
2948     BOOL result;
2949     static BYTE abSessionKey[148] = {
2950         0x01, 0x02, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00,
2951         0x00, 0xa4, 0x00, 0x00, 0xb8, 0xa4, 0xdf, 0x5e,
2952         0x9e, 0xb1, 0xbf, 0x85, 0x3d, 0x24, 0x2d, 0x1e,
2953         0x69, 0xb7, 0x67, 0x13, 0x8e, 0x78, 0xf2, 0xdf,
2954         0xc6, 0x69, 0xce, 0x46, 0x7e, 0xf2, 0xf2, 0x33,
2955         0x20, 0x6f, 0xa1, 0xa5, 0x59, 0x83, 0x25, 0xcb,
2956         0x3a, 0xb1, 0x8a, 0x12, 0x63, 0x02, 0x3c, 0xfb,
2957         0x4a, 0xfa, 0xef, 0x8e, 0xf7, 0x29, 0x57, 0xb1,
2958         0x9e, 0xa7, 0xf3, 0x02, 0xfd, 0xca, 0xdf, 0x5a,
2959         0x1f, 0x71, 0xb6, 0x26, 0x09, 0x24, 0x39, 0xda,
2960         0xc0, 0xde, 0x2a, 0x0e, 0xcd, 0x1f, 0xe5, 0xb6,
2961         0x4f, 0x82, 0xa0, 0xa9, 0x90, 0xd3, 0xd9, 0x6a,
2962         0x43, 0x14, 0x2a, 0xf7, 0xac, 0xd5, 0xa0, 0x54,
2963         0x93, 0xc4, 0xb9, 0xe7, 0x24, 0x84, 0x4d, 0x69,
2964         0x5e, 0xcc, 0x2a, 0x32, 0xb5, 0xfb, 0xe4, 0xb4,
2965         0x08, 0xd5, 0x36, 0x58, 0x59, 0x40, 0xfb, 0x29,
2966         0x7f, 0xa7, 0x17, 0x25, 0xc4, 0x0d, 0x78, 0x37,
2967         0x04, 0x8c, 0x49, 0x92
2968     };
2969
2970     /* Like init_base_environment, but doesn't generate new keys, as they'll
2971      * be imported instead.
2972      */
2973     if (!CryptAcquireContext(&prov1, szContainer, szProvider, PROV_RSA_FULL, 0))
2974     {
2975         result = CryptAcquireContext(&prov1, szContainer, szProvider, PROV_RSA_FULL,
2976                                      CRYPT_NEWKEYSET);
2977         ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2978     }
2979     dwLen = (DWORD)sizeof(abPlainPrivateKey);
2980     result = CryptImportKey(prov1, abPlainPrivateKey, dwLen, 0, 0, &hKeyExchangeKey);
2981     ok(result, "CryptImportKey failed: %08x\n", GetLastError());
2982
2983     dwLen = (DWORD)sizeof(abSessionKey);
2984     result = CryptImportKey(prov1, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
2985     ok(result, "CryptImportKey failed: %08x\n", GetLastError());
2986
2987     /* Once the key has been imported, subsequently acquiring a context with
2988      * the same name will allow retrieving the key.
2989      */
2990     result = CryptAcquireContext(&prov2, szContainer, szProvider, PROV_RSA_FULL, 0);
2991     ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2992     result = CryptGetUserKey(prov2, AT_KEYEXCHANGE, &hKey);
2993     ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
2994     if (result) CryptDestroyKey(hKey);
2995     CryptReleaseContext(prov2, 0);
2996
2997     CryptDestroyKey(hSessionKey);
2998     CryptDestroyKey(hKeyExchangeKey);
2999     CryptReleaseContext(prov1, 0);
3000     CryptAcquireContext(&prov1, szContainer, NULL, PROV_RSA_FULL,
3001      CRYPT_DELETEKEYSET);
3002 }
3003
3004 START_TEST(rsaenh)
3005 {
3006     if (!init_base_environment(0))
3007         return;
3008     test_prov();
3009     test_gen_random();
3010     test_hashes();
3011     test_rc4();
3012     test_rc2();
3013     test_des();
3014     test_3des112();
3015     test_3des();
3016     test_hmac();
3017     test_mac();
3018     test_block_cipher_modes();
3019     test_import_private();
3020     test_verify_signature();
3021     test_rsa_encrypt();
3022     test_import_export();
3023     test_import_hmac();
3024     test_enum_container();
3025     clean_up_base_environment();
3026     test_key_permissions();
3027     test_key_initialization();
3028     test_schannel_provider();
3029     test_null_provider();
3030     test_rsa_round_trip();
3031     if (!init_aes_environment())
3032         return;
3033     test_aes(128);
3034     test_aes(192);
3035     test_aes(256);
3036     test_sha2();
3037     clean_up_aes_environment();
3038 }