wintrust/tests: Replace the self-signed certificate with one that expires in ten...
[wine/wine-gecko.git] / dlls / wintrust / tests / softpub.c
blobf3429362dd07a7107d053b99a68904128a5121b5
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(CP_ACP, 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 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43,
429 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
430 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44, 0x70, 0x7a, 0x43, 0x43,
431 0x41, 0x6f, 0x2b, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4a,
432 0x41, 0x4c, 0x59, 0x51, 0x67, 0x65, 0x66, 0x7a, 0x51, 0x41, 0x61, 0x43,
433 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33,
434 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x4d, 0x47, 0x6f, 0x78,
435 0x43, 0x7a, 0x41, 0x4a, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, 0x41, 0x59,
436 0x54, 0x41, 0x6b, 0x46, 0x56, 0x4d, 0x52, 0x4d, 0x77, 0x45, 0x51, 0x59,
437 0x44, 0x56, 0x51, 0x51, 0x49, 0x44, 0x41, 0x70, 0x54, 0x62, 0x32, 0x31,
438 0x6c, 0x4c, 0x56, 0x4e, 0x30, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x53, 0x45,
439 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x42, 0x68,
440 0x4a, 0x62, 0x6e, 0x52, 0x6c, 0x63, 0x6d, 0x35, 0x6c, 0x64, 0x43, 0x42,
441 0x58, 0x0a, 0x61, 0x57, 0x52, 0x6e, 0x61, 0x58, 0x52, 0x7a, 0x49, 0x46,
442 0x42, 0x30, 0x65, 0x53, 0x42, 0x4d, 0x64, 0x47, 0x51, 0x78, 0x49, 0x7a,
443 0x41, 0x68, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x4d, 0x4d, 0x47, 0x6e,
444 0x4e, 0x6c, 0x62, 0x47, 0x5a, 0x7a, 0x61, 0x57, 0x64, 0x75, 0x5a, 0x57,
445 0x51, 0x75, 0x64, 0x47, 0x56, 0x7a, 0x64, 0x43, 0x35, 0x33, 0x61, 0x57,
446 0x35, 0x6c, 0x61, 0x48, 0x45, 0x75, 0x0a, 0x62, 0x33, 0x4a, 0x6e, 0x4d,
447 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x7a, 0x4d, 0x44, 0x59, 0x79, 0x4d,
448 0x54, 0x45, 0x78, 0x4d, 0x6a, 0x55, 0x78, 0x4d, 0x46, 0x6f, 0x58, 0x44,
449 0x54, 0x49, 0x7a, 0x4d, 0x44, 0x59, 0x78, 0x4f, 0x54, 0x45, 0x78, 0x4d,
450 0x6a, 0x55, 0x78, 0x4d, 0x46, 0x6f, 0x77, 0x61, 0x6a, 0x45, 0x4c, 0x4d,
451 0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, 0x43, 0x0a,
452 0x51, 0x56, 0x55, 0x78, 0x45, 0x7a, 0x41, 0x52, 0x42, 0x67, 0x4e, 0x56,
453 0x42, 0x41, 0x67, 0x4d, 0x43, 0x6c, 0x4e, 0x76, 0x62, 0x57, 0x55, 0x74,
454 0x55, 0x33, 0x52, 0x68, 0x64, 0x47, 0x55, 0x78, 0x49, 0x54, 0x41, 0x66,
455 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x47, 0x45, 0x6c, 0x75,
456 0x64, 0x47, 0x56, 0x79, 0x62, 0x6d, 0x56, 0x30, 0x49, 0x46, 0x64, 0x70,
457 0x5a, 0x47, 0x64, 0x70, 0x0a, 0x64, 0x48, 0x4d, 0x67, 0x55, 0x48, 0x52,
458 0x35, 0x49, 0x45, 0x78, 0x30, 0x5a, 0x44, 0x45, 0x6a, 0x4d, 0x43, 0x45,
459 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x61, 0x63, 0x32, 0x56,
460 0x73, 0x5a, 0x6e, 0x4e, 0x70, 0x5a, 0x32, 0x35, 0x6c, 0x5a, 0x43, 0x35,
461 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6e, 0x64, 0x70, 0x62, 0x6d, 0x56,
462 0x6f, 0x63, 0x53, 0x35, 0x76, 0x63, 0x6d, 0x63, 0x77, 0x0a, 0x67, 0x67,
463 0x45, 0x69, 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49,
464 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34,
465 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4b, 0x41, 0x6f,
466 0x49, 0x42, 0x41, 0x51, 0x44, 0x77, 0x4e, 0x6d, 0x2b, 0x46, 0x7a, 0x78,
467 0x6e, 0x6b, 0x48, 0x57, 0x2f, 0x4e, 0x70, 0x37, 0x59, 0x48, 0x34, 0x4d,
468 0x79, 0x45, 0x0a, 0x77, 0x4d, 0x6c, 0x49, 0x67, 0x71, 0x30, 0x66, 0x45,
469 0x77, 0x70, 0x47, 0x6f, 0x41, 0x75, 0x78, 0x44, 0x64, 0x61, 0x46, 0x55,
470 0x32, 0x6f, 0x70, 0x76, 0x41, 0x51, 0x56, 0x61, 0x2b, 0x41, 0x43, 0x46,
471 0x38, 0x63, 0x6f, 0x38, 0x4d, 0x4a, 0x6c, 0x33, 0x78, 0x77, 0x76, 0x46,
472 0x44, 0x2b, 0x67, 0x61, 0x46, 0x45, 0x7a, 0x59, 0x78, 0x53, 0x58, 0x30,
473 0x43, 0x47, 0x72, 0x4a, 0x45, 0x4c, 0x63, 0x0a, 0x74, 0x34, 0x4d, 0x69,
474 0x30, 0x68, 0x4b, 0x50, 0x76, 0x42, 0x70, 0x65, 0x73, 0x59, 0x6c, 0x46,
475 0x4d, 0x51, 0x65, 0x6b, 0x2b, 0x63, 0x70, 0x51, 0x50, 0x33, 0x4b, 0x35,
476 0x75, 0x36, 0x71, 0x58, 0x5a, 0x52, 0x49, 0x67, 0x48, 0x75, 0x59, 0x45,
477 0x4c, 0x2f, 0x73, 0x55, 0x6f, 0x39, 0x32, 0x70, 0x44, 0x30, 0x7a, 0x4a,
478 0x65, 0x4c, 0x47, 0x41, 0x31, 0x49, 0x30, 0x4b, 0x5a, 0x34, 0x73, 0x2f,
479 0x0a, 0x51, 0x7a, 0x77, 0x61, 0x4f, 0x38, 0x62, 0x62, 0x4b, 0x6d, 0x37,
480 0x42, 0x72, 0x6e, 0x56, 0x77, 0x30, 0x6e, 0x5a, 0x2f, 0x4b, 0x41, 0x5a,
481 0x6a, 0x75, 0x78, 0x75, 0x6f, 0x4e, 0x33, 0x52, 0x64, 0x72, 0x69, 0x30,
482 0x4a, 0x48, 0x77, 0x7a, 0x6a, 0x41, 0x55, 0x34, 0x2b, 0x71, 0x57, 0x65,
483 0x55, 0x63, 0x2f, 0x64, 0x33, 0x45, 0x70, 0x4f, 0x47, 0x78, 0x69, 0x42,
484 0x77, 0x5a, 0x4e, 0x61, 0x7a, 0x0a, 0x39, 0x6f, 0x4a, 0x41, 0x37, 0x54,
485 0x2f, 0x51, 0x6f, 0x62, 0x75, 0x61, 0x4e, 0x53, 0x6b, 0x65, 0x55, 0x48,
486 0x43, 0x61, 0x50, 0x53, 0x6a, 0x44, 0x37, 0x71, 0x7a, 0x6c, 0x43, 0x4f,
487 0x52, 0x48, 0x47, 0x68, 0x75, 0x31, 0x76, 0x79, 0x79, 0x35, 0x31, 0x45,
488 0x36, 0x79, 0x46, 0x43, 0x4e, 0x47, 0x66, 0x65, 0x7a, 0x71, 0x2f, 0x4d,
489 0x59, 0x34, 0x4e, 0x4b, 0x68, 0x77, 0x72, 0x61, 0x59, 0x64, 0x0a, 0x62,
490 0x79, 0x49, 0x2f, 0x6c, 0x42, 0x46, 0x62, 0x36, 0x35, 0x6b, 0x5a, 0x45,
491 0x66, 0x49, 0x4b, 0x4b, 0x54, 0x7a, 0x79, 0x36, 0x76, 0x30, 0x44, 0x65,
492 0x79, 0x50, 0x37, 0x52, 0x6b, 0x34, 0x75, 0x48, 0x44, 0x38, 0x77, 0x62,
493 0x49, 0x79, 0x50, 0x32, 0x47, 0x6c, 0x42, 0x30, 0x67, 0x37, 0x2f, 0x69,
494 0x79, 0x33, 0x4c, 0x61, 0x74, 0x49, 0x74, 0x49, 0x70, 0x2b, 0x49, 0x35,
495 0x53, 0x50, 0x56, 0x0a, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, 0x47, 0x6a,
496 0x55, 0x44, 0x42, 0x4f, 0x4d, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64,
497 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x36, 0x49, 0x4c, 0x5a, 0x2f,
498 0x71, 0x38, 0x66, 0x2f, 0x4b, 0x45, 0x68, 0x4b, 0x76, 0x68, 0x69, 0x2b,
499 0x73, 0x6b, 0x59, 0x45, 0x31, 0x79, 0x48, 0x71, 0x39, 0x7a, 0x41, 0x66,
500 0x42, 0x67, 0x4e, 0x56, 0x48, 0x53, 0x4d, 0x45, 0x0a, 0x47, 0x44, 0x41,
501 0x57, 0x67, 0x42, 0x53, 0x36, 0x49, 0x4c, 0x5a, 0x2f, 0x71, 0x38, 0x66,
502 0x2f, 0x4b, 0x45, 0x68, 0x4b, 0x76, 0x68, 0x69, 0x2b, 0x73, 0x6b, 0x59,
503 0x45, 0x31, 0x79, 0x48, 0x71, 0x39, 0x7a, 0x41, 0x4d, 0x42, 0x67, 0x4e,
504 0x56, 0x48, 0x52, 0x4d, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48,
505 0x2f, 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62,
506 0x33, 0x0a, 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x41, 0x34,
507 0x49, 0x42, 0x41, 0x51, 0x41, 0x79, 0x5a, 0x59, 0x77, 0x47, 0x4b, 0x46,
508 0x34, 0x34, 0x43, 0x68, 0x47, 0x51, 0x72, 0x6e, 0x74, 0x57, 0x6c, 0x38,
509 0x48, 0x53, 0x4a, 0x30, 0x63, 0x69, 0x55, 0x58, 0x4d, 0x44, 0x4b, 0x32,
510 0x46, 0x6c, 0x6f, 0x74, 0x47, 0x49, 0x6a, 0x30, 0x32, 0x6c, 0x4d, 0x39,
511 0x38, 0x71, 0x45, 0x49, 0x65, 0x68, 0x0a, 0x56, 0x67, 0x66, 0x41, 0x34,
512 0x7a, 0x69, 0x37, 0x4d, 0x45, 0x6c, 0x51, 0x61, 0x76, 0x6b, 0x52, 0x76,
513 0x32, 0x54, 0x43, 0x50, 0x50, 0x55, 0x51, 0x62, 0x35, 0x51, 0x64, 0x61,
514 0x6f, 0x37, 0x57, 0x78, 0x37, 0x6c, 0x66, 0x61, 0x54, 0x6f, 0x5a, 0x68,
515 0x4f, 0x54, 0x2b, 0x4e, 0x52, 0x68, 0x32, 0x6b, 0x35, 0x78, 0x2b, 0x6b,
516 0x6a, 0x5a, 0x46, 0x77, 0x38, 0x70, 0x45, 0x48, 0x74, 0x35, 0x51, 0x0a,
517 0x69, 0x68, 0x62, 0x46, 0x4c, 0x35, 0x58, 0x2b, 0x57, 0x7a, 0x6f, 0x2b,
518 0x42, 0x36, 0x36, 0x59, 0x79, 0x49, 0x76, 0x68, 0x77, 0x54, 0x63, 0x48,
519 0x30, 0x46, 0x2b, 0x6e, 0x66, 0x55, 0x71, 0x66, 0x74, 0x38, 0x59, 0x74,
520 0x72, 0x2f, 0x38, 0x37, 0x47, 0x45, 0x62, 0x73, 0x41, 0x48, 0x6a, 0x48,
521 0x43, 0x36, 0x4c, 0x2b, 0x77, 0x6b, 0x31, 0x76, 0x4e, 0x6e, 0x64, 0x49,
522 0x59, 0x47, 0x30, 0x51, 0x0a, 0x79, 0x62, 0x73, 0x7a, 0x78, 0x49, 0x72,
523 0x32, 0x6d, 0x46, 0x45, 0x49, 0x4a, 0x6f, 0x69, 0x51, 0x44, 0x44, 0x67,
524 0x66, 0x6c, 0x71, 0x67, 0x64, 0x76, 0x4c, 0x54, 0x32, 0x79, 0x64, 0x46,
525 0x6d, 0x79, 0x33, 0x73, 0x32, 0x68, 0x49, 0x74, 0x51, 0x6c, 0x49, 0x71,
526 0x4b, 0x4c, 0x42, 0x36, 0x49, 0x4a, 0x51, 0x49, 0x75, 0x69, 0x37, 0x72,
527 0x37, 0x34, 0x76, 0x64, 0x72, 0x63, 0x58, 0x71, 0x58, 0x0a, 0x44, 0x7a,
528 0x68, 0x6d, 0x4c, 0x66, 0x67, 0x6a, 0x67, 0x4c, 0x77, 0x33, 0x2b, 0x55,
529 0x79, 0x69, 0x59, 0x74, 0x44, 0x54, 0x76, 0x63, 0x78, 0x65, 0x7a, 0x62,
530 0x4c, 0x73, 0x76, 0x51, 0x6f, 0x52, 0x6b, 0x74, 0x77, 0x4b, 0x5a, 0x4c,
531 0x44, 0x54, 0x42, 0x42, 0x35, 0x76, 0x59, 0x32, 0x78, 0x4b, 0x36, 0x6b,
532 0x4f, 0x4f, 0x44, 0x70, 0x7a, 0x50, 0x48, 0x73, 0x4b, 0x67, 0x30, 0x42,
533 0x59, 0x77, 0x0a, 0x4d, 0x6b, 0x48, 0x56, 0x56, 0x54, 0x34, 0x79, 0x2f,
534 0x4d, 0x59, 0x36, 0x63, 0x63, 0x4b, 0x51, 0x2f, 0x4c, 0x56, 0x74, 0x32,
535 0x66, 0x4a, 0x49, 0x74, 0x69, 0x41, 0x71, 0x49, 0x47, 0x32, 0x38, 0x64,
536 0x37, 0x31, 0x53, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44,
537 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45,
538 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a
541 static void testCertTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
543 CRYPT_PROVIDER_DATA data = { 0 };
544 CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
545 HRESULT ret;
547 if (!CertFreeCertificateChain_p)
549 win_skip("CertFreeCertificateChain not found\n");
550 return;
553 data.padwTrustStepErrors =
554 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
555 if (!data.padwTrustStepErrors)
557 skip("pfnAlloc failed\n");
558 return;
560 ret = funcs->pfnCertificateTrust(&data);
561 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
562 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
563 TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
564 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
565 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
566 if (ret)
568 PCCERT_CONTEXT cert;
570 /* An empty signer "succeeds," even though there's no cert */
571 ret = funcs->pfnCertificateTrust(&data);
572 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
573 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
574 sizeof(selfSignedCert));
575 if (cert)
577 WINTRUST_DATA wintrust_data = { 0 };
579 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
580 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
582 /* If pWintrustData isn't set, crashes attempting to access
583 * pWintrustData->fdwRevocationChecks
585 data.pWintrustData = &wintrust_data;
586 /* If psPfns isn't set, crashes attempting to access
587 * psPfns->pfnCertCheckPolicy
589 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
590 ret = funcs->pfnCertificateTrust(&data);
591 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
592 ok(data.csSigners == 1, "Unexpected number of signers %d\n",
593 data.csSigners);
594 ok(data.pasSigners[0].pChainContext != NULL,
595 "Expected a certificate chain\n");
596 ok(data.pasSigners[0].csCertChain == 1,
597 "Unexpected number of chain elements %d\n",
598 data.pasSigners[0].csCertChain);
599 /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
600 * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
602 ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
603 "Didn't expect cert to be trusted\n");
604 ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
605 "Expected cert to be self-signed\n");
606 ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
607 (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
608 "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
609 data.pasSigners[0].pasCertChain[0].dwConfidence);
610 CertFreeCertificateContext(
611 data.pasSigners[0].pasCertChain[0].pCert);
612 CertFreeCertificateChain_p(data.pasSigners[0].pChainContext);
613 CertFreeCertificateContext(cert);
616 funcs->pfnFree(data.padwTrustStepErrors);
619 static void test_provider_funcs(void)
621 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
622 SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
623 BOOL ret;
625 ret = WintrustLoadFunctionPointers(&generic_verify_v2,
626 (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
627 if (!ret)
628 skip("WintrustLoadFunctionPointers failed\n");
629 else
631 test_utils(&funcs);
632 testInitialize(&funcs, &generic_verify_v2);
633 testObjTrust(&funcs, &generic_verify_v2);
634 testCertTrust(&funcs, &generic_verify_v2);
638 /* minimal PE file image */
639 #define VA_START 0x400000
640 #define FILE_PE_START 0x50
641 #define NUM_SECTIONS 3
642 #define FILE_TEXT 0x200
643 #define RVA_TEXT 0x1000
644 #define RVA_BSS 0x2000
645 #define FILE_IDATA 0x400
646 #define RVA_IDATA 0x3000
647 #define FILE_TOTAL 0x600
648 #define RVA_TOTAL 0x4000
649 #include <pshpack1.h>
650 struct Imports {
651 IMAGE_IMPORT_DESCRIPTOR descriptors[2];
652 IMAGE_THUNK_DATA32 original_thunks[2];
653 IMAGE_THUNK_DATA32 thunks[2];
654 struct __IMPORT_BY_NAME {
655 WORD hint;
656 char funcname[0x20];
657 } ibn;
658 char dllname[0x10];
660 #define EXIT_PROCESS (VA_START+RVA_IDATA+FIELD_OFFSET(struct Imports, thunks))
662 static struct _PeImage {
663 IMAGE_DOS_HEADER dos_header;
664 char __alignment1[FILE_PE_START - sizeof(IMAGE_DOS_HEADER)];
665 IMAGE_NT_HEADERS32 nt_headers;
666 IMAGE_SECTION_HEADER sections[NUM_SECTIONS];
667 char __alignment2[FILE_TEXT - FILE_PE_START - sizeof(IMAGE_NT_HEADERS32) -
668 NUM_SECTIONS * sizeof(IMAGE_SECTION_HEADER)];
669 unsigned char text_section[FILE_IDATA-FILE_TEXT];
670 struct Imports idata_section;
671 char __alignment3[FILE_TOTAL-FILE_IDATA-sizeof(struct Imports)];
672 } bin = {
673 /* dos header */
674 {IMAGE_DOS_SIGNATURE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, 0, {0}, FILE_PE_START},
675 /* alignment before PE header */
676 {0},
677 /* nt headers */
678 {IMAGE_NT_SIGNATURE,
679 /* basic headers - 3 sections, no symbols, EXE file */
680 {IMAGE_FILE_MACHINE_I386, NUM_SECTIONS, 0, 0, 0, sizeof(IMAGE_OPTIONAL_HEADER32),
681 IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE},
682 /* optional header */
683 {IMAGE_NT_OPTIONAL_HDR32_MAGIC, 4, 0, FILE_IDATA-FILE_TEXT,
684 FILE_TOTAL-FILE_IDATA + FILE_IDATA-FILE_TEXT, 0x400,
685 RVA_TEXT, RVA_TEXT, RVA_BSS, VA_START, 0x1000, 0x200, 4, 0, 1, 0, 4, 0, 0,
686 RVA_TOTAL, FILE_TEXT, 0, IMAGE_SUBSYSTEM_WINDOWS_GUI, 0,
687 0x200000, 0x1000, 0x100000, 0x1000, 0, 0x10,
688 {{0, 0},
689 {RVA_IDATA, sizeof(struct Imports)}
693 /* sections */
695 {".text", {0x100}, RVA_TEXT, FILE_IDATA-FILE_TEXT, FILE_TEXT,
696 0, 0, 0, 0, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ},
697 {".bss", {0x400}, RVA_BSS, 0, 0, 0, 0, 0, 0,
698 IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE},
699 {".idata", {sizeof(struct Imports)}, RVA_IDATA, FILE_TOTAL-FILE_IDATA, FILE_IDATA, 0,
700 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}
702 /* alignment before first section */
703 {0},
704 /* .text section */
706 0x31, 0xC0, /* xor eax, eax */
707 0xFF, 0x25, EXIT_PROCESS&0xFF, (EXIT_PROCESS>>8)&0xFF, (EXIT_PROCESS>>16)&0xFF,
708 (EXIT_PROCESS>>24)&0xFF, /* jmp ExitProcess */
711 /* .idata section */
714 {{RVA_IDATA + FIELD_OFFSET(struct Imports, original_thunks)}, 0, 0,
715 RVA_IDATA + FIELD_OFFSET(struct Imports, dllname),
716 RVA_IDATA + FIELD_OFFSET(struct Imports, thunks)
718 {{0}, 0, 0, 0, 0}
720 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
721 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
722 {0,"ExitProcess"},
723 "KERNEL32.DLL"
725 /* final alignment */
728 #include <poppack.h>
730 static void test_sip_create_indirect_data(void)
732 static GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
733 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
734 static char oid_sha1[] = szOID_OIWSEC_sha1;
735 BOOL ret;
736 SIP_SUBJECTINFO subjinfo = { 0 };
737 WCHAR temp_file[MAX_PATH];
738 HANDLE file;
739 DWORD count;
741 if (!CryptSIPCreateIndirectData_p)
743 skip("Missing CryptSIPCreateIndirectData\n");
744 return;
746 SetLastError(0xdeadbeef);
747 ret = CryptSIPCreateIndirectData_p(NULL, NULL, NULL);
748 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
749 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
750 SetLastError(0xdeadbeef);
751 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
752 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
753 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
754 subjinfo.cbSize = sizeof(subjinfo);
755 SetLastError(0xdeadbeef);
756 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
757 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
758 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
759 file = create_temp_file(temp_file);
760 if (file == INVALID_HANDLE_VALUE)
762 skip("couldn't create temp file\n");
763 return;
765 WriteFile(file, &bin, sizeof(bin), &count, NULL);
766 FlushFileBuffers(file);
768 subjinfo.hFile = file;
769 SetLastError(0xdeadbeef);
770 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
771 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
772 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
773 subjinfo.pgSubjectType = &unknown;
774 SetLastError(0xdeadbeef);
775 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
776 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
777 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
778 count = 0xdeadbeef;
779 SetLastError(0xdeadbeef);
780 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
781 todo_wine
782 ok(!ret && (GetLastError() == NTE_BAD_ALGID ||
783 GetLastError() == ERROR_INVALID_PARAMETER /* Win7 */),
784 "expected NTE_BAD_ALGID or ERROR_INVALID_PARAMETER, got %08x\n",
785 GetLastError());
786 ok(count == 0xdeadbeef, "expected count to be unmodified, got %d\n", count);
787 subjinfo.DigestAlgorithm.pszObjId = oid_sha1;
788 count = 0xdeadbeef;
789 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
790 todo_wine
791 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
792 ok(count, "expected a positive count\n");
793 if (ret)
795 SIP_INDIRECT_DATA *indirect = HeapAlloc(GetProcessHeap(), 0, count);
797 count = 256;
798 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, indirect);
799 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
800 /* If the count is larger than needed, it's unmodified */
801 ok(count == 256, "unexpected count %d\n", count);
802 ok(!strcmp(indirect->Data.pszObjId, SPC_PE_IMAGE_DATA_OBJID),
803 "unexpected data oid %s\n",
804 indirect->Data.pszObjId);
805 ok(!strcmp(indirect->DigestAlgorithm.pszObjId, oid_sha1),
806 "unexpected digest algorithm oid %s\n",
807 indirect->DigestAlgorithm.pszObjId);
808 ok(indirect->Digest.cbData == 20, "unexpected hash size %d\n",
809 indirect->Digest.cbData);
810 if (indirect->Digest.cbData == 20)
812 const BYTE hash[20] = {
813 0x8a,0xd5,0x45,0x53,0x3d,0x67,0xdf,0x2f,0x78,0xe0,
814 0x55,0x0a,0xe0,0xd9,0x7a,0x28,0x3e,0xbf,0x45,0x2b };
816 ok(!memcmp(indirect->Digest.pbData, hash, 20),
817 "unexpected value\n");
820 HeapFree(GetProcessHeap(), 0, indirect);
822 CloseHandle(file);
823 DeleteFileW(temp_file);
826 static void test_wintrust(void)
828 static GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
829 WINTRUST_DATA wtd;
830 WINTRUST_FILE_INFO file;
831 LONG r;
832 HRESULT hr;
833 WCHAR pathW[MAX_PATH];
835 memset(&wtd, 0, sizeof(wtd));
836 wtd.cbStruct = sizeof(wtd);
837 wtd.dwUIChoice = WTD_UI_NONE;
838 wtd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
839 wtd.dwUnionChoice = WTD_CHOICE_FILE;
840 U(wtd).pFile = &file;
841 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
842 memset(&file, 0, sizeof(file));
843 file.cbStruct = sizeof(file);
844 file.pcwszFilePath = pathW;
845 /* Test with an empty file */
846 file.hFile = create_temp_file(pathW);
847 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
848 ok(r == TRUST_E_SUBJECT_FORM_UNKNOWN,
849 "expected TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n", r);
850 CloseHandle(file.hFile);
851 DeleteFileW(pathW);
852 file.hFile = NULL;
853 /* Test with a known file path, which we expect not have a signature */
854 getNotepadPath(pathW, MAX_PATH);
855 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
856 ok(r == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
857 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", r);
858 wtd.dwStateAction = WTD_STATEACTION_CLOSE;
859 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
860 ok(r == S_OK, "WinVerifyTrust failed: %08x\n", r);
861 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
862 hr = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
863 ok(hr == TRUST_E_NOSIGNATURE || hr == CRYPT_E_FILE_ERROR,
864 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", hr);
865 wtd.dwStateAction = WTD_STATEACTION_CLOSE;
866 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
867 ok(r == S_OK, "WinVerifyTrust failed: %08x\n", r);
870 static void test_get_known_usages(void)
872 BOOL ret;
873 PCCRYPT_OID_INFO *usages;
875 if (!pWTHelperGetKnownUsages)
877 skip("missing WTHelperGetKnownUsages\n");
878 return;
880 SetLastError(0xdeadbeef);
881 ret = pWTHelperGetKnownUsages(0, NULL);
882 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
883 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
884 SetLastError(0xdeadbeef);
885 ret = pWTHelperGetKnownUsages(1, NULL);
886 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
887 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
888 SetLastError(0xdeadbeef);
889 ret = pWTHelperGetKnownUsages(0, &usages);
890 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
891 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
892 /* A value of 1 for the first parameter seems to imply the value is
893 * allocated
895 SetLastError(0xdeadbeef);
896 usages = NULL;
897 ret = pWTHelperGetKnownUsages(1, &usages);
898 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
899 ok(usages != NULL, "expected a pointer\n");
900 if (ret && usages)
902 PCCRYPT_OID_INFO *ptr;
904 /* The returned usages are an array of PCCRYPT_OID_INFOs, terminated with a
905 * NULL pointer.
907 for (ptr = usages; *ptr; ptr++)
909 ok((*ptr)->cbSize == sizeof(CRYPT_OID_INFO) ||
910 (*ptr)->cbSize == (sizeof(CRYPT_OID_INFO) + 2 * sizeof(LPCWSTR)), /* Vista */
911 "unexpected size %d\n", (*ptr)->cbSize);
912 /* Each returned usage is in the CRYPT_ENHKEY_USAGE_OID_GROUP_ID group */
913 ok((*ptr)->dwGroupId == CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
914 "expected group CRYPT_ENHKEY_USAGE_OID_GROUP_ID, got %d\n",
915 (*ptr)->dwGroupId);
918 /* A value of 2 for the second parameter seems to imply the value is freed
920 SetLastError(0xdeadbeef);
921 ret = pWTHelperGetKnownUsages(2, &usages);
922 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
923 ok(usages == NULL, "expected pointer to be cleared\n");
924 SetLastError(0xdeadbeef);
925 usages = NULL;
926 ret = pWTHelperGetKnownUsages(2, &usages);
927 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
928 SetLastError(0xdeadbeef);
929 ret = pWTHelperGetKnownUsages(2, NULL);
930 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
931 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
934 START_TEST(softpub)
936 InitFunctionPtrs();
937 test_provider_funcs();
938 test_sip_create_indirect_data();
939 test_wintrust();
940 test_get_known_usages();