strmbase: Implement BaseControlWindow.
[wine/multimedia.git] / dlls / wintrust / tests / softpub.c
blob0987f9c8e06525fdacfab52719d3d99548cbb2a2
1 /*
2 * wintrust softpub functions tests
4 * Copyright 2007,2010 Juan Lang
5 * Copyright 2010 Andrey Turkin
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdio.h>
23 #include <stdarg.h>
25 #include <windef.h>
26 #include <winbase.h>
27 #include <winerror.h>
28 #include <wintrust.h>
29 #include <softpub.h>
30 #include <mssip.h>
31 #include <winuser.h>
32 #include "winnls.h"
34 #include "wine/test.h"
36 /* Just in case we're being built with borked headers, redefine function
37 * pointers to have the correct calling convention.
39 typedef void *(WINAPI *SAFE_MEM_ALLOC)(DWORD);
40 typedef void (WINAPI *SAFE_MEM_FREE)(void *);
41 typedef BOOL (WINAPI *SAFE_ADD_STORE)(CRYPT_PROVIDER_DATA *,
42 HCERTSTORE);
43 typedef BOOL (WINAPI *SAFE_ADD_SGNR)(CRYPT_PROVIDER_DATA *,
44 BOOL, DWORD, struct _CRYPT_PROVIDER_SGNR *);
45 typedef BOOL (WINAPI *SAFE_ADD_CERT)(CRYPT_PROVIDER_DATA *,
46 DWORD, BOOL, DWORD, PCCERT_CONTEXT);
47 typedef BOOL (WINAPI *SAFE_ADD_PRIVDATA)(CRYPT_PROVIDER_DATA *,
48 CRYPT_PROVIDER_PRIVDATA *);
49 typedef HRESULT (WINAPI *SAFE_PROVIDER_INIT_CALL)(CRYPT_PROVIDER_DATA *);
50 typedef HRESULT (WINAPI *SAFE_PROVIDER_OBJTRUST_CALL)(CRYPT_PROVIDER_DATA *);
51 typedef HRESULT (WINAPI *SAFE_PROVIDER_SIGTRUST_CALL)(CRYPT_PROVIDER_DATA *);
52 typedef HRESULT (WINAPI *SAFE_PROVIDER_CERTTRUST_CALL)(CRYPT_PROVIDER_DATA *);
53 typedef HRESULT (WINAPI *SAFE_PROVIDER_FINALPOLICY_CALL)(CRYPT_PROVIDER_DATA *);
54 typedef HRESULT (WINAPI *SAFE_PROVIDER_TESTFINALPOLICY_CALL)(
55 CRYPT_PROVIDER_DATA *);
56 typedef HRESULT (WINAPI *SAFE_PROVIDER_CLEANUP_CALL)(CRYPT_PROVIDER_DATA *);
57 typedef BOOL (WINAPI *SAFE_PROVIDER_CERTCHKPOLICY_CALL)(
58 CRYPT_PROVIDER_DATA *, DWORD, BOOL, DWORD);
60 typedef struct _SAFE_PROVIDER_FUNCTIONS
62 DWORD cbStruct;
63 SAFE_MEM_ALLOC pfnAlloc;
64 SAFE_MEM_FREE pfnFree;
65 SAFE_ADD_STORE pfnAddStore2Chain;
66 SAFE_ADD_SGNR pfnAddSgnr2Chain;
67 SAFE_ADD_CERT pfnAddCert2Chain;
68 SAFE_ADD_PRIVDATA pfnAddPrivData2Chain;
69 SAFE_PROVIDER_INIT_CALL pfnInitialize;
70 SAFE_PROVIDER_OBJTRUST_CALL pfnObjectTrust;
71 SAFE_PROVIDER_SIGTRUST_CALL pfnSignatureTrust;
72 SAFE_PROVIDER_CERTTRUST_CALL pfnCertificateTrust;
73 SAFE_PROVIDER_FINALPOLICY_CALL pfnFinalPolicy;
74 SAFE_PROVIDER_CERTCHKPOLICY_CALL pfnCertCheckPolicy;
75 SAFE_PROVIDER_TESTFINALPOLICY_CALL pfnTestFinalPolicy;
76 struct _CRYPT_PROVUI_FUNCS *psUIpfns;
77 SAFE_PROVIDER_CLEANUP_CALL pfnCleanupPolicy;
78 } SAFE_PROVIDER_FUNCTIONS;
80 static BOOL (WINAPI * pWTHelperGetKnownUsages)(DWORD action, PCCRYPT_OID_INFO **usages);
81 static BOOL (WINAPI * CryptSIPCreateIndirectData_p)(SIP_SUBJECTINFO *, DWORD *, SIP_INDIRECT_DATA *);
82 static VOID (WINAPI * CertFreeCertificateChain_p)(PCCERT_CHAIN_CONTEXT);
84 static void InitFunctionPtrs(void)
86 HMODULE hWintrust = GetModuleHandleA("wintrust.dll");
87 HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
89 #define WINTRUST_GET_PROC(func) \
90 p ## func = (void*)GetProcAddress(hWintrust, #func); \
91 if(!p ## func) { \
92 trace("GetProcAddress(%s) failed\n", #func); \
95 WINTRUST_GET_PROC(WTHelperGetKnownUsages)
97 #undef WINTRUST_GET_PROC
99 #define CRYPT32_GET_PROC(func) \
100 func ## _p = (void*)GetProcAddress(hCrypt32, #func); \
101 if(!func ## _p) { \
102 trace("GetProcAddress(%s) failed\n", #func); \
105 CRYPT32_GET_PROC(CryptSIPCreateIndirectData)
106 CRYPT32_GET_PROC(CertFreeCertificateChain)
108 #undef CRYPT32_GET_PROC
111 static const BYTE v1CertWithPubKey[] = {
112 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
113 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
114 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
115 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
116 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
117 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
118 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
119 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
120 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
121 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
122 0x01,0x01 };
124 static void test_utils(SAFE_PROVIDER_FUNCTIONS *funcs)
126 CRYPT_PROVIDER_DATA data = { 0 };
127 HCERTSTORE store;
128 CRYPT_PROVIDER_SGNR sgnr = { 0 };
129 BOOL ret;
131 /* Crash
132 ret = funcs->pfnAddStore2Chain(NULL, NULL);
133 ret = funcs->pfnAddStore2Chain(&data, NULL);
135 store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0,
136 CERT_STORE_CREATE_NEW_FLAG, NULL);
137 if (store)
139 ret = funcs->pfnAddStore2Chain(&data, store);
140 ok(ret, "pfnAddStore2Chain failed: %08x\n", GetLastError());
141 ok(data.chStores == 1, "Expected 1 store, got %d\n", data.chStores);
142 ok(data.pahStores != NULL, "Expected pahStores to be allocated\n");
143 if (data.pahStores)
145 ok(data.pahStores[0] == store, "Unexpected store\n");
146 CertCloseStore(data.pahStores[0], 0);
147 funcs->pfnFree(data.pahStores);
148 data.pahStores = NULL;
149 data.chStores = 0;
150 CertCloseStore(store, 0);
151 store = NULL;
154 else
155 skip("CertOpenStore failed: %08x\n", GetLastError());
157 /* Crash
158 ret = funcs->pfnAddSgnr2Chain(NULL, FALSE, 0, NULL);
159 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, NULL);
161 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
162 ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
163 ok(data.csSigners == 1, "Expected 1 signer, got %d\n", data.csSigners);
164 ok(data.pasSigners != NULL, "Expected pasSigners to be allocated\n");
165 if (data.pasSigners)
167 PCCERT_CONTEXT cert;
169 ok(!memcmp(&data.pasSigners[0], &sgnr, sizeof(sgnr)),
170 "Unexpected data in signer\n");
171 /* Adds into the location specified by the index */
172 sgnr.cbStruct = sizeof(CRYPT_PROVIDER_SGNR);
173 sgnr.sftVerifyAsOf.dwLowDateTime = 0xdeadbeef;
174 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 1, &sgnr);
175 ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
176 ok(data.csSigners == 2, "Expected 2 signers, got %d\n", data.csSigners);
177 ok(!memcmp(&data.pasSigners[1], &sgnr, sizeof(sgnr)),
178 "Unexpected data in signer\n");
179 /* This also adds, but the data aren't copied */
180 sgnr.cbStruct = sizeof(DWORD);
181 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
182 ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
183 ok(data.csSigners == 3, "Expected 3 signers, got %d\n", data.csSigners);
184 ok(data.pasSigners[0].cbStruct == 0, "Unexpected data size %d\n",
185 data.pasSigners[0].cbStruct);
186 ok(data.pasSigners[0].sftVerifyAsOf.dwLowDateTime == 0,
187 "Unexpected verify time %d\n",
188 data.pasSigners[0].sftVerifyAsOf.dwLowDateTime);
189 /* But too large a thing isn't added */
190 sgnr.cbStruct = sizeof(sgnr) + sizeof(DWORD);
191 SetLastError(0xdeadbeef);
192 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
193 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
194 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
196 /* Crash
197 ret = funcs->pfnAddCert2Chain(NULL, 0, FALSE, 0, NULL);
198 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, NULL);
200 cert = CertCreateCertificateContext(X509_ASN_ENCODING, v1CertWithPubKey,
201 sizeof(v1CertWithPubKey));
202 if (cert)
204 /* Notes on behavior that are hard to test:
205 * 1. If pasSigners is invalid, pfnAddCert2Chain crashes
206 * 2. An invalid signer index isn't checked.
208 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
209 ok(ret, "pfnAddCert2Chain failed: %08x\n", GetLastError());
210 ok(data.pasSigners[0].csCertChain == 1, "Expected 1 cert, got %d\n",
211 data.pasSigners[0].csCertChain);
212 ok(data.pasSigners[0].pasCertChain != NULL,
213 "Expected pasCertChain to be allocated\n");
214 if (data.pasSigners[0].pasCertChain)
216 ok(data.pasSigners[0].pasCertChain[0].pCert == cert,
217 "Unexpected cert\n");
218 CertFreeCertificateContext(
219 data.pasSigners[0].pasCertChain[0].pCert);
221 CertFreeCertificateContext(cert);
223 else
224 skip("CertCreateCertificateContext failed: %08x\n", GetLastError());
228 static void testInitialize(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
230 HRESULT ret;
231 CRYPT_PROVIDER_DATA data = { 0 };
232 WINTRUST_DATA wintrust_data = { 0 };
234 if (!funcs->pfnInitialize)
236 skip("missing pfnInitialize\n");
237 return;
240 /* Crashes
241 ret = funcs->pfnInitialize(NULL);
243 memset(&data, 0, sizeof(data));
244 ret = funcs->pfnInitialize(&data);
245 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
246 data.padwTrustStepErrors =
247 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
248 /* Without wintrust data set, crashes when padwTrustStepErrors is set */
249 data.pWintrustData = &wintrust_data;
250 if (data.padwTrustStepErrors)
252 /* Apparently, cdwTrustStepErrors does not need to be set. */
253 ret = funcs->pfnInitialize(&data);
254 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
255 data.cdwTrustStepErrors = 1;
256 ret = funcs->pfnInitialize(&data);
257 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
258 memset(data.padwTrustStepErrors, 0xba,
259 TRUSTERROR_MAX_STEPS * sizeof(DWORD));
260 ret = funcs->pfnInitialize(&data);
261 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
262 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] = 0;
263 ret = funcs->pfnInitialize(&data);
264 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
265 funcs->pfnFree(data.padwTrustStepErrors);
269 static void getNotepadPath(WCHAR *notepadPathW, DWORD size)
271 static const CHAR notepad[] = "\\notepad.exe";
272 CHAR notepadPath[MAX_PATH];
274 /* Workaround missing W-functions for win9x */
275 GetWindowsDirectoryA(notepadPath, MAX_PATH);
276 lstrcatA(notepadPath, notepad);
277 MultiByteToWideChar(0, 0, notepadPath, -1, notepadPathW, size);
280 /* Creates a test file and returns a handle to it. The file's path is returned
281 * in temp_file, which must be at least MAX_PATH characters in length.
283 static HANDLE create_temp_file(WCHAR *temp_file)
285 HANDLE file = INVALID_HANDLE_VALUE;
286 WCHAR temp_path[MAX_PATH];
288 if (GetTempPathW(sizeof(temp_path) / sizeof(temp_path[0]), temp_path))
290 static const WCHAR img[] = { 'i','m','g',0 };
292 if (GetTempFileNameW(temp_path, img, 0, temp_file))
293 file = CreateFileW(temp_file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
294 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
296 return file;
299 static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
301 HRESULT ret;
302 CRYPT_PROVIDER_DATA data = { 0 };
303 WINTRUST_DATA wintrust_data = { 0 };
304 WINTRUST_CERT_INFO certInfo = { sizeof(WINTRUST_CERT_INFO), 0 };
305 WINTRUST_FILE_INFO fileInfo = { sizeof(WINTRUST_FILE_INFO), 0 };
307 if (!funcs->pfnObjectTrust)
309 skip("missing pfnObjectTrust\n");
310 return;
313 /* Crashes
314 ret = funcs->pfnObjectTrust(NULL);
316 data.pWintrustData = &wintrust_data;
317 data.padwTrustStepErrors =
318 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
319 if (data.padwTrustStepErrors)
321 WCHAR pathW[MAX_PATH];
322 PROVDATA_SIP provDataSIP = { 0 };
323 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
324 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
325 static GUID bogusGuid = { 0xdeadbeef, 0xbaad, 0xf00d, { 0x00,0x00,0x00,
326 0x00,0x00,0x00,0x00,0x00 } };
328 ret = funcs->pfnObjectTrust(&data);
329 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
330 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
331 ERROR_INVALID_PARAMETER,
332 "Expected ERROR_INVALID_PARAMETER, got %08x\n",
333 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
334 U(wintrust_data).pCert = &certInfo;
335 wintrust_data.dwUnionChoice = WTD_CHOICE_CERT;
336 ret = funcs->pfnObjectTrust(&data);
337 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
338 certInfo.psCertContext = (PCERT_CONTEXT)CertCreateCertificateContext(
339 X509_ASN_ENCODING, v1CertWithPubKey, sizeof(v1CertWithPubKey));
340 ret = funcs->pfnObjectTrust(&data);
341 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
342 CertFreeCertificateContext(certInfo.psCertContext);
343 certInfo.psCertContext = NULL;
344 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
345 U(wintrust_data).pFile = NULL;
346 ret = funcs->pfnObjectTrust(&data);
347 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
348 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
349 ERROR_INVALID_PARAMETER,
350 "Expected ERROR_INVALID_PARAMETER, got %08x\n",
351 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
352 U(wintrust_data).pFile = &fileInfo;
353 /* Crashes
354 ret = funcs->pfnObjectTrust(&data);
356 /* Create and test with an empty file */
357 fileInfo.hFile = create_temp_file(pathW);
358 /* pfnObjectTrust now crashes unless both pPDSip and psPfns are set */
359 U(data).pPDSip = &provDataSIP;
360 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
361 ret = funcs->pfnObjectTrust(&data);
362 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
363 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
364 TRUST_E_SUBJECT_FORM_UNKNOWN,
365 "expected TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
366 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
367 CloseHandle(fileInfo.hFile);
368 fileInfo.hFile = NULL;
369 fileInfo.pcwszFilePath = pathW;
370 ret = funcs->pfnObjectTrust(&data);
371 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
372 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
373 TRUST_E_SUBJECT_FORM_UNKNOWN,
374 "expected TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
375 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
376 DeleteFileW(pathW);
377 /* Test again with a file we expect to exist, and to contain no
378 * signature.
380 getNotepadPath(pathW, MAX_PATH);
381 ret = funcs->pfnObjectTrust(&data);
382 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
383 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
384 TRUST_E_NOSIGNATURE ||
385 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
386 TRUST_E_SUBJECT_FORM_UNKNOWN,
387 "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
388 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
389 if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
390 TRUST_E_NOSIGNATURE)
392 ok(!memcmp(&provDataSIP.gSubject, &unknown, sizeof(unknown)),
393 "Unexpected subject GUID\n");
394 ok(provDataSIP.pSip != NULL, "Expected a SIP\n");
395 ok(provDataSIP.psSipSubjectInfo != NULL,
396 "Expected a subject info\n");
398 /* Specifying the GUID results in that GUID being the subject GUID */
399 fileInfo.pgKnownSubject = &bogusGuid;
400 ret = funcs->pfnObjectTrust(&data);
401 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
402 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
403 TRUST_E_NOSIGNATURE ||
404 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
405 TRUST_E_SUBJECT_FORM_UNKNOWN ||
406 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
407 TRUST_E_PROVIDER_UNKNOWN,
408 "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN or TRUST_E_PROVIDER_UNKNOWN, got %08x\n",
409 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
410 if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
411 TRUST_E_NOSIGNATURE)
413 ok(!memcmp(&provDataSIP.gSubject, &bogusGuid, sizeof(bogusGuid)),
414 "unexpected subject GUID\n");
416 /* Specifying a bogus GUID pointer crashes */
417 if (0)
419 fileInfo.pgKnownSubject = (GUID *)0xdeadbeef;
420 ret = funcs->pfnObjectTrust(&data);
421 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
423 funcs->pfnFree(data.padwTrustStepErrors);
427 static const BYTE selfSignedCert[] = {
428 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
429 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
430 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
431 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
432 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
433 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
434 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
435 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
436 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
437 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
438 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
439 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
440 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
441 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
442 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
443 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
444 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
445 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
446 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
447 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
448 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
449 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
450 0xa8, 0x76, 0x57, 0x92, 0x36 };
452 static void testCertTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
454 CRYPT_PROVIDER_DATA data = { 0 };
455 CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
456 HRESULT ret;
458 if (!CertFreeCertificateChain_p)
460 win_skip("CertFreeCertificateChain not found\n");
461 return;
464 data.padwTrustStepErrors =
465 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
466 if (!data.padwTrustStepErrors)
468 skip("pfnAlloc failed\n");
469 return;
471 ret = funcs->pfnCertificateTrust(&data);
472 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
473 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
474 TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
475 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
476 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
477 if (ret)
479 PCCERT_CONTEXT cert;
481 /* An empty signer "succeeds," even though there's no cert */
482 ret = funcs->pfnCertificateTrust(&data);
483 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
484 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
485 sizeof(selfSignedCert));
486 if (cert)
488 WINTRUST_DATA wintrust_data = { 0 };
490 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
491 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
493 /* If pWintrustData isn't set, crashes attempting to access
494 * pWintrustData->fdwRevocationChecks
496 data.pWintrustData = &wintrust_data;
497 /* If psPfns isn't set, crashes attempting to access
498 * psPfns->pfnCertCheckPolicy
500 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
501 ret = funcs->pfnCertificateTrust(&data);
502 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
503 ok(data.csSigners == 1, "Unexpected number of signers %d\n",
504 data.csSigners);
505 ok(data.pasSigners[0].pChainContext != NULL,
506 "Expected a certificate chain\n");
507 ok(data.pasSigners[0].csCertChain == 1,
508 "Unexpected number of chain elements %d\n",
509 data.pasSigners[0].csCertChain);
510 /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
511 * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
513 ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
514 "Didn't expect cert to be trusted\n");
515 ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
516 "Expected cert to be self-signed\n");
517 ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
518 (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
519 "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
520 data.pasSigners[0].pasCertChain[0].dwConfidence);
521 CertFreeCertificateContext(
522 data.pasSigners[0].pasCertChain[0].pCert);
523 CertFreeCertificateChain_p(data.pasSigners[0].pChainContext);
524 CertFreeCertificateContext(cert);
527 funcs->pfnFree(data.padwTrustStepErrors);
530 static void test_provider_funcs(void)
532 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
533 SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
534 BOOL ret;
536 ret = WintrustLoadFunctionPointers(&generic_verify_v2,
537 (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
538 if (!ret)
539 skip("WintrustLoadFunctionPointers failed\n");
540 else
542 test_utils(&funcs);
543 testInitialize(&funcs, &generic_verify_v2);
544 testObjTrust(&funcs, &generic_verify_v2);
545 testCertTrust(&funcs, &generic_verify_v2);
549 /* minimal PE file image */
550 #define VA_START 0x400000
551 #define FILE_PE_START 0x50
552 #define NUM_SECTIONS 3
553 #define FILE_TEXT 0x200
554 #define RVA_TEXT 0x1000
555 #define RVA_BSS 0x2000
556 #define FILE_IDATA 0x400
557 #define RVA_IDATA 0x3000
558 #define FILE_TOTAL 0x600
559 #define RVA_TOTAL 0x4000
560 #include <pshpack1.h>
561 struct Imports {
562 IMAGE_IMPORT_DESCRIPTOR descriptors[2];
563 IMAGE_THUNK_DATA32 original_thunks[2];
564 IMAGE_THUNK_DATA32 thunks[2];
565 struct __IMPORT_BY_NAME {
566 WORD hint;
567 char funcname[0x20];
568 } ibn;
569 char dllname[0x10];
571 #define EXIT_PROCESS (VA_START+RVA_IDATA+FIELD_OFFSET(struct Imports, thunks[0]))
573 static struct _PeImage {
574 IMAGE_DOS_HEADER dos_header;
575 char __alignment1[FILE_PE_START - sizeof(IMAGE_DOS_HEADER)];
576 IMAGE_NT_HEADERS32 nt_headers;
577 IMAGE_SECTION_HEADER sections[NUM_SECTIONS];
578 char __alignment2[FILE_TEXT - FILE_PE_START - sizeof(IMAGE_NT_HEADERS32) -
579 NUM_SECTIONS * sizeof(IMAGE_SECTION_HEADER)];
580 unsigned char text_section[FILE_IDATA-FILE_TEXT];
581 struct Imports idata_section;
582 char __alignment3[FILE_TOTAL-FILE_IDATA-sizeof(struct Imports)];
583 } bin = {
584 /* dos header */
585 {IMAGE_DOS_SIGNATURE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {}, 0, 0, {}, FILE_PE_START},
586 /* alignment before PE header */
588 /* nt headers */
589 {IMAGE_NT_SIGNATURE,
590 /* basic headers - 3 sections, no symbols, EXE file */
591 {IMAGE_FILE_MACHINE_I386, NUM_SECTIONS, 0, 0, 0, sizeof(IMAGE_OPTIONAL_HEADER32),
592 IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE},
593 /* optional header */
594 {IMAGE_NT_OPTIONAL_HDR32_MAGIC, 4, 0, FILE_IDATA-FILE_TEXT,
595 FILE_TOTAL-FILE_IDATA + FILE_IDATA-FILE_TEXT, 0x400,
596 RVA_TEXT, RVA_TEXT, RVA_BSS, VA_START, 0x1000, 0x200, 4, 0, 1, 0, 4, 0, 0,
597 RVA_TOTAL, FILE_TEXT, 0, IMAGE_SUBSYSTEM_WINDOWS_GUI, 0,
598 0x200000, 0x1000, 0x100000, 0x1000, 0, 0x10,
599 {{0, 0},
600 {RVA_IDATA, sizeof(struct Imports)}
604 /* sections */
606 {".text", {0x100}, RVA_TEXT, FILE_IDATA-FILE_TEXT, FILE_TEXT,
607 0, 0, 0, 0, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ},
608 {".bss", {0x400}, RVA_BSS, 0, 0, 0, 0, 0, 0,
609 IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE},
610 {".idata", {sizeof(struct Imports)}, RVA_IDATA, FILE_TOTAL-FILE_IDATA, FILE_IDATA, 0,
611 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}
613 /* alignment before first section */
615 /* .text section */
617 0x31, 0xC0, /* xor eax, eax */
618 0xFF, 0x25, EXIT_PROCESS&0xFF, (EXIT_PROCESS>>8)&0xFF, (EXIT_PROCESS>>16)&0xFF,
619 (EXIT_PROCESS>>24)&0xFF, /* jmp ExitProcess */
622 /* .idata section */
625 {{RVA_IDATA + FIELD_OFFSET(struct Imports, original_thunks)}, 0, 0,
626 RVA_IDATA + FIELD_OFFSET(struct Imports, dllname),
627 RVA_IDATA + FIELD_OFFSET(struct Imports, thunks)
629 {{0}, 0, 0, 0, 0}
631 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
632 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
633 {0,"ExitProcess"},
634 "KERNEL32.DLL"
636 /* final alignment */
639 #include <poppack.h>
641 static void test_sip_create_indirect_data(void)
643 static GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
644 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
645 static char oid_sha1[] = szOID_OIWSEC_sha1;
646 BOOL ret;
647 SIP_SUBJECTINFO subjinfo = { 0 };
648 WCHAR temp_file[MAX_PATH];
649 HANDLE file;
650 DWORD count;
652 if (!CryptSIPCreateIndirectData_p)
654 skip("Missing CryptSIPCreateIndirectData\n");
655 return;
657 SetLastError(0xdeadbeef);
658 ret = CryptSIPCreateIndirectData_p(NULL, NULL, NULL);
659 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
660 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
661 SetLastError(0xdeadbeef);
662 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
663 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
664 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
665 subjinfo.cbSize = sizeof(subjinfo);
666 SetLastError(0xdeadbeef);
667 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
668 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
669 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
670 file = create_temp_file(temp_file);
671 if (file == INVALID_HANDLE_VALUE)
673 skip("couldn't create temp file\n");
674 return;
676 WriteFile(file, &bin, sizeof(bin), &count, NULL);
677 FlushFileBuffers(file);
679 subjinfo.hFile = file;
680 SetLastError(0xdeadbeef);
681 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
682 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
683 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
684 subjinfo.pgSubjectType = &unknown;
685 SetLastError(0xdeadbeef);
686 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
687 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
688 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
689 count = 0xdeadbeef;
690 SetLastError(0xdeadbeef);
691 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
692 todo_wine
693 ok(!ret && (GetLastError() == NTE_BAD_ALGID ||
694 GetLastError() == ERROR_INVALID_PARAMETER /* Win7 */),
695 "expected NTE_BAD_ALGID or ERROR_INVALID_PARAMETER, got %08x\n",
696 GetLastError());
697 ok(count == 0xdeadbeef, "expected count to be unmodified, got %d\n", count);
698 subjinfo.DigestAlgorithm.pszObjId = oid_sha1;
699 count = 0xdeadbeef;
700 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
701 todo_wine
702 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
703 ok(count, "expected a positive count\n");
704 if (ret)
706 SIP_INDIRECT_DATA *indirect = HeapAlloc(GetProcessHeap(), 0, count);
708 count = 256;
709 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, indirect);
710 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
711 /* If the count is larger than needed, it's unmodified */
712 ok(count == 256, "unexpected count %d\n", count);
713 ok(!strcmp(indirect->Data.pszObjId, SPC_PE_IMAGE_DATA_OBJID),
714 "unexpected data oid %s\n",
715 indirect->Data.pszObjId);
716 ok(!strcmp(indirect->DigestAlgorithm.pszObjId, oid_sha1),
717 "unexpected digest algorithm oid %s\n",
718 indirect->DigestAlgorithm.pszObjId);
719 ok(indirect->Digest.cbData == 20, "unexpected hash size %d\n",
720 indirect->Digest.cbData);
721 if (indirect->Digest.cbData == 20)
723 const BYTE hash[20] = {
724 0x8a,0xd5,0x45,0x53,0x3d,0x67,0xdf,0x2f,0x78,0xe0,
725 0x55,0x0a,0xe0,0xd9,0x7a,0x28,0x3e,0xbf,0x45,0x2b };
727 ok(!memcmp(indirect->Digest.pbData, hash, 20),
728 "unexpected value\n");
731 HeapFree(GetProcessHeap(), 0, indirect);
733 CloseHandle(file);
734 DeleteFileW(temp_file);
737 static void test_wintrust(void)
739 static GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
740 WINTRUST_DATA wtd;
741 WINTRUST_FILE_INFO file;
742 LONG r;
743 HRESULT hr;
744 WCHAR pathW[MAX_PATH];
746 memset(&wtd, 0, sizeof(wtd));
747 wtd.cbStruct = sizeof(wtd);
748 wtd.dwUIChoice = WTD_UI_NONE;
749 wtd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
750 wtd.dwUnionChoice = WTD_CHOICE_FILE;
751 U(wtd).pFile = &file;
752 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
753 memset(&file, 0, sizeof(file));
754 file.cbStruct = sizeof(file);
755 file.pcwszFilePath = pathW;
756 /* Test with an empty file */
757 file.hFile = create_temp_file(pathW);
758 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
759 ok(r == TRUST_E_SUBJECT_FORM_UNKNOWN,
760 "expected TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n", r);
761 CloseHandle(file.hFile);
762 DeleteFileW(pathW);
763 file.hFile = NULL;
764 /* Test with a known file path, which we expect not have a signature */
765 getNotepadPath(pathW, MAX_PATH);
766 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
767 ok(r == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
768 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", r);
769 wtd.dwStateAction = WTD_STATEACTION_CLOSE;
770 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
771 ok(r == S_OK, "WinVerifyTrust failed: %08x\n", r);
772 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
773 hr = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
774 ok(hr == TRUST_E_NOSIGNATURE || hr == CRYPT_E_FILE_ERROR,
775 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", hr);
776 wtd.dwStateAction = WTD_STATEACTION_CLOSE;
777 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
778 ok(r == S_OK, "WinVerifyTrust failed: %08x\n", r);
781 static void test_get_known_usages(void)
783 BOOL ret;
784 PCCRYPT_OID_INFO *usages;
786 if (!pWTHelperGetKnownUsages)
788 skip("missing WTHelperGetKnownUsages\n");
789 return;
791 SetLastError(0xdeadbeef);
792 ret = pWTHelperGetKnownUsages(0, NULL);
793 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
794 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
795 SetLastError(0xdeadbeef);
796 ret = pWTHelperGetKnownUsages(1, NULL);
797 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
798 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
799 SetLastError(0xdeadbeef);
800 ret = pWTHelperGetKnownUsages(0, &usages);
801 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
802 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
803 /* A value of 1 for the first parameter seems to imply the value is
804 * allocated
806 SetLastError(0xdeadbeef);
807 usages = NULL;
808 ret = pWTHelperGetKnownUsages(1, &usages);
809 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
810 ok(usages != NULL, "expected a pointer\n");
811 if (ret && usages)
813 PCCRYPT_OID_INFO *ptr;
815 /* The returned usages are an array of PCCRYPT_OID_INFOs, terminated with a
816 * NULL pointer.
818 for (ptr = usages; *ptr; ptr++)
820 ok((*ptr)->cbSize == sizeof(CRYPT_OID_INFO) ||
821 (*ptr)->cbSize == (sizeof(CRYPT_OID_INFO) + 2 * sizeof(LPCWSTR)), /* Vista */
822 "unexpected size %d\n", (*ptr)->cbSize);
823 /* Each returned usage is in the CRYPT_ENHKEY_USAGE_OID_GROUP_ID group */
824 ok((*ptr)->dwGroupId == CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
825 "expected group CRYPT_ENHKEY_USAGE_OID_GROUP_ID, got %d\n",
826 (*ptr)->dwGroupId);
829 /* A value of 2 for the second parameter seems to imply the value is freed
831 SetLastError(0xdeadbeef);
832 ret = pWTHelperGetKnownUsages(2, &usages);
833 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
834 ok(usages == NULL, "expected pointer to be cleared\n");
835 SetLastError(0xdeadbeef);
836 usages = NULL;
837 ret = pWTHelperGetKnownUsages(2, &usages);
838 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
839 SetLastError(0xdeadbeef);
840 ret = pWTHelperGetKnownUsages(2, NULL);
841 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
842 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
845 START_TEST(softpub)
847 InitFunctionPtrs();
848 test_provider_funcs();
849 test_sip_create_indirect_data();
850 test_wintrust();
851 test_get_known_usages();