[WINTRUST_WINETEST]
[reactos.git] / rostests / winetests / wintrust / softpub.c
1 /*
2 * wintrust softpub functions tests
3 *
4 * Copyright 2007,2010 Juan Lang
5 * Copyright 2010 Andrey Turkin
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include <stdio.h>
23 #include <stdarg.h>
24
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"
33
34 #include "wine/test.h"
35
36 /* Just in case we're being built with borked headers, redefine function
37 * pointers to have the correct calling convention.
38 */
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);
59
60 typedef struct _SAFE_PROVIDER_FUNCTIONS
61 {
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;
79
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);
83
84 static void InitFunctionPtrs(void)
85 {
86 HMODULE hWintrust = GetModuleHandleA("wintrust.dll");
87 HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
88
89 #define WINTRUST_GET_PROC(func) \
90 p ## func = (void*)GetProcAddress(hWintrust, #func); \
91 if(!p ## func) { \
92 trace("GetProcAddress(%s) failed\n", #func); \
93 }
94
95 WINTRUST_GET_PROC(WTHelperGetKnownUsages)
96
97 #undef WINTRUST_GET_PROC
98
99 #define CRYPT32_GET_PROC(func) \
100 func ## _p = (void*)GetProcAddress(hCrypt32, #func); \
101 if(!func ## _p) { \
102 trace("GetProcAddress(%s) failed\n", #func); \
103 }
104
105 CRYPT32_GET_PROC(CryptSIPCreateIndirectData)
106 CRYPT32_GET_PROC(CertFreeCertificateChain)
107
108 #undef CRYPT32_GET_PROC
109 }
110
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 };
123
124 static void test_utils(SAFE_PROVIDER_FUNCTIONS *funcs)
125 {
126 CRYPT_PROVIDER_DATA data = { 0 };
127 HCERTSTORE store;
128 CRYPT_PROVIDER_SGNR sgnr = { 0 };
129 BOOL ret;
130
131 /* Crash
132 ret = funcs->pfnAddStore2Chain(NULL, NULL);
133 ret = funcs->pfnAddStore2Chain(&data, NULL);
134 */
135 store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0,
136 CERT_STORE_CREATE_NEW_FLAG, NULL);
137 if (store)
138 {
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)
144 {
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;
152 }
153 }
154 else
155 skip("CertOpenStore failed: %08x\n", GetLastError());
156
157 /* Crash
158 ret = funcs->pfnAddSgnr2Chain(NULL, FALSE, 0, NULL);
159 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, NULL);
160 */
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)
166 {
167 PCCERT_CONTEXT cert;
168
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());
195
196 /* Crash
197 ret = funcs->pfnAddCert2Chain(NULL, 0, FALSE, 0, NULL);
198 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, NULL);
199 */
200 cert = CertCreateCertificateContext(X509_ASN_ENCODING, v1CertWithPubKey,
201 sizeof(v1CertWithPubKey));
202 if (cert)
203 {
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.
207 */
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)
215 {
216 ok(data.pasSigners[0].pasCertChain[0].pCert == cert,
217 "Unexpected cert\n");
218 CertFreeCertificateContext(
219 data.pasSigners[0].pasCertChain[0].pCert);
220 }
221 CertFreeCertificateContext(cert);
222 }
223 else
224 skip("CertCreateCertificateContext failed: %08x\n", GetLastError());
225 funcs->pfnFree(data.pasSigners);
226 }
227 }
228
229 static void testInitialize(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
230 {
231 HRESULT ret;
232 CRYPT_PROVIDER_DATA data = { 0 };
233 WINTRUST_DATA wintrust_data = { 0 };
234
235 if (!funcs->pfnInitialize)
236 {
237 skip("missing pfnInitialize\n");
238 return;
239 }
240
241 /* Crashes
242 ret = funcs->pfnInitialize(NULL);
243 */
244 memset(&data, 0, sizeof(data));
245 ret = funcs->pfnInitialize(&data);
246 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
247 data.padwTrustStepErrors =
248 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
249 /* Without wintrust data set, crashes when padwTrustStepErrors is set */
250 data.pWintrustData = &wintrust_data;
251 if (data.padwTrustStepErrors)
252 {
253 /* Apparently, cdwTrustStepErrors does not need to be set. */
254 ret = funcs->pfnInitialize(&data);
255 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
256 data.cdwTrustStepErrors = 1;
257 ret = funcs->pfnInitialize(&data);
258 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
259 memset(data.padwTrustStepErrors, 0xba,
260 TRUSTERROR_MAX_STEPS * sizeof(DWORD));
261 ret = funcs->pfnInitialize(&data);
262 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
263 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] = 0;
264 ret = funcs->pfnInitialize(&data);
265 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
266 funcs->pfnFree(data.padwTrustStepErrors);
267 }
268 }
269
270 static void getNotepadPath(WCHAR *notepadPathW, DWORD size)
271 {
272 static const CHAR notepad[] = "\\notepad.exe";
273 CHAR notepadPath[MAX_PATH];
274
275 /* Workaround missing W-functions for win9x */
276 GetWindowsDirectoryA(notepadPath, MAX_PATH);
277 lstrcatA(notepadPath, notepad);
278 MultiByteToWideChar(CP_ACP, 0, notepadPath, -1, notepadPathW, size);
279 }
280
281 /* Creates a test file and returns a handle to it. The file's path is returned
282 * in temp_file, which must be at least MAX_PATH characters in length.
283 */
284 static HANDLE create_temp_file(WCHAR *temp_file)
285 {
286 HANDLE file = INVALID_HANDLE_VALUE;
287 WCHAR temp_path[MAX_PATH];
288
289 if (GetTempPathW(sizeof(temp_path) / sizeof(temp_path[0]), temp_path))
290 {
291 static const WCHAR img[] = { 'i','m','g',0 };
292
293 if (GetTempFileNameW(temp_path, img, 0, temp_file))
294 file = CreateFileW(temp_file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
295 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
296 }
297 return file;
298 }
299
300 static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
301 {
302 HRESULT ret;
303 CRYPT_PROVIDER_DATA data = { 0 };
304 WINTRUST_DATA wintrust_data = { 0 };
305 WINTRUST_CERT_INFO certInfo = { sizeof(WINTRUST_CERT_INFO), 0 };
306 WINTRUST_FILE_INFO fileInfo = { sizeof(WINTRUST_FILE_INFO), 0 };
307
308 if (!funcs->pfnObjectTrust)
309 {
310 skip("missing pfnObjectTrust\n");
311 return;
312 }
313
314 /* Crashes
315 ret = funcs->pfnObjectTrust(NULL);
316 */
317 data.pWintrustData = &wintrust_data;
318 data.padwTrustStepErrors =
319 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
320 if (data.padwTrustStepErrors)
321 {
322 WCHAR pathW[MAX_PATH];
323 PROVDATA_SIP provDataSIP = { 0 };
324 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
325 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
326 static GUID bogusGuid = { 0xdeadbeef, 0xbaad, 0xf00d, { 0x00,0x00,0x00,
327 0x00,0x00,0x00,0x00,0x00 } };
328
329 ret = funcs->pfnObjectTrust(&data);
330 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
331 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
332 ERROR_INVALID_PARAMETER,
333 "Expected ERROR_INVALID_PARAMETER, got %08x\n",
334 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
335 U(wintrust_data).pCert = &certInfo;
336 wintrust_data.dwUnionChoice = WTD_CHOICE_CERT;
337 ret = funcs->pfnObjectTrust(&data);
338 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
339 certInfo.psCertContext = (PCERT_CONTEXT)CertCreateCertificateContext(
340 X509_ASN_ENCODING, v1CertWithPubKey, sizeof(v1CertWithPubKey));
341 ret = funcs->pfnObjectTrust(&data);
342 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
343 CertFreeCertificateContext(certInfo.psCertContext);
344 certInfo.psCertContext = NULL;
345 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
346 U(wintrust_data).pFile = NULL;
347 ret = funcs->pfnObjectTrust(&data);
348 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
349 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
350 ERROR_INVALID_PARAMETER,
351 "Expected ERROR_INVALID_PARAMETER, got %08x\n",
352 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
353 U(wintrust_data).pFile = &fileInfo;
354 /* Crashes
355 ret = funcs->pfnObjectTrust(&data);
356 */
357 /* Create and test with an empty file */
358 fileInfo.hFile = create_temp_file(pathW);
359 /* pfnObjectTrust now crashes unless both pPDSip and psPfns are set */
360 U(data).pPDSip = &provDataSIP;
361 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
362 ret = funcs->pfnObjectTrust(&data);
363 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
364 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
365 TRUST_E_SUBJECT_FORM_UNKNOWN,
366 "expected TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
367 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
368 CloseHandle(fileInfo.hFile);
369 fileInfo.hFile = NULL;
370 fileInfo.pcwszFilePath = pathW;
371 ret = funcs->pfnObjectTrust(&data);
372 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
373 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
374 TRUST_E_SUBJECT_FORM_UNKNOWN,
375 "expected TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
376 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
377 DeleteFileW(pathW);
378 /* Test again with a file we expect to exist, and to contain no
379 * signature.
380 */
381 getNotepadPath(pathW, MAX_PATH);
382 ret = funcs->pfnObjectTrust(&data);
383 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
384 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
385 TRUST_E_NOSIGNATURE ||
386 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
387 TRUST_E_SUBJECT_FORM_UNKNOWN,
388 "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
389 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
390 if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
391 TRUST_E_NOSIGNATURE)
392 {
393 ok(!memcmp(&provDataSIP.gSubject, &unknown, sizeof(unknown)),
394 "Unexpected subject GUID\n");
395 ok(provDataSIP.pSip != NULL, "Expected a SIP\n");
396 ok(provDataSIP.psSipSubjectInfo != NULL,
397 "Expected a subject info\n");
398 }
399 /* Specifying the GUID results in that GUID being the subject GUID */
400 fileInfo.pgKnownSubject = &bogusGuid;
401 ret = funcs->pfnObjectTrust(&data);
402 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
403 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
404 TRUST_E_NOSIGNATURE ||
405 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
406 TRUST_E_SUBJECT_FORM_UNKNOWN ||
407 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
408 TRUST_E_PROVIDER_UNKNOWN,
409 "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN or TRUST_E_PROVIDER_UNKNOWN, got %08x\n",
410 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
411 if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
412 TRUST_E_NOSIGNATURE)
413 {
414 ok(!memcmp(&provDataSIP.gSubject, &bogusGuid, sizeof(bogusGuid)),
415 "unexpected subject GUID\n");
416 }
417 /* Specifying a bogus GUID pointer crashes */
418 if (0)
419 {
420 fileInfo.pgKnownSubject = (GUID *)0xdeadbeef;
421 ret = funcs->pfnObjectTrust(&data);
422 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
423 }
424 funcs->pfnFree(data.padwTrustStepErrors);
425 }
426 }
427
428 static const BYTE selfSignedCert[] = {
429 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43,
430 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
431 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44, 0x70, 0x7a, 0x43, 0x43,
432 0x41, 0x6f, 0x2b, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x4a,
433 0x41, 0x4c, 0x59, 0x51, 0x67, 0x65, 0x66, 0x7a, 0x51, 0x41, 0x61, 0x43,
434 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33,
435 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x4d, 0x47, 0x6f, 0x78,
436 0x43, 0x7a, 0x41, 0x4a, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, 0x41, 0x59,
437 0x54, 0x41, 0x6b, 0x46, 0x56, 0x4d, 0x52, 0x4d, 0x77, 0x45, 0x51, 0x59,
438 0x44, 0x56, 0x51, 0x51, 0x49, 0x44, 0x41, 0x70, 0x54, 0x62, 0x32, 0x31,
439 0x6c, 0x4c, 0x56, 0x4e, 0x30, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x53, 0x45,
440 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x42, 0x68,
441 0x4a, 0x62, 0x6e, 0x52, 0x6c, 0x63, 0x6d, 0x35, 0x6c, 0x64, 0x43, 0x42,
442 0x58, 0x0a, 0x61, 0x57, 0x52, 0x6e, 0x61, 0x58, 0x52, 0x7a, 0x49, 0x46,
443 0x42, 0x30, 0x65, 0x53, 0x42, 0x4d, 0x64, 0x47, 0x51, 0x78, 0x49, 0x7a,
444 0x41, 0x68, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x4d, 0x4d, 0x47, 0x6e,
445 0x4e, 0x6c, 0x62, 0x47, 0x5a, 0x7a, 0x61, 0x57, 0x64, 0x75, 0x5a, 0x57,
446 0x51, 0x75, 0x64, 0x47, 0x56, 0x7a, 0x64, 0x43, 0x35, 0x33, 0x61, 0x57,
447 0x35, 0x6c, 0x61, 0x48, 0x45, 0x75, 0x0a, 0x62, 0x33, 0x4a, 0x6e, 0x4d,
448 0x42, 0x34, 0x58, 0x44, 0x54, 0x45, 0x7a, 0x4d, 0x44, 0x59, 0x79, 0x4d,
449 0x54, 0x45, 0x78, 0x4d, 0x6a, 0x55, 0x78, 0x4d, 0x46, 0x6f, 0x58, 0x44,
450 0x54, 0x49, 0x7a, 0x4d, 0x44, 0x59, 0x78, 0x4f, 0x54, 0x45, 0x78, 0x4d,
451 0x6a, 0x55, 0x78, 0x4d, 0x46, 0x6f, 0x77, 0x61, 0x6a, 0x45, 0x4c, 0x4d,
452 0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, 0x43, 0x0a,
453 0x51, 0x56, 0x55, 0x78, 0x45, 0x7a, 0x41, 0x52, 0x42, 0x67, 0x4e, 0x56,
454 0x42, 0x41, 0x67, 0x4d, 0x43, 0x6c, 0x4e, 0x76, 0x62, 0x57, 0x55, 0x74,
455 0x55, 0x33, 0x52, 0x68, 0x64, 0x47, 0x55, 0x78, 0x49, 0x54, 0x41, 0x66,
456 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x47, 0x45, 0x6c, 0x75,
457 0x64, 0x47, 0x56, 0x79, 0x62, 0x6d, 0x56, 0x30, 0x49, 0x46, 0x64, 0x70,
458 0x5a, 0x47, 0x64, 0x70, 0x0a, 0x64, 0x48, 0x4d, 0x67, 0x55, 0x48, 0x52,
459 0x35, 0x49, 0x45, 0x78, 0x30, 0x5a, 0x44, 0x45, 0x6a, 0x4d, 0x43, 0x45,
460 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x61, 0x63, 0x32, 0x56,
461 0x73, 0x5a, 0x6e, 0x4e, 0x70, 0x5a, 0x32, 0x35, 0x6c, 0x5a, 0x43, 0x35,
462 0x30, 0x5a, 0x58, 0x4e, 0x30, 0x4c, 0x6e, 0x64, 0x70, 0x62, 0x6d, 0x56,
463 0x6f, 0x63, 0x53, 0x35, 0x76, 0x63, 0x6d, 0x63, 0x77, 0x0a, 0x67, 0x67,
464 0x45, 0x69, 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49,
465 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34,
466 0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4b, 0x41, 0x6f,
467 0x49, 0x42, 0x41, 0x51, 0x44, 0x77, 0x4e, 0x6d, 0x2b, 0x46, 0x7a, 0x78,
468 0x6e, 0x6b, 0x48, 0x57, 0x2f, 0x4e, 0x70, 0x37, 0x59, 0x48, 0x34, 0x4d,
469 0x79, 0x45, 0x0a, 0x77, 0x4d, 0x6c, 0x49, 0x67, 0x71, 0x30, 0x66, 0x45,
470 0x77, 0x70, 0x47, 0x6f, 0x41, 0x75, 0x78, 0x44, 0x64, 0x61, 0x46, 0x55,
471 0x32, 0x6f, 0x70, 0x76, 0x41, 0x51, 0x56, 0x61, 0x2b, 0x41, 0x43, 0x46,
472 0x38, 0x63, 0x6f, 0x38, 0x4d, 0x4a, 0x6c, 0x33, 0x78, 0x77, 0x76, 0x46,
473 0x44, 0x2b, 0x67, 0x61, 0x46, 0x45, 0x7a, 0x59, 0x78, 0x53, 0x58, 0x30,
474 0x43, 0x47, 0x72, 0x4a, 0x45, 0x4c, 0x63, 0x0a, 0x74, 0x34, 0x4d, 0x69,
475 0x30, 0x68, 0x4b, 0x50, 0x76, 0x42, 0x70, 0x65, 0x73, 0x59, 0x6c, 0x46,
476 0x4d, 0x51, 0x65, 0x6b, 0x2b, 0x63, 0x70, 0x51, 0x50, 0x33, 0x4b, 0x35,
477 0x75, 0x36, 0x71, 0x58, 0x5a, 0x52, 0x49, 0x67, 0x48, 0x75, 0x59, 0x45,
478 0x4c, 0x2f, 0x73, 0x55, 0x6f, 0x39, 0x32, 0x70, 0x44, 0x30, 0x7a, 0x4a,
479 0x65, 0x4c, 0x47, 0x41, 0x31, 0x49, 0x30, 0x4b, 0x5a, 0x34, 0x73, 0x2f,
480 0x0a, 0x51, 0x7a, 0x77, 0x61, 0x4f, 0x38, 0x62, 0x62, 0x4b, 0x6d, 0x37,
481 0x42, 0x72, 0x6e, 0x56, 0x77, 0x30, 0x6e, 0x5a, 0x2f, 0x4b, 0x41, 0x5a,
482 0x6a, 0x75, 0x78, 0x75, 0x6f, 0x4e, 0x33, 0x52, 0x64, 0x72, 0x69, 0x30,
483 0x4a, 0x48, 0x77, 0x7a, 0x6a, 0x41, 0x55, 0x34, 0x2b, 0x71, 0x57, 0x65,
484 0x55, 0x63, 0x2f, 0x64, 0x33, 0x45, 0x70, 0x4f, 0x47, 0x78, 0x69, 0x42,
485 0x77, 0x5a, 0x4e, 0x61, 0x7a, 0x0a, 0x39, 0x6f, 0x4a, 0x41, 0x37, 0x54,
486 0x2f, 0x51, 0x6f, 0x62, 0x75, 0x61, 0x4e, 0x53, 0x6b, 0x65, 0x55, 0x48,
487 0x43, 0x61, 0x50, 0x53, 0x6a, 0x44, 0x37, 0x71, 0x7a, 0x6c, 0x43, 0x4f,
488 0x52, 0x48, 0x47, 0x68, 0x75, 0x31, 0x76, 0x79, 0x79, 0x35, 0x31, 0x45,
489 0x36, 0x79, 0x46, 0x43, 0x4e, 0x47, 0x66, 0x65, 0x7a, 0x71, 0x2f, 0x4d,
490 0x59, 0x34, 0x4e, 0x4b, 0x68, 0x77, 0x72, 0x61, 0x59, 0x64, 0x0a, 0x62,
491 0x79, 0x49, 0x2f, 0x6c, 0x42, 0x46, 0x62, 0x36, 0x35, 0x6b, 0x5a, 0x45,
492 0x66, 0x49, 0x4b, 0x4b, 0x54, 0x7a, 0x79, 0x36, 0x76, 0x30, 0x44, 0x65,
493 0x79, 0x50, 0x37, 0x52, 0x6b, 0x34, 0x75, 0x48, 0x44, 0x38, 0x77, 0x62,
494 0x49, 0x79, 0x50, 0x32, 0x47, 0x6c, 0x42, 0x30, 0x67, 0x37, 0x2f, 0x69,
495 0x79, 0x33, 0x4c, 0x61, 0x74, 0x49, 0x74, 0x49, 0x70, 0x2b, 0x49, 0x35,
496 0x53, 0x50, 0x56, 0x0a, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, 0x47, 0x6a,
497 0x55, 0x44, 0x42, 0x4f, 0x4d, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64,
498 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, 0x36, 0x49, 0x4c, 0x5a, 0x2f,
499 0x71, 0x38, 0x66, 0x2f, 0x4b, 0x45, 0x68, 0x4b, 0x76, 0x68, 0x69, 0x2b,
500 0x73, 0x6b, 0x59, 0x45, 0x31, 0x79, 0x48, 0x71, 0x39, 0x7a, 0x41, 0x66,
501 0x42, 0x67, 0x4e, 0x56, 0x48, 0x53, 0x4d, 0x45, 0x0a, 0x47, 0x44, 0x41,
502 0x57, 0x67, 0x42, 0x53, 0x36, 0x49, 0x4c, 0x5a, 0x2f, 0x71, 0x38, 0x66,
503 0x2f, 0x4b, 0x45, 0x68, 0x4b, 0x76, 0x68, 0x69, 0x2b, 0x73, 0x6b, 0x59,
504 0x45, 0x31, 0x79, 0x48, 0x71, 0x39, 0x7a, 0x41, 0x4d, 0x42, 0x67, 0x4e,
505 0x56, 0x48, 0x52, 0x4d, 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48,
506 0x2f, 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, 0x62,
507 0x33, 0x0a, 0x44, 0x51, 0x45, 0x42, 0x42, 0x51, 0x55, 0x41, 0x41, 0x34,
508 0x49, 0x42, 0x41, 0x51, 0x41, 0x79, 0x5a, 0x59, 0x77, 0x47, 0x4b, 0x46,
509 0x34, 0x34, 0x43, 0x68, 0x47, 0x51, 0x72, 0x6e, 0x74, 0x57, 0x6c, 0x38,
510 0x48, 0x53, 0x4a, 0x30, 0x63, 0x69, 0x55, 0x58, 0x4d, 0x44, 0x4b, 0x32,
511 0x46, 0x6c, 0x6f, 0x74, 0x47, 0x49, 0x6a, 0x30, 0x32, 0x6c, 0x4d, 0x39,
512 0x38, 0x71, 0x45, 0x49, 0x65, 0x68, 0x0a, 0x56, 0x67, 0x66, 0x41, 0x34,
513 0x7a, 0x69, 0x37, 0x4d, 0x45, 0x6c, 0x51, 0x61, 0x76, 0x6b, 0x52, 0x76,
514 0x32, 0x54, 0x43, 0x50, 0x50, 0x55, 0x51, 0x62, 0x35, 0x51, 0x64, 0x61,
515 0x6f, 0x37, 0x57, 0x78, 0x37, 0x6c, 0x66, 0x61, 0x54, 0x6f, 0x5a, 0x68,
516 0x4f, 0x54, 0x2b, 0x4e, 0x52, 0x68, 0x32, 0x6b, 0x35, 0x78, 0x2b, 0x6b,
517 0x6a, 0x5a, 0x46, 0x77, 0x38, 0x70, 0x45, 0x48, 0x74, 0x35, 0x51, 0x0a,
518 0x69, 0x68, 0x62, 0x46, 0x4c, 0x35, 0x58, 0x2b, 0x57, 0x7a, 0x6f, 0x2b,
519 0x42, 0x36, 0x36, 0x59, 0x79, 0x49, 0x76, 0x68, 0x77, 0x54, 0x63, 0x48,
520 0x30, 0x46, 0x2b, 0x6e, 0x66, 0x55, 0x71, 0x66, 0x74, 0x38, 0x59, 0x74,
521 0x72, 0x2f, 0x38, 0x37, 0x47, 0x45, 0x62, 0x73, 0x41, 0x48, 0x6a, 0x48,
522 0x43, 0x36, 0x4c, 0x2b, 0x77, 0x6b, 0x31, 0x76, 0x4e, 0x6e, 0x64, 0x49,
523 0x59, 0x47, 0x30, 0x51, 0x0a, 0x79, 0x62, 0x73, 0x7a, 0x78, 0x49, 0x72,
524 0x32, 0x6d, 0x46, 0x45, 0x49, 0x4a, 0x6f, 0x69, 0x51, 0x44, 0x44, 0x67,
525 0x66, 0x6c, 0x71, 0x67, 0x64, 0x76, 0x4c, 0x54, 0x32, 0x79, 0x64, 0x46,
526 0x6d, 0x79, 0x33, 0x73, 0x32, 0x68, 0x49, 0x74, 0x51, 0x6c, 0x49, 0x71,
527 0x4b, 0x4c, 0x42, 0x36, 0x49, 0x4a, 0x51, 0x49, 0x75, 0x69, 0x37, 0x72,
528 0x37, 0x34, 0x76, 0x64, 0x72, 0x63, 0x58, 0x71, 0x58, 0x0a, 0x44, 0x7a,
529 0x68, 0x6d, 0x4c, 0x66, 0x67, 0x6a, 0x67, 0x4c, 0x77, 0x33, 0x2b, 0x55,
530 0x79, 0x69, 0x59, 0x74, 0x44, 0x54, 0x76, 0x63, 0x78, 0x65, 0x7a, 0x62,
531 0x4c, 0x73, 0x76, 0x51, 0x6f, 0x52, 0x6b, 0x74, 0x77, 0x4b, 0x5a, 0x4c,
532 0x44, 0x54, 0x42, 0x42, 0x35, 0x76, 0x59, 0x32, 0x78, 0x4b, 0x36, 0x6b,
533 0x4f, 0x4f, 0x44, 0x70, 0x7a, 0x50, 0x48, 0x73, 0x4b, 0x67, 0x30, 0x42,
534 0x59, 0x77, 0x0a, 0x4d, 0x6b, 0x48, 0x56, 0x56, 0x54, 0x34, 0x79, 0x2f,
535 0x4d, 0x59, 0x36, 0x63, 0x63, 0x4b, 0x51, 0x2f, 0x4c, 0x56, 0x74, 0x32,
536 0x66, 0x4a, 0x49, 0x74, 0x69, 0x41, 0x71, 0x49, 0x47, 0x32, 0x38, 0x64,
537 0x37, 0x31, 0x53, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44,
538 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45,
539 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a
540 };
541
542 static void testCertTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
543 {
544 CRYPT_PROVIDER_DATA data = { 0 };
545 CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
546 HRESULT ret;
547
548 if (!CertFreeCertificateChain_p)
549 {
550 win_skip("CertFreeCertificateChain not found\n");
551 return;
552 }
553
554 data.padwTrustStepErrors =
555 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
556 if (!data.padwTrustStepErrors)
557 {
558 skip("pfnAlloc failed\n");
559 return;
560 }
561 ret = funcs->pfnCertificateTrust(&data);
562 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
563 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
564 TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
565 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
566 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
567 if (ret)
568 {
569 PCCERT_CONTEXT cert;
570
571 /* An empty signer "succeeds," even though there's no cert */
572 ret = funcs->pfnCertificateTrust(&data);
573 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
574 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
575 sizeof(selfSignedCert));
576 if (cert)
577 {
578 WINTRUST_DATA wintrust_data = { 0 };
579
580 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
581 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
582
583 /* If pWintrustData isn't set, crashes attempting to access
584 * pWintrustData->fdwRevocationChecks
585 */
586 data.pWintrustData = &wintrust_data;
587 /* If psPfns isn't set, crashes attempting to access
588 * psPfns->pfnCertCheckPolicy
589 */
590 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
591 ret = funcs->pfnCertificateTrust(&data);
592 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
593 ok(data.csSigners == 1, "Unexpected number of signers %d\n",
594 data.csSigners);
595 ok(data.pasSigners[0].pChainContext != NULL,
596 "Expected a certificate chain\n");
597 ok(data.pasSigners[0].csCertChain == 1,
598 "Unexpected number of chain elements %d\n",
599 data.pasSigners[0].csCertChain);
600 /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
601 * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
602 */
603 ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
604 "Didn't expect cert to be trusted\n");
605 ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
606 "Expected cert to be self-signed\n");
607 ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
608 (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
609 "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
610 data.pasSigners[0].pasCertChain[0].dwConfidence);
611 CertFreeCertificateContext(
612 data.pasSigners[0].pasCertChain[0].pCert);
613 CertFreeCertificateChain_p(data.pasSigners[0].pChainContext);
614 CertFreeCertificateContext(cert);
615 }
616 }
617 funcs->pfnFree(data.padwTrustStepErrors);
618 }
619
620 static void test_provider_funcs(void)
621 {
622 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
623 SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
624 BOOL ret;
625
626 ret = WintrustLoadFunctionPointers(&generic_verify_v2,
627 (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
628 if (!ret)
629 skip("WintrustLoadFunctionPointers failed\n");
630 else
631 {
632 test_utils(&funcs);
633 testInitialize(&funcs, &generic_verify_v2);
634 testObjTrust(&funcs, &generic_verify_v2);
635 testCertTrust(&funcs, &generic_verify_v2);
636 }
637 }
638
639 /* minimal PE file image */
640 #define VA_START 0x400000
641 #define FILE_PE_START 0x50
642 #define NUM_SECTIONS 3
643 #define FILE_TEXT 0x200
644 #define RVA_TEXT 0x1000
645 #define RVA_BSS 0x2000
646 #define FILE_IDATA 0x400
647 #define RVA_IDATA 0x3000
648 #define FILE_TOTAL 0x600
649 #define RVA_TOTAL 0x4000
650 #include <pshpack1.h>
651 struct Imports {
652 IMAGE_IMPORT_DESCRIPTOR descriptors[2];
653 IMAGE_THUNK_DATA32 original_thunks[2];
654 IMAGE_THUNK_DATA32 thunks[2];
655 struct __IMPORT_BY_NAME {
656 WORD hint;
657 char funcname[0x20];
658 } ibn;
659 char dllname[0x10];
660 };
661 #define EXIT_PROCESS (VA_START+RVA_IDATA+FIELD_OFFSET(struct Imports, thunks))
662
663 static struct _PeImage {
664 IMAGE_DOS_HEADER dos_header;
665 char __alignment1[FILE_PE_START - sizeof(IMAGE_DOS_HEADER)];
666 IMAGE_NT_HEADERS32 nt_headers;
667 IMAGE_SECTION_HEADER sections[NUM_SECTIONS];
668 char __alignment2[FILE_TEXT - FILE_PE_START - sizeof(IMAGE_NT_HEADERS32) -
669 NUM_SECTIONS * sizeof(IMAGE_SECTION_HEADER)];
670 unsigned char text_section[FILE_IDATA-FILE_TEXT];
671 struct Imports idata_section;
672 char __alignment3[FILE_TOTAL-FILE_IDATA-sizeof(struct Imports)];
673 } bin = {
674 /* dos header */
675 {IMAGE_DOS_SIGNATURE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, 0, {0}, FILE_PE_START},
676 /* alignment before PE header */
677 {0},
678 /* nt headers */
679 {IMAGE_NT_SIGNATURE,
680 /* basic headers - 3 sections, no symbols, EXE file */
681 {IMAGE_FILE_MACHINE_I386, NUM_SECTIONS, 0, 0, 0, sizeof(IMAGE_OPTIONAL_HEADER32),
682 IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE},
683 /* optional header */
684 {IMAGE_NT_OPTIONAL_HDR32_MAGIC, 4, 0, FILE_IDATA-FILE_TEXT,
685 FILE_TOTAL-FILE_IDATA + FILE_IDATA-FILE_TEXT, 0x400,
686 RVA_TEXT, RVA_TEXT, RVA_BSS, VA_START, 0x1000, 0x200, 4, 0, 1, 0, 4, 0, 0,
687 RVA_TOTAL, FILE_TEXT, 0, IMAGE_SUBSYSTEM_WINDOWS_GUI, 0,
688 0x200000, 0x1000, 0x100000, 0x1000, 0, 0x10,
689 {{0, 0},
690 {RVA_IDATA, sizeof(struct Imports)}
691 }
692 }
693 },
694 /* sections */
695 {
696 {".text", {0x100}, RVA_TEXT, FILE_IDATA-FILE_TEXT, FILE_TEXT,
697 0, 0, 0, 0, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ},
698 {".bss", {0x400}, RVA_BSS, 0, 0, 0, 0, 0, 0,
699 IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE},
700 {".idata", {sizeof(struct Imports)}, RVA_IDATA, FILE_TOTAL-FILE_IDATA, FILE_IDATA, 0,
701 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}
702 },
703 /* alignment before first section */
704 {0},
705 /* .text section */
706 {
707 0x31, 0xC0, /* xor eax, eax */
708 0xFF, 0x25, EXIT_PROCESS&0xFF, (EXIT_PROCESS>>8)&0xFF, (EXIT_PROCESS>>16)&0xFF,
709 (EXIT_PROCESS>>24)&0xFF, /* jmp ExitProcess */
710 0
711 },
712 /* .idata section */
713 {
714 {
715 {{RVA_IDATA + FIELD_OFFSET(struct Imports, original_thunks)}, 0, 0,
716 RVA_IDATA + FIELD_OFFSET(struct Imports, dllname),
717 RVA_IDATA + FIELD_OFFSET(struct Imports, thunks)
718 },
719 {{0}, 0, 0, 0, 0}
720 },
721 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
722 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
723 {0,"ExitProcess"},
724 "KERNEL32.DLL"
725 },
726 /* final alignment */
727 {0}
728 };
729 #include <poppack.h>
730
731 static void test_sip_create_indirect_data(void)
732 {
733 static GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
734 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
735 static char oid_sha1[] = szOID_OIWSEC_sha1;
736 BOOL ret;
737 SIP_SUBJECTINFO subjinfo = { 0 };
738 WCHAR temp_file[MAX_PATH];
739 HANDLE file;
740 DWORD count;
741
742 if (!CryptSIPCreateIndirectData_p)
743 {
744 skip("Missing CryptSIPCreateIndirectData\n");
745 return;
746 }
747 SetLastError(0xdeadbeef);
748 ret = CryptSIPCreateIndirectData_p(NULL, NULL, NULL);
749 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
750 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
751 SetLastError(0xdeadbeef);
752 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
753 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
754 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
755 subjinfo.cbSize = sizeof(subjinfo);
756 SetLastError(0xdeadbeef);
757 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
758 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
759 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
760 file = create_temp_file(temp_file);
761 if (file == INVALID_HANDLE_VALUE)
762 {
763 skip("couldn't create temp file\n");
764 return;
765 }
766 WriteFile(file, &bin, sizeof(bin), &count, NULL);
767 FlushFileBuffers(file);
768
769 subjinfo.hFile = file;
770 SetLastError(0xdeadbeef);
771 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
772 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
773 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
774 subjinfo.pgSubjectType = &unknown;
775 SetLastError(0xdeadbeef);
776 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
777 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
778 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
779 count = 0xdeadbeef;
780 SetLastError(0xdeadbeef);
781 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
782 todo_wine
783 ok(!ret && (GetLastError() == NTE_BAD_ALGID ||
784 GetLastError() == ERROR_INVALID_PARAMETER /* Win7 */),
785 "expected NTE_BAD_ALGID or ERROR_INVALID_PARAMETER, got %08x\n",
786 GetLastError());
787 ok(count == 0xdeadbeef, "expected count to be unmodified, got %d\n", count);
788 subjinfo.DigestAlgorithm.pszObjId = oid_sha1;
789 count = 0xdeadbeef;
790 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
791 todo_wine
792 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
793 ok(count, "expected a positive count\n");
794 if (ret)
795 {
796 SIP_INDIRECT_DATA *indirect = HeapAlloc(GetProcessHeap(), 0, count);
797
798 count = 256;
799 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, indirect);
800 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
801 /* If the count is larger than needed, it's unmodified */
802 ok(count == 256, "unexpected count %d\n", count);
803 ok(!strcmp(indirect->Data.pszObjId, SPC_PE_IMAGE_DATA_OBJID),
804 "unexpected data oid %s\n",
805 indirect->Data.pszObjId);
806 ok(!strcmp(indirect->DigestAlgorithm.pszObjId, oid_sha1),
807 "unexpected digest algorithm oid %s\n",
808 indirect->DigestAlgorithm.pszObjId);
809 ok(indirect->Digest.cbData == 20, "unexpected hash size %d\n",
810 indirect->Digest.cbData);
811 if (indirect->Digest.cbData == 20)
812 {
813 const BYTE hash[20] = {
814 0x8a,0xd5,0x45,0x53,0x3d,0x67,0xdf,0x2f,0x78,0xe0,
815 0x55,0x0a,0xe0,0xd9,0x7a,0x28,0x3e,0xbf,0x45,0x2b };
816
817 ok(!memcmp(indirect->Digest.pbData, hash, 20),
818 "unexpected value\n");
819 }
820
821 HeapFree(GetProcessHeap(), 0, indirect);
822 }
823 CloseHandle(file);
824 DeleteFileW(temp_file);
825 }
826
827 static void test_wintrust(void)
828 {
829 static GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
830 WINTRUST_DATA wtd;
831 WINTRUST_FILE_INFO file;
832 LONG r;
833 HRESULT hr;
834 WCHAR pathW[MAX_PATH];
835
836 memset(&wtd, 0, sizeof(wtd));
837 wtd.cbStruct = sizeof(wtd);
838 wtd.dwUIChoice = WTD_UI_NONE;
839 wtd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
840 wtd.dwUnionChoice = WTD_CHOICE_FILE;
841 U(wtd).pFile = &file;
842 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
843 memset(&file, 0, sizeof(file));
844 file.cbStruct = sizeof(file);
845 file.pcwszFilePath = pathW;
846 /* Test with an empty file */
847 file.hFile = create_temp_file(pathW);
848 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
849 ok(r == TRUST_E_SUBJECT_FORM_UNKNOWN,
850 "expected TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n", r);
851 CloseHandle(file.hFile);
852 DeleteFileW(pathW);
853 file.hFile = NULL;
854 /* Test with a known file path, which we expect not have a signature */
855 getNotepadPath(pathW, MAX_PATH);
856 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
857 ok(r == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
858 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", r);
859 wtd.dwStateAction = WTD_STATEACTION_CLOSE;
860 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
861 ok(r == S_OK, "WinVerifyTrust failed: %08x\n", r);
862 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
863 hr = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
864 ok(hr == TRUST_E_NOSIGNATURE || hr == CRYPT_E_FILE_ERROR,
865 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", hr);
866 wtd.dwStateAction = WTD_STATEACTION_CLOSE;
867 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
868 ok(r == S_OK, "WinVerifyTrust failed: %08x\n", r);
869 }
870
871 static void test_get_known_usages(void)
872 {
873 BOOL ret;
874 PCCRYPT_OID_INFO *usages;
875
876 if (!pWTHelperGetKnownUsages)
877 {
878 skip("missing WTHelperGetKnownUsages\n");
879 return;
880 }
881 SetLastError(0xdeadbeef);
882 ret = pWTHelperGetKnownUsages(0, NULL);
883 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
884 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
885 SetLastError(0xdeadbeef);
886 ret = pWTHelperGetKnownUsages(1, NULL);
887 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
888 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
889 SetLastError(0xdeadbeef);
890 ret = pWTHelperGetKnownUsages(0, &usages);
891 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
892 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
893 /* A value of 1 for the first parameter seems to imply the value is
894 * allocated
895 */
896 SetLastError(0xdeadbeef);
897 usages = NULL;
898 ret = pWTHelperGetKnownUsages(1, &usages);
899 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
900 ok(usages != NULL, "expected a pointer\n");
901 if (ret && usages)
902 {
903 PCCRYPT_OID_INFO *ptr;
904
905 /* The returned usages are an array of PCCRYPT_OID_INFOs, terminated with a
906 * NULL pointer.
907 */
908 for (ptr = usages; *ptr; ptr++)
909 {
910 ok((*ptr)->cbSize == sizeof(CRYPT_OID_INFO) ||
911 (*ptr)->cbSize == (sizeof(CRYPT_OID_INFO) + 2 * sizeof(LPCWSTR)), /* Vista */
912 "unexpected size %d\n", (*ptr)->cbSize);
913 /* Each returned usage is in the CRYPT_ENHKEY_USAGE_OID_GROUP_ID group */
914 ok((*ptr)->dwGroupId == CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
915 "expected group CRYPT_ENHKEY_USAGE_OID_GROUP_ID, got %d\n",
916 (*ptr)->dwGroupId);
917 }
918 }
919 /* A value of 2 for the second parameter seems to imply the value is freed
920 */
921 SetLastError(0xdeadbeef);
922 ret = pWTHelperGetKnownUsages(2, &usages);
923 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
924 ok(usages == NULL, "expected pointer to be cleared\n");
925 SetLastError(0xdeadbeef);
926 usages = NULL;
927 ret = pWTHelperGetKnownUsages(2, &usages);
928 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
929 SetLastError(0xdeadbeef);
930 ret = pWTHelperGetKnownUsages(2, NULL);
931 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
932 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
933 }
934
935 START_TEST(softpub)
936 {
937 InitFunctionPtrs();
938 test_provider_funcs();
939 test_sip_create_indirect_data();
940 test_wintrust();
941 test_get_known_usages();
942 }