436de472c12c2e499ec3897af912d9823604a8b6
[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 BOOL b;
548
549 if (!CertFreeCertificateChain_p)
550 {
551 win_skip("CertFreeCertificateChain not found\n");
552 return;
553 }
554
555 data.padwTrustStepErrors =
556 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
557 if (!data.padwTrustStepErrors)
558 {
559 skip("pfnAlloc failed\n");
560 return;
561 }
562 ret = funcs->pfnCertificateTrust(&data);
563 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
564 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
565 TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
566 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
567 b = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
568 if (b)
569 {
570 PCCERT_CONTEXT cert;
571
572 /* An empty signer "succeeds," even though there's no cert */
573 ret = funcs->pfnCertificateTrust(&data);
574 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
575 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
576 sizeof(selfSignedCert));
577 if (cert)
578 {
579 WINTRUST_DATA wintrust_data = { 0 };
580
581 b = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
582 ok(b == TRUE, "Expected TRUE, got %d\n", b);
583
584 /* If pWintrustData isn't set, crashes attempting to access
585 * pWintrustData->fdwRevocationChecks
586 */
587 data.pWintrustData = &wintrust_data;
588 /* If psPfns isn't set, crashes attempting to access
589 * psPfns->pfnCertCheckPolicy
590 */
591 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
592 ret = funcs->pfnCertificateTrust(&data);
593 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
594 ok(data.csSigners == 1, "Unexpected number of signers %d\n",
595 data.csSigners);
596 ok(data.pasSigners[0].pChainContext != NULL,
597 "Expected a certificate chain\n");
598 ok(data.pasSigners[0].csCertChain == 1,
599 "Unexpected number of chain elements %d\n",
600 data.pasSigners[0].csCertChain);
601 /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
602 * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
603 */
604 ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
605 "Didn't expect cert to be trusted\n");
606 ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
607 "Expected cert to be self-signed\n");
608 ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
609 (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
610 "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
611 data.pasSigners[0].pasCertChain[0].dwConfidence);
612 CertFreeCertificateContext(
613 data.pasSigners[0].pasCertChain[0].pCert);
614 CertFreeCertificateChain_p(data.pasSigners[0].pChainContext);
615 CertFreeCertificateContext(cert);
616 }
617 }
618 funcs->pfnFree(data.padwTrustStepErrors);
619 }
620
621 static void test_provider_funcs(void)
622 {
623 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
624 SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
625 BOOL ret;
626
627 ret = WintrustLoadFunctionPointers(&generic_verify_v2,
628 (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
629 if (!ret)
630 skip("WintrustLoadFunctionPointers failed\n");
631 else
632 {
633 test_utils(&funcs);
634 testInitialize(&funcs, &generic_verify_v2);
635 testObjTrust(&funcs, &generic_verify_v2);
636 testCertTrust(&funcs, &generic_verify_v2);
637 }
638 }
639
640 /* minimal PE file image */
641 #define VA_START 0x400000
642 #define FILE_PE_START 0x50
643 #define NUM_SECTIONS 3
644 #define FILE_TEXT 0x200
645 #define RVA_TEXT 0x1000
646 #define RVA_BSS 0x2000
647 #define FILE_IDATA 0x400
648 #define RVA_IDATA 0x3000
649 #define FILE_TOTAL 0x600
650 #define RVA_TOTAL 0x4000
651 #include <pshpack1.h>
652 struct Imports {
653 IMAGE_IMPORT_DESCRIPTOR descriptors[2];
654 IMAGE_THUNK_DATA32 original_thunks[2];
655 IMAGE_THUNK_DATA32 thunks[2];
656 struct __IMPORT_BY_NAME {
657 WORD hint;
658 char funcname[0x20];
659 } ibn;
660 char dllname[0x10];
661 };
662 #define EXIT_PROCESS (VA_START+RVA_IDATA+FIELD_OFFSET(struct Imports, thunks))
663
664 static struct _PeImage {
665 IMAGE_DOS_HEADER dos_header;
666 char __alignment1[FILE_PE_START - sizeof(IMAGE_DOS_HEADER)];
667 IMAGE_NT_HEADERS32 nt_headers;
668 IMAGE_SECTION_HEADER sections[NUM_SECTIONS];
669 char __alignment2[FILE_TEXT - FILE_PE_START - sizeof(IMAGE_NT_HEADERS32) -
670 NUM_SECTIONS * sizeof(IMAGE_SECTION_HEADER)];
671 unsigned char text_section[FILE_IDATA-FILE_TEXT];
672 struct Imports idata_section;
673 char __alignment3[FILE_TOTAL-FILE_IDATA-sizeof(struct Imports)];
674 } bin = {
675 /* dos header */
676 {IMAGE_DOS_SIGNATURE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, 0, {0}, FILE_PE_START},
677 /* alignment before PE header */
678 {0},
679 /* nt headers */
680 {IMAGE_NT_SIGNATURE,
681 /* basic headers - 3 sections, no symbols, EXE file */
682 {IMAGE_FILE_MACHINE_I386, NUM_SECTIONS, 0, 0, 0, sizeof(IMAGE_OPTIONAL_HEADER32),
683 IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE},
684 /* optional header */
685 {IMAGE_NT_OPTIONAL_HDR32_MAGIC, 4, 0, FILE_IDATA-FILE_TEXT,
686 FILE_TOTAL-FILE_IDATA + FILE_IDATA-FILE_TEXT, 0x400,
687 RVA_TEXT, RVA_TEXT, RVA_BSS, VA_START, 0x1000, 0x200, 4, 0, 1, 0, 4, 0, 0,
688 RVA_TOTAL, FILE_TEXT, 0, IMAGE_SUBSYSTEM_WINDOWS_GUI, 0,
689 0x200000, 0x1000, 0x100000, 0x1000, 0, 0x10,
690 {{0, 0},
691 {RVA_IDATA, sizeof(struct Imports)}
692 }
693 }
694 },
695 /* sections */
696 {
697 {".text", {0x100}, RVA_TEXT, FILE_IDATA-FILE_TEXT, FILE_TEXT,
698 0, 0, 0, 0, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ},
699 {".bss", {0x400}, RVA_BSS, 0, 0, 0, 0, 0, 0,
700 IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE},
701 {".idata", {sizeof(struct Imports)}, RVA_IDATA, FILE_TOTAL-FILE_IDATA, FILE_IDATA, 0,
702 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}
703 },
704 /* alignment before first section */
705 {0},
706 /* .text section */
707 {
708 0x31, 0xC0, /* xor eax, eax */
709 0xFF, 0x25, EXIT_PROCESS&0xFF, (EXIT_PROCESS>>8)&0xFF, (EXIT_PROCESS>>16)&0xFF,
710 (EXIT_PROCESS>>24)&0xFF, /* jmp ExitProcess */
711 0
712 },
713 /* .idata section */
714 {
715 {
716 {{RVA_IDATA + FIELD_OFFSET(struct Imports, original_thunks)}, 0, 0,
717 RVA_IDATA + FIELD_OFFSET(struct Imports, dllname),
718 RVA_IDATA + FIELD_OFFSET(struct Imports, thunks)
719 },
720 {{0}, 0, 0, 0, 0}
721 },
722 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
723 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
724 {0,"ExitProcess"},
725 "KERNEL32.DLL"
726 },
727 /* final alignment */
728 {0}
729 };
730 #include <poppack.h>
731
732 static void test_sip_create_indirect_data(void)
733 {
734 static GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
735 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
736 static char oid_sha1[] = szOID_OIWSEC_sha1;
737 BOOL ret;
738 SIP_SUBJECTINFO subjinfo = { 0 };
739 WCHAR temp_file[MAX_PATH];
740 HANDLE file;
741 DWORD count;
742
743 if (!CryptSIPCreateIndirectData_p)
744 {
745 skip("Missing CryptSIPCreateIndirectData\n");
746 return;
747 }
748 SetLastError(0xdeadbeef);
749 ret = CryptSIPCreateIndirectData_p(NULL, NULL, NULL);
750 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
751 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
752 SetLastError(0xdeadbeef);
753 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
754 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
755 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
756 subjinfo.cbSize = sizeof(subjinfo);
757 SetLastError(0xdeadbeef);
758 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
759 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
760 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
761 file = create_temp_file(temp_file);
762 if (file == INVALID_HANDLE_VALUE)
763 {
764 skip("couldn't create temp file\n");
765 return;
766 }
767 WriteFile(file, &bin, sizeof(bin), &count, NULL);
768 FlushFileBuffers(file);
769
770 subjinfo.hFile = file;
771 SetLastError(0xdeadbeef);
772 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
773 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
774 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
775 subjinfo.pgSubjectType = &unknown;
776 SetLastError(0xdeadbeef);
777 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
778 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
779 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
780 count = 0xdeadbeef;
781 SetLastError(0xdeadbeef);
782 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
783 todo_wine
784 ok(!ret && (GetLastError() == NTE_BAD_ALGID ||
785 GetLastError() == ERROR_INVALID_PARAMETER /* Win7 */),
786 "expected NTE_BAD_ALGID or ERROR_INVALID_PARAMETER, got %08x\n",
787 GetLastError());
788 ok(count == 0xdeadbeef, "expected count to be unmodified, got %d\n", count);
789 subjinfo.DigestAlgorithm.pszObjId = oid_sha1;
790 count = 0xdeadbeef;
791 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
792 todo_wine
793 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
794 ok(count, "expected a positive count\n");
795 if (ret)
796 {
797 SIP_INDIRECT_DATA *indirect = HeapAlloc(GetProcessHeap(), 0, count);
798
799 count = 256;
800 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, indirect);
801 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
802 /* If the count is larger than needed, it's unmodified */
803 ok(count == 256, "unexpected count %d\n", count);
804 ok(!strcmp(indirect->Data.pszObjId, SPC_PE_IMAGE_DATA_OBJID),
805 "unexpected data oid %s\n",
806 indirect->Data.pszObjId);
807 ok(!strcmp(indirect->DigestAlgorithm.pszObjId, oid_sha1),
808 "unexpected digest algorithm oid %s\n",
809 indirect->DigestAlgorithm.pszObjId);
810 ok(indirect->Digest.cbData == 20, "unexpected hash size %d\n",
811 indirect->Digest.cbData);
812 if (indirect->Digest.cbData == 20)
813 {
814 const BYTE hash[20] = {
815 0x8a,0xd5,0x45,0x53,0x3d,0x67,0xdf,0x2f,0x78,0xe0,
816 0x55,0x0a,0xe0,0xd9,0x7a,0x28,0x3e,0xbf,0x45,0x2b };
817
818 ok(!memcmp(indirect->Digest.pbData, hash, 20),
819 "unexpected value\n");
820 }
821
822 HeapFree(GetProcessHeap(), 0, indirect);
823 }
824 CloseHandle(file);
825 DeleteFileW(temp_file);
826 }
827
828 static void test_wintrust(void)
829 {
830 static GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
831 WINTRUST_DATA wtd;
832 WINTRUST_FILE_INFO file;
833 LONG r;
834 HRESULT hr;
835 WCHAR pathW[MAX_PATH];
836
837 memset(&wtd, 0, sizeof(wtd));
838 wtd.cbStruct = sizeof(wtd);
839 wtd.dwUIChoice = WTD_UI_NONE;
840 wtd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
841 wtd.dwUnionChoice = WTD_CHOICE_FILE;
842 U(wtd).pFile = &file;
843 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
844 memset(&file, 0, sizeof(file));
845 file.cbStruct = sizeof(file);
846 file.pcwszFilePath = pathW;
847 /* Test with an empty file */
848 file.hFile = create_temp_file(pathW);
849 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
850 ok(r == TRUST_E_SUBJECT_FORM_UNKNOWN,
851 "expected TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n", r);
852 CloseHandle(file.hFile);
853 DeleteFileW(pathW);
854 file.hFile = NULL;
855 /* Test with a known file path, which we expect not have a signature */
856 getNotepadPath(pathW, MAX_PATH);
857 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
858 ok(r == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
859 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", r);
860 wtd.dwStateAction = WTD_STATEACTION_CLOSE;
861 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
862 ok(r == S_OK, "WinVerifyTrust failed: %08x\n", r);
863 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
864 hr = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
865 ok(hr == TRUST_E_NOSIGNATURE || hr == CRYPT_E_FILE_ERROR,
866 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", hr);
867 wtd.dwStateAction = WTD_STATEACTION_CLOSE;
868 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
869 ok(r == S_OK, "WinVerifyTrust failed: %08x\n", r);
870 }
871
872 static void test_get_known_usages(void)
873 {
874 BOOL ret;
875 PCCRYPT_OID_INFO *usages;
876
877 if (!pWTHelperGetKnownUsages)
878 {
879 skip("missing WTHelperGetKnownUsages\n");
880 return;
881 }
882 SetLastError(0xdeadbeef);
883 ret = pWTHelperGetKnownUsages(0, NULL);
884 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
885 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
886 SetLastError(0xdeadbeef);
887 ret = pWTHelperGetKnownUsages(1, NULL);
888 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
889 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
890 SetLastError(0xdeadbeef);
891 ret = pWTHelperGetKnownUsages(0, &usages);
892 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
893 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
894 /* A value of 1 for the first parameter seems to imply the value is
895 * allocated
896 */
897 SetLastError(0xdeadbeef);
898 usages = NULL;
899 ret = pWTHelperGetKnownUsages(1, &usages);
900 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
901 ok(usages != NULL, "expected a pointer\n");
902 if (ret && usages)
903 {
904 PCCRYPT_OID_INFO *ptr;
905
906 /* The returned usages are an array of PCCRYPT_OID_INFOs, terminated with a
907 * NULL pointer.
908 */
909 for (ptr = usages; *ptr; ptr++)
910 {
911 ok((*ptr)->cbSize == sizeof(CRYPT_OID_INFO) ||
912 (*ptr)->cbSize == (sizeof(CRYPT_OID_INFO) + 2 * sizeof(LPCWSTR)), /* Vista */
913 "unexpected size %d\n", (*ptr)->cbSize);
914 /* Each returned usage is in the CRYPT_ENHKEY_USAGE_OID_GROUP_ID group */
915 ok((*ptr)->dwGroupId == CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
916 "expected group CRYPT_ENHKEY_USAGE_OID_GROUP_ID, got %d\n",
917 (*ptr)->dwGroupId);
918 }
919 }
920 /* A value of 2 for the second parameter seems to imply the value is freed
921 */
922 SetLastError(0xdeadbeef);
923 ret = pWTHelperGetKnownUsages(2, &usages);
924 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
925 ok(usages == NULL, "expected pointer to be cleared\n");
926 SetLastError(0xdeadbeef);
927 usages = NULL;
928 ret = pWTHelperGetKnownUsages(2, &usages);
929 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
930 SetLastError(0xdeadbeef);
931 ret = pWTHelperGetKnownUsages(2, NULL);
932 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
933 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
934 }
935
936 START_TEST(softpub)
937 {
938 InitFunctionPtrs();
939 test_provider_funcs();
940 test_sip_create_indirect_data();
941 test_wintrust();
942 test_get_known_usages();
943 }