1 /*
2  * Miscellaneous crypt32 tests
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "precomp.h"
22 
23 static HMODULE hCrypt;
24 
25 static void test_findAttribute(void)
26 {
27     PCRYPT_ATTRIBUTE ret;
28     BYTE blobbin[] = {0x02,0x01,0x01};
29     static CHAR oid[] = "1.2.3";
30     CRYPT_ATTR_BLOB blobs[] = { { sizeof blobbin, blobbin }, };
31     CRYPT_ATTRIBUTE attr = { oid, sizeof(blobs) / sizeof(blobs[0]), blobs };
32 
33     /* returns NULL, last error not set */
34     SetLastError(0xdeadbeef);
35     ret = CertFindAttribute(NULL, 0, NULL);
36     ok(ret == NULL, "Expected failure\n");
37     ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
38      GetLastError());
39     if (0)
40     {
41         /* crashes */
42         CertFindAttribute(NULL, 1, NULL);
43         /* returns NULL, last error is ERROR_INVALID_PARAMETER
44          * crashes on Vista
45          */
46         SetLastError(0xdeadbeef);
47         ret = CertFindAttribute(NULL, 1, &attr);
48         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
49          "Expected ERROR_INVALID_PARAMETER, got %d (%08x)\n", GetLastError(),
50          GetLastError());
51     }
52     /* returns NULL, last error not set */
53     SetLastError(0xdeadbeef);
54     ret = CertFindAttribute("bogus", 1, &attr);
55     ok(ret == NULL, "Expected failure\n");
56     ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
57      GetLastError());
58     /* returns NULL, last error not set */
59     SetLastError(0xdeadbeef);
60     ret = CertFindAttribute("1.2.4", 1, &attr);
61     ok(ret == NULL, "Expected failure\n");
62     ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
63      GetLastError());
64     /* succeeds, last error not set */
65     SetLastError(0xdeadbeef);
66     ret = CertFindAttribute("1.2.3", 1, &attr);
67     ok(ret != NULL, "CertFindAttribute failed: %08x\n", GetLastError());
68 }
69 
70 static void test_findExtension(void)
71 {
72     PCERT_EXTENSION ret;
73     static CHAR oid[] = "1.2.3";
74     BYTE blobbin[] = {0x02,0x01,0x01};
75     CERT_EXTENSION ext = { oid, TRUE, { sizeof blobbin, blobbin } };
76 
77     /* returns NULL, last error not set */
78     SetLastError(0xdeadbeef);
79     ret = CertFindExtension(NULL, 0, NULL);
80     ok(ret == NULL, "Expected failure\n");
81     ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
82      GetLastError());
83     if (0)
84     {
85         /* crashes */
86         SetLastError(0xdeadbeef);
87         CertFindExtension(NULL, 1, NULL);
88         /* returns NULL, last error is ERROR_INVALID_PARAMETER
89          * crashes on Vista
90          */
91         SetLastError(0xdeadbeef);
92         ret = CertFindExtension(NULL, 1, &ext);
93         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
94          "Expected ERROR_INVALID_PARAMETER, got %d (%08x)\n", GetLastError(),
95          GetLastError());
96     }
97     /* returns NULL, last error not set */
98     SetLastError(0xdeadbeef);
99     ret = CertFindExtension("bogus", 1, &ext);
100     ok(ret == NULL, "Expected failure\n");
101     ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
102      GetLastError());
103     /* returns NULL, last error not set */
104     SetLastError(0xdeadbeef);
105     ret = CertFindExtension("1.2.4", 1, &ext);
106     ok(ret == NULL, "Expected failure\n");
107     ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
108      GetLastError());
109     /* succeeds, last error not set */
110     SetLastError(0xdeadbeef);
111     ret = CertFindExtension("1.2.3", 1, &ext);
112     ok(ret != NULL, "CertFindExtension failed: %08x\n", GetLastError());
113 }
114 
115 static void test_findRDNAttr(void)
116 {
117     PCERT_RDN_ATTR ret;
118     static CHAR oid[] = "1.2.3";
119     BYTE bin[] = { 0x16,0x09,'J','u','a','n',' ','L','a','n','g' };
120     CERT_RDN_ATTR attrs[] = {
121      { oid, CERT_RDN_IA5_STRING, { sizeof bin, bin } },
122     };
123     CERT_RDN rdns[] = {
124      { sizeof(attrs) / sizeof(attrs[0]), attrs },
125     };
126     CERT_NAME_INFO nameInfo = { sizeof(rdns) / sizeof(rdns[0]), rdns };
127 
128     if (0)
129     {
130         /* crashes */
131         SetLastError(0xdeadbeef);
132         CertFindRDNAttr(NULL, NULL);
133         /* returns NULL, last error is ERROR_INVALID_PARAMETER
134          * crashes on Vista
135          */
136         SetLastError(0xdeadbeef);
137         ret = CertFindRDNAttr(NULL, &nameInfo);
138         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
139          "Expected ERROR_INVALID_PARAMETER, got %d (%08x)\n", GetLastError(),
140          GetLastError());
141     }
142     /* returns NULL, last error not set */
143     SetLastError(0xdeadbeef);
144     ret = CertFindRDNAttr("bogus", &nameInfo);
145     ok(ret == NULL, "Expected failure\n");
146     ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
147      GetLastError());
148     /* returns NULL, last error not set */
149     SetLastError(0xdeadbeef);
150     ret = CertFindRDNAttr("1.2.4", &nameInfo);
151     ok(ret == NULL, "Expected failure\n");
152     ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
153      GetLastError());
154     /* succeeds, last error not set */
155     SetLastError(0xdeadbeef);
156     ret = CertFindRDNAttr("1.2.3", &nameInfo);
157     ok(ret != NULL, "CertFindRDNAttr failed: %08x\n", GetLastError());
158 }
159 
160 static void test_verifyTimeValidity(void)
161 {
162     SYSTEMTIME sysTime;
163     FILETIME fileTime;
164     CERT_INFO info = { 0 };
165     LONG ret;
166 
167     GetSystemTime(&sysTime);
168     SystemTimeToFileTime(&sysTime, &fileTime);
169     /* crashes
170     ret = CertVerifyTimeValidity(NULL, NULL);
171     ret = CertVerifyTimeValidity(&fileTime, NULL);
172      */
173     /* Check with 0 NotBefore and NotAfter */
174     ret = CertVerifyTimeValidity(&fileTime, &info);
175     ok(ret == 1, "Expected 1, got %d\n", ret);
176     info.NotAfter = fileTime;
177     /* Check with NotAfter equal to comparison time */
178     ret = CertVerifyTimeValidity(&fileTime, &info);
179     ok(ret == 0, "Expected 0, got %d\n", ret);
180     /* Check with NotBefore after comparison time */
181     info.NotBefore = fileTime;
182     info.NotBefore.dwLowDateTime += 5000;
183     ret = CertVerifyTimeValidity(&fileTime, &info);
184     ok(ret == -1, "Expected -1, got %d\n", ret);
185 }
186 
187 static void test_cryptAllocate(void)
188 {
189     LPVOID buf;
190 
191     buf = CryptMemAlloc(0);
192     ok(buf != NULL, "CryptMemAlloc failed: %08x\n", GetLastError());
193     CryptMemFree(buf);
194     /* CryptMemRealloc(NULL, 0) fails pre-Vista */
195     buf = CryptMemAlloc(0);
196     buf = CryptMemRealloc(buf, 1);
197     ok(buf != NULL, "CryptMemRealloc failed: %08x\n", GetLastError());
198     CryptMemFree(buf);
199 }
200 
201 
202 static void test_cryptTls(void)
203 {
204     DWORD  (WINAPI *pI_CryptAllocTls)(void);
205     LPVOID (WINAPI *pI_CryptDetachTls)(DWORD dwTlsIndex);
206     LPVOID (WINAPI *pI_CryptGetTls)(DWORD dwTlsIndex);
207     BOOL   (WINAPI *pI_CryptSetTls)(DWORD dwTlsIndex, LPVOID lpTlsValue);
208     BOOL   (WINAPI *pI_CryptFreeTls)(DWORD dwTlsIndex, DWORD unknown);
209     DWORD index;
210     BOOL ret;
211 
212     pI_CryptAllocTls = (void *)GetProcAddress(hCrypt, "I_CryptAllocTls");
213     pI_CryptDetachTls = (void *)GetProcAddress(hCrypt, "I_CryptDetachTls");
214     pI_CryptGetTls = (void *)GetProcAddress(hCrypt, "I_CryptGetTls");
215     pI_CryptSetTls = (void *)GetProcAddress(hCrypt, "I_CryptSetTls");
216     pI_CryptFreeTls = (void *)GetProcAddress(hCrypt, "I_CryptFreeTls");
217 
218     /* One normal pass */
219     index = pI_CryptAllocTls();
220     ok(index, "I_CryptAllocTls failed: %08x\n", GetLastError());
221     if (index)
222     {
223         LPVOID ptr;
224 
225         ptr = pI_CryptGetTls(index);
226         ok(!ptr, "Expected NULL\n");
227         ret = pI_CryptSetTls(index, (LPVOID)0xdeadbeef);
228         ok(ret, "I_CryptSetTls failed: %08x\n", GetLastError());
229         ptr = pI_CryptGetTls(index);
230         ok(ptr == (LPVOID)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", ptr);
231         /* This crashes
232         ret = pI_CryptFreeTls(index, 1);
233          */
234         ret = pI_CryptFreeTls(index, 0);
235         ok(ret, "I_CryptFreeTls failed: %08x\n", GetLastError());
236         ret = pI_CryptFreeTls(index, 0);
237         ok(!ret, "I_CryptFreeTls succeeded\n");
238         ok(GetLastError() == E_INVALIDARG,
239          "Expected E_INVALIDARG, got %08x\n", GetLastError());
240     }
241     /* Similar pass, check I_CryptDetachTls */
242     index = pI_CryptAllocTls();
243     ok(index, "I_CryptAllocTls failed: %08x\n", GetLastError());
244     if (index)
245     {
246         LPVOID ptr;
247 
248         ptr = pI_CryptGetTls(index);
249         ok(!ptr, "Expected NULL\n");
250         ret = pI_CryptSetTls(index, (LPVOID)0xdeadbeef);
251         ok(ret, "I_CryptSetTls failed: %08x\n", GetLastError());
252         ptr = pI_CryptGetTls(index);
253         ok(ptr == (LPVOID)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", ptr);
254         ptr = pI_CryptDetachTls(index);
255         ok(ptr == (LPVOID)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", ptr);
256         ptr = pI_CryptGetTls(index);
257         ok(!ptr, "Expected NULL\n");
258     }
259 }
260 
261 static void test_readTrustedPublisherDWORD(void)
262 {
263 
264     BOOL (WINAPI *pReadDWORD)(LPCWSTR, DWORD *);
265 
266     pReadDWORD = (void *)GetProcAddress(hCrypt, "I_CryptReadTrustedPublisherDWORDValueFromRegistry");
267     if (pReadDWORD)
268     {
269         static const WCHAR safer[] = {
270          'S','o','f','t','w','a','r','e','\\',
271          'P','o','l','i','c','i','e','s','\\',
272          'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m',
273          'C','e','r','t','i','f','i','c','a','t','e','s','\\',
274          'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',
275          '\\','S','a','f','e','r',0 };
276         static const WCHAR authenticodeFlags[] = { 'A','u','t','h','e','n',
277          't','i','c','o','d','e','F','l','a','g','s',0 };
278         BOOL ret, exists = FALSE;
279         DWORD size, readFlags = 0, returnedFlags;
280         HKEY key;
281         LONG rc;
282 
283         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, safer, &key);
284         if (rc == ERROR_SUCCESS)
285         {
286             size = sizeof(readFlags);
287             rc = RegQueryValueExW(key, authenticodeFlags, NULL, NULL,
288              (LPBYTE)&readFlags, &size);
289             if (rc == ERROR_SUCCESS)
290                 exists = TRUE;
291         }
292         returnedFlags = 0xdeadbeef;
293         ret = pReadDWORD(authenticodeFlags, &returnedFlags);
294         ok(ret == exists, "Unexpected return value\n");
295         ok(readFlags == returnedFlags,
296          "Expected flags %08x, got %08x\n", readFlags, returnedFlags);
297     }
298 }
299 
300 static void test_getDefaultCryptProv(void)
301 {
302     HCRYPTPROV (WINAPI *pI_CryptGetDefaultCryptProv)(DWORD w);
303     HCRYPTPROV prov;
304 
305     pI_CryptGetDefaultCryptProv = (void *)GetProcAddress(hCrypt, "I_CryptGetDefaultCryptProv");
306     if (!pI_CryptGetDefaultCryptProv) return;
307 
308     prov = pI_CryptGetDefaultCryptProv(0xdeadbeef);
309     ok(prov == 0 && GetLastError() == E_INVALIDARG,
310      "Expected E_INVALIDARG, got %08x\n", GetLastError());
311     prov = pI_CryptGetDefaultCryptProv(PROV_RSA_FULL);
312     ok(prov == 0 && GetLastError() == E_INVALIDARG,
313      "Expected E_INVALIDARG, got %08x\n", GetLastError());
314     prov = pI_CryptGetDefaultCryptProv(1);
315     ok(prov == 0 && GetLastError() == E_INVALIDARG,
316      "Expected E_INVALIDARG, got %08x\n", GetLastError());
317     prov = pI_CryptGetDefaultCryptProv(0);
318     ok(prov != 0, "I_CryptGetDefaultCryptProv failed: %08x\n", GetLastError());
319     CryptReleaseContext(prov, 0);
320 }
321 
322 static void test_CryptInstallOssGlobal(void)
323 {
324     int (WINAPI *pI_CryptInstallOssGlobal)(DWORD,DWORD,DWORD);
325     int ret,i;
326 
327     pI_CryptInstallOssGlobal = (void *)GetProcAddress(hCrypt,"I_CryptInstallOssGlobal");
328     /* passing in some random values to I_CryptInstallOssGlobal, it always returns 9 the first time, then 10, 11 etc.*/
329     for(i=0;i<30;i++)
330     {
331       ret =  pI_CryptInstallOssGlobal(rand(),rand(),rand());
332       ok((9+i) == ret ||
333          ret == 0, /* Vista */
334          "Expected %d or 0, got %d\n",(9+i),ret);
335     }
336 }
337 
338 static const BYTE encodedInt[] = { 0x02,0x01,0x01 };
339 static const WCHAR encodedIntStr[] = { '0','2',' ','0','1',' ','0','1',0 };
340 static const BYTE encodedBigInt[] = { 0x02,0x1f,0x01,0x02,0x03,0x04,0x05,0x06,
341  0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,
342  0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f };
343 static const WCHAR encodedBigIntStr[] = { '0','2',' ','1','f',' ','0','1',' ',
344  '0','2',' ','0','3',' ','0','4',' ','0','5',' ','0','6',' ','0','7',' ','0',
345  '8',' ','0','9',' ','0','a',' ','0','b',' ','0','c',' ','0','d',' ','0','e',
346  ' ','0','f',' ','1','0',' ','1','1',' ','1','2',' ','1','3',' ','1','4',' ',
347  '1','5',' ','1','6',' ','1','7',' ','1','8',' ','1','9',' ','1','a',' ','1',
348  'b',' ','1','c',' ','1','d',' ','1','e',' ','1','f',0 };
349 
350 static void test_format_object(void)
351 {
352     BOOL (WINAPI *pCryptFormatObject)(DWORD dwEncoding, DWORD dwFormatType,
353         DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType,
354         const BYTE *pbEncoded, DWORD dwEncoded, void *pbFormat,
355         DWORD *pcbFormat);
356     BOOL ret;
357     DWORD size;
358     LPWSTR str;
359 
360     pCryptFormatObject = (void *)GetProcAddress(hCrypt, "CryptFormatObject");
361     if (!pCryptFormatObject)
362     {
363         skip("No CryptFormatObject\n");
364         return;
365     }
366     /* Crash */
367     if (0)
368     {
369         pCryptFormatObject(0, 0, 0, NULL, NULL, NULL, 0, NULL, NULL);
370     }
371     /* When called with any but the default encoding, it fails to find a
372      * formatting function.
373      */
374     SetLastError(0xdeadbeef);
375     ret = pCryptFormatObject(0, 0, 0, NULL, NULL, NULL, 0, NULL, &size);
376     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
377      "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
378     /* When called with the default encoding type for any undefined struct type
379      * (including none), it succeeds:  the default encoding is a hex string
380      * encoding.
381      */
382     SetLastError(0xdeadbeef);
383     ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL, 0,
384      NULL, &size);
385     ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
386     if (ret)
387     {
388         if (size == 0 && GetLastError() == ERROR_FILE_NOT_FOUND)
389         {
390             win_skip("CryptFormatObject has no default implementation\n");
391             return;
392         }
393         ok(size == sizeof(WCHAR), "unexpected size %d\n", size);
394         str = HeapAlloc(GetProcessHeap(), 0, size);
395         SetLastError(0xdeadbeef);
396         size = 0;
397         ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL, 0,
398          str, &size);
399         ok(!ret && GetLastError() == ERROR_MORE_DATA,
400          "expected ERROR_MORE_DATA, got %d\n", GetLastError());
401         size = sizeof(WCHAR);
402         ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL, 0,
403          str, &size);
404         ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
405         ok(!str[0], "expected empty string\n");
406         HeapFree(GetProcessHeap(), 0, str);
407     }
408     ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL, encodedInt,
409      sizeof(encodedInt), NULL, &size);
410     ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
411     if (ret)
412     {
413         str = HeapAlloc(GetProcessHeap(), 0, size);
414         ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL,
415          encodedInt, sizeof(encodedInt), str, &size);
416         ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
417         ok(!lstrcmpW(str, encodedIntStr), "unexpected format string\n");
418         HeapFree(GetProcessHeap(), 0, str);
419     }
420     ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL,
421      encodedBigInt, sizeof(encodedBigInt), NULL, &size);
422     ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
423     if (ret)
424     {
425         str = HeapAlloc(GetProcessHeap(), 0, size);
426         ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL,
427          encodedBigInt, sizeof(encodedBigInt), str, &size);
428         ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
429         ok(!lstrcmpiW(str, encodedBigIntStr), "unexpected format string\n");
430         HeapFree(GetProcessHeap(), 0, str);
431     }
432     /* When called with the default encoding type for any undefined struct
433      * type but CRYPT_FORMAT_STR_NO_HEX specified, it fails to find a
434      * formatting function.
435      */
436     SetLastError(0xdeadbeef);
437     ret = pCryptFormatObject(X509_ASN_ENCODING, 0, CRYPT_FORMAT_STR_NO_HEX,
438      NULL, NULL, NULL, 0, NULL, &size);
439     ok(!ret, "CryptFormatObject succeeded\n");
440     ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
441      GetLastError() == 0xdeadbeef, /* Vista, W2K8 */
442      "expected ERROR_FILE_NOT_FOUND or no change, got %d\n", GetLastError());
443     /* When called to format an AUTHORITY_KEY_ID2_INFO, it fails when no
444      * data are given.
445      */
446     SetLastError(0xdeadbeef);
447     ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL,
448      szOID_AUTHORITY_KEY_IDENTIFIER2, NULL, 0, NULL, &size);
449     ok(!ret && GetLastError() == E_INVALIDARG,
450      "expected E_INVALIDARG, got %d\n", GetLastError());
451 }
452 
453 START_TEST(main)
454 {
455     hCrypt = GetModuleHandleA("crypt32.dll");
456 
457     test_findAttribute();
458     test_findExtension();
459     test_findRDNAttr();
460     test_verifyTimeValidity();
461     test_cryptAllocate();
462     test_cryptTls();
463     test_readTrustedPublisherDWORD();
464     test_getDefaultCryptProv();
465     test_CryptInstallOssGlobal();
466     test_format_object();
467 }
468