crypt32: Add parameter checking to CryptSIPCreateIndirectData.
[wine/multimedia.git] / dlls / wintrust / tests / softpub.c
blobb431ff84796984cf093ba84dbb9a4b928e97b568
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
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winerror.h>
27 #include <wintrust.h>
28 #include <softpub.h>
29 #include <mssip.h>
30 #include <winuser.h>
31 #include "winnls.h"
33 #include "wine/test.h"
35 /* Just in case we're being built with borked headers, redefine function
36 * pointers to have the correct calling convention.
38 typedef void *(WINAPI *SAFE_MEM_ALLOC)(DWORD);
39 typedef void (WINAPI *SAFE_MEM_FREE)(void *);
40 typedef BOOL (WINAPI *SAFE_ADD_STORE)(CRYPT_PROVIDER_DATA *,
41 HCERTSTORE);
42 typedef BOOL (WINAPI *SAFE_ADD_SGNR)(CRYPT_PROVIDER_DATA *,
43 BOOL, DWORD, struct _CRYPT_PROVIDER_SGNR *);
44 typedef BOOL (WINAPI *SAFE_ADD_CERT)(CRYPT_PROVIDER_DATA *,
45 DWORD, BOOL, DWORD, PCCERT_CONTEXT);
46 typedef BOOL (WINAPI *SAFE_ADD_PRIVDATA)(CRYPT_PROVIDER_DATA *,
47 CRYPT_PROVIDER_PRIVDATA *);
48 typedef HRESULT (WINAPI *SAFE_PROVIDER_INIT_CALL)(CRYPT_PROVIDER_DATA *);
49 typedef HRESULT (WINAPI *SAFE_PROVIDER_OBJTRUST_CALL)(CRYPT_PROVIDER_DATA *);
50 typedef HRESULT (WINAPI *SAFE_PROVIDER_SIGTRUST_CALL)(CRYPT_PROVIDER_DATA *);
51 typedef HRESULT (WINAPI *SAFE_PROVIDER_CERTTRUST_CALL)(CRYPT_PROVIDER_DATA *);
52 typedef HRESULT (WINAPI *SAFE_PROVIDER_FINALPOLICY_CALL)(CRYPT_PROVIDER_DATA *);
53 typedef HRESULT (WINAPI *SAFE_PROVIDER_TESTFINALPOLICY_CALL)(
54 CRYPT_PROVIDER_DATA *);
55 typedef HRESULT (WINAPI *SAFE_PROVIDER_CLEANUP_CALL)(CRYPT_PROVIDER_DATA *);
56 typedef BOOL (WINAPI *SAFE_PROVIDER_CERTCHKPOLICY_CALL)(
57 CRYPT_PROVIDER_DATA *, DWORD, BOOL, DWORD);
59 typedef struct _SAFE_PROVIDER_FUNCTIONS
61 DWORD cbStruct;
62 SAFE_MEM_ALLOC pfnAlloc;
63 SAFE_MEM_FREE pfnFree;
64 SAFE_ADD_STORE pfnAddStore2Chain;
65 SAFE_ADD_SGNR pfnAddSgnr2Chain;
66 SAFE_ADD_CERT pfnAddCert2Chain;
67 SAFE_ADD_PRIVDATA pfnAddPrivData2Chain;
68 SAFE_PROVIDER_INIT_CALL pfnInitialize;
69 SAFE_PROVIDER_OBJTRUST_CALL pfnObjectTrust;
70 SAFE_PROVIDER_SIGTRUST_CALL pfnSignatureTrust;
71 SAFE_PROVIDER_CERTTRUST_CALL pfnCertificateTrust;
72 SAFE_PROVIDER_FINALPOLICY_CALL pfnFinalPolicy;
73 SAFE_PROVIDER_CERTCHKPOLICY_CALL pfnCertCheckPolicy;
74 SAFE_PROVIDER_TESTFINALPOLICY_CALL pfnTestFinalPolicy;
75 struct _CRYPT_PROVUI_FUNCS *psUIpfns;
76 SAFE_PROVIDER_CLEANUP_CALL pfnCleanupPolicy;
77 } SAFE_PROVIDER_FUNCTIONS;
79 static BOOL (WINAPI * pWTHelperGetKnownUsages)(DWORD action, PCCRYPT_OID_INFO **usages);
80 static BOOL (WINAPI * CryptSIPCreateIndirectData_p)(SIP_SUBJECTINFO *, DWORD *, SIP_INDIRECT_DATA *);
82 static void InitFunctionPtrs(void)
84 HMODULE hWintrust = GetModuleHandleA("wintrust.dll");
85 HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
87 #define WINTRUST_GET_PROC(func) \
88 p ## func = (void*)GetProcAddress(hWintrust, #func); \
89 if(!p ## func) { \
90 trace("GetProcAddress(%s) failed\n", #func); \
93 WINTRUST_GET_PROC(WTHelperGetKnownUsages)
95 #undef WINTRUST_GET_PROC
97 #define CRYPT32_GET_PROC(func) \
98 func ## _p = (void*)GetProcAddress(hCrypt32, #func); \
99 if(!func ## _p) { \
100 trace("GetProcAddress(%s) failed\n", #func); \
103 CRYPT32_GET_PROC(CryptSIPCreateIndirectData)
105 #undef CRYPT32_GET_PROC
108 static const BYTE v1CertWithPubKey[] = {
109 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
110 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
111 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
112 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
113 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
114 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
115 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
116 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
117 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
118 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
119 0x01,0x01 };
121 static void test_utils(SAFE_PROVIDER_FUNCTIONS *funcs)
123 CRYPT_PROVIDER_DATA data = { 0 };
124 HCERTSTORE store;
125 CRYPT_PROVIDER_SGNR sgnr = { 0 };
126 BOOL ret;
128 /* Crash
129 ret = funcs->pfnAddStore2Chain(NULL, NULL);
130 ret = funcs->pfnAddStore2Chain(&data, NULL);
132 store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0,
133 CERT_STORE_CREATE_NEW_FLAG, NULL);
134 if (store)
136 ret = funcs->pfnAddStore2Chain(&data, store);
137 ok(ret, "pfnAddStore2Chain failed: %08x\n", GetLastError());
138 ok(data.chStores == 1, "Expected 1 store, got %d\n", data.chStores);
139 ok(data.pahStores != NULL, "Expected pahStores to be allocated\n");
140 if (data.pahStores)
142 ok(data.pahStores[0] == store, "Unexpected store\n");
143 CertCloseStore(data.pahStores[0], 0);
144 funcs->pfnFree(data.pahStores);
145 data.pahStores = NULL;
146 data.chStores = 0;
147 CertCloseStore(store, 0);
148 store = NULL;
151 else
152 skip("CertOpenStore failed: %08x\n", GetLastError());
154 /* Crash
155 ret = funcs->pfnAddSgnr2Chain(NULL, FALSE, 0, NULL);
156 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, NULL);
158 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
159 ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
160 ok(data.csSigners == 1, "Expected 1 signer, got %d\n", data.csSigners);
161 ok(data.pasSigners != NULL, "Expected pasSigners to be allocated\n");
162 if (data.pasSigners)
164 PCCERT_CONTEXT cert;
166 ok(!memcmp(&data.pasSigners[0], &sgnr, sizeof(sgnr)),
167 "Unexpected data in signer\n");
168 /* Adds into the location specified by the index */
169 sgnr.cbStruct = sizeof(CRYPT_PROVIDER_SGNR);
170 sgnr.sftVerifyAsOf.dwLowDateTime = 0xdeadbeef;
171 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 1, &sgnr);
172 ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
173 ok(data.csSigners == 2, "Expected 2 signers, got %d\n", data.csSigners);
174 ok(!memcmp(&data.pasSigners[1], &sgnr, sizeof(sgnr)),
175 "Unexpected data in signer\n");
176 /* This also adds, but the data aren't copied */
177 sgnr.cbStruct = sizeof(DWORD);
178 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
179 ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
180 ok(data.csSigners == 3, "Expected 3 signers, got %d\n", data.csSigners);
181 ok(data.pasSigners[0].cbStruct == 0, "Unexpected data size %d\n",
182 data.pasSigners[0].cbStruct);
183 ok(data.pasSigners[0].sftVerifyAsOf.dwLowDateTime == 0,
184 "Unexpected verify time %d\n",
185 data.pasSigners[0].sftVerifyAsOf.dwLowDateTime);
186 /* But too large a thing isn't added */
187 sgnr.cbStruct = sizeof(sgnr) + sizeof(DWORD);
188 SetLastError(0xdeadbeef);
189 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
190 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
191 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
193 /* Crash
194 ret = funcs->pfnAddCert2Chain(NULL, 0, FALSE, 0, NULL);
195 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, NULL);
197 cert = CertCreateCertificateContext(X509_ASN_ENCODING, v1CertWithPubKey,
198 sizeof(v1CertWithPubKey));
199 if (cert)
201 /* Notes on behavior that are hard to test:
202 * 1. If pasSigners is invalid, pfnAddCert2Chain crashes
203 * 2. An invalid signer index isn't checked.
205 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
206 ok(ret, "pfnAddCert2Chain failed: %08x\n", GetLastError());
207 ok(data.pasSigners[0].csCertChain == 1, "Expected 1 cert, got %d\n",
208 data.pasSigners[0].csCertChain);
209 ok(data.pasSigners[0].pasCertChain != NULL,
210 "Expected pasCertChain to be allocated\n");
211 if (data.pasSigners[0].pasCertChain)
213 ok(data.pasSigners[0].pasCertChain[0].pCert == cert,
214 "Unexpected cert\n");
215 CertFreeCertificateContext(
216 data.pasSigners[0].pasCertChain[0].pCert);
218 CertFreeCertificateContext(cert);
220 else
221 skip("CertCreateCertificateContext failed: %08x\n", GetLastError());
225 static void testInitialize(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
227 HRESULT ret;
228 CRYPT_PROVIDER_DATA data = { 0 };
229 WINTRUST_DATA wintrust_data = { 0 };
231 if (!funcs->pfnInitialize)
233 skip("missing pfnInitialize\n");
234 return;
237 /* Crashes
238 ret = funcs->pfnInitialize(NULL);
240 memset(&data, 0, sizeof(data));
241 ret = funcs->pfnInitialize(&data);
242 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
243 data.padwTrustStepErrors =
244 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
245 /* Without wintrust data set, crashes when padwTrustStepErrors is set */
246 data.pWintrustData = &wintrust_data;
247 if (data.padwTrustStepErrors)
249 /* Apparently, cdwTrustStepErrors does not need to be set. */
250 ret = funcs->pfnInitialize(&data);
251 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
252 data.cdwTrustStepErrors = 1;
253 ret = funcs->pfnInitialize(&data);
254 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
255 memset(data.padwTrustStepErrors, 0xba,
256 TRUSTERROR_MAX_STEPS * sizeof(DWORD));
257 ret = funcs->pfnInitialize(&data);
258 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
259 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] = 0;
260 ret = funcs->pfnInitialize(&data);
261 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
262 funcs->pfnFree(data.padwTrustStepErrors);
266 static void getNotepadPath(WCHAR *notepadPathW, DWORD size)
268 static const CHAR notepad[] = "\\notepad.exe";
269 CHAR notepadPath[MAX_PATH];
271 /* Workaround missing W-functions for win9x */
272 GetWindowsDirectoryA(notepadPath, MAX_PATH);
273 lstrcatA(notepadPath, notepad);
274 MultiByteToWideChar(0, 0, notepadPath, -1, notepadPathW, size);
277 static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
279 HRESULT ret;
280 CRYPT_PROVIDER_DATA data = { 0 };
281 WINTRUST_DATA wintrust_data = { 0 };
282 WINTRUST_CERT_INFO certInfo = { sizeof(WINTRUST_CERT_INFO), 0 };
283 WINTRUST_FILE_INFO fileInfo = { sizeof(WINTRUST_FILE_INFO), 0 };
285 if (!funcs->pfnObjectTrust)
287 skip("missing pfnObjectTrust\n");
288 return;
291 /* Crashes
292 ret = funcs->pfnObjectTrust(NULL);
294 data.pWintrustData = &wintrust_data;
295 data.padwTrustStepErrors =
296 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
297 if (data.padwTrustStepErrors)
299 WCHAR notepadPathW[MAX_PATH];
300 PROVDATA_SIP provDataSIP = { 0 };
301 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
302 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
303 static GUID bogusGuid = { 0xdeadbeef, 0xbaad, 0xf00d, { 0x00,0x00,0x00,
304 0x00,0x00,0x00,0x00,0x00 } };
306 ret = funcs->pfnObjectTrust(&data);
307 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
308 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
309 ERROR_INVALID_PARAMETER,
310 "Expected ERROR_INVALID_PARAMETER, got %08x\n",
311 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
312 U(wintrust_data).pCert = &certInfo;
313 wintrust_data.dwUnionChoice = WTD_CHOICE_CERT;
314 ret = funcs->pfnObjectTrust(&data);
315 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
316 certInfo.psCertContext = (PCERT_CONTEXT)CertCreateCertificateContext(
317 X509_ASN_ENCODING, v1CertWithPubKey, sizeof(v1CertWithPubKey));
318 ret = funcs->pfnObjectTrust(&data);
319 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
320 CertFreeCertificateContext(certInfo.psCertContext);
321 certInfo.psCertContext = NULL;
322 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
323 U(wintrust_data).pFile = NULL;
324 ret = funcs->pfnObjectTrust(&data);
325 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
326 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
327 ERROR_INVALID_PARAMETER,
328 "Expected ERROR_INVALID_PARAMETER, got %08x\n",
329 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
330 U(wintrust_data).pFile = &fileInfo;
331 /* Crashes
332 ret = funcs->pfnObjectTrust(&data);
334 getNotepadPath(notepadPathW, MAX_PATH);
335 fileInfo.pcwszFilePath = notepadPathW;
336 /* pfnObjectTrust now crashes unless both pPDSip and psPfns are set */
337 U(data).pPDSip = &provDataSIP;
338 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
339 ret = funcs->pfnObjectTrust(&data);
340 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
341 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
342 TRUST_E_NOSIGNATURE ||
343 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
344 TRUST_E_SUBJECT_FORM_UNKNOWN,
345 "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
346 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
347 if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
348 TRUST_E_NOSIGNATURE)
350 ok(!memcmp(&provDataSIP.gSubject, &unknown, sizeof(unknown)),
351 "Unexpected subject GUID\n");
352 ok(provDataSIP.pSip != NULL, "Expected a SIP\n");
353 ok(provDataSIP.psSipSubjectInfo != NULL,
354 "Expected a subject info\n");
356 /* Specifying the GUID results in that GUID being the subject GUID */
357 fileInfo.pgKnownSubject = &bogusGuid;
358 ret = funcs->pfnObjectTrust(&data);
359 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
360 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
361 TRUST_E_NOSIGNATURE ||
362 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
363 TRUST_E_SUBJECT_FORM_UNKNOWN ||
364 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
365 TRUST_E_PROVIDER_UNKNOWN,
366 "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN or TRUST_E_PROVIDER_UNKNOWN, got %08x\n",
367 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
368 if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
369 TRUST_E_NOSIGNATURE)
371 ok(!memcmp(&provDataSIP.gSubject, &bogusGuid, sizeof(bogusGuid)),
372 "unexpected subject GUID\n");
374 /* Specifying a bogus GUID pointer crashes */
375 if (0)
377 fileInfo.pgKnownSubject = (GUID *)0xdeadbeef;
378 ret = funcs->pfnObjectTrust(&data);
380 funcs->pfnFree(data.padwTrustStepErrors);
384 static const BYTE selfSignedCert[] = {
385 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
386 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
387 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
388 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
389 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
390 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
391 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
392 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
393 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
394 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
395 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
396 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
397 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
398 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
399 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
400 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
401 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
402 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
403 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
404 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
405 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
406 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
407 0xa8, 0x76, 0x57, 0x92, 0x36 };
409 static void testCertTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
411 CRYPT_PROVIDER_DATA data = { 0 };
412 CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
413 HRESULT ret;
415 data.padwTrustStepErrors =
416 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
417 if (!data.padwTrustStepErrors)
419 skip("pfnAlloc failed\n");
420 return;
422 ret = funcs->pfnCertificateTrust(&data);
423 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
424 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
425 TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
426 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
427 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
428 if (ret)
430 PCCERT_CONTEXT cert;
432 /* An empty signer "succeeds," even though there's no cert */
433 ret = funcs->pfnCertificateTrust(&data);
434 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
435 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
436 sizeof(selfSignedCert));
437 if (cert)
439 WINTRUST_DATA wintrust_data = { 0 };
441 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
442 /* If pWintrustData isn't set, crashes attempting to access
443 * pWintrustData->fdwRevocationChecks
445 data.pWintrustData = &wintrust_data;
446 /* If psPfns isn't set, crashes attempting to access
447 * psPfns->pfnCertCheckPolicy
449 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
450 ret = funcs->pfnCertificateTrust(&data);
451 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
452 ok(data.csSigners == 1, "Unexpected number of signers %d\n",
453 data.csSigners);
454 ok(data.pasSigners[0].pChainContext != NULL,
455 "Expected a certificate chain\n");
456 ok(data.pasSigners[0].csCertChain == 1,
457 "Unexpected number of chain elements %d\n",
458 data.pasSigners[0].csCertChain);
459 /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
460 * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
462 ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
463 "Didn't expect cert to be trusted\n");
464 ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
465 "Expected cert to be self-signed\n");
466 ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
467 (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
468 "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
469 data.pasSigners[0].pasCertChain[0].dwConfidence);
470 CertFreeCertificateContext(
471 data.pasSigners[0].pasCertChain[0].pCert);
472 CertFreeCertificateChain(data.pasSigners[0].pChainContext);
473 CertFreeCertificateContext(cert);
478 static void test_provider_funcs(void)
480 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
481 SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
482 BOOL ret;
484 ret = WintrustLoadFunctionPointers(&generic_verify_v2,
485 (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
486 if (!ret)
487 skip("WintrustLoadFunctionPointers failed\n");
488 else
490 test_utils(&funcs);
491 testInitialize(&funcs, &generic_verify_v2);
492 testObjTrust(&funcs, &generic_verify_v2);
493 testCertTrust(&funcs, &generic_verify_v2);
497 /* minimal PE file image */
498 #define VA_START 0x400000
499 #define FILE_PE_START 0x50
500 #define NUM_SECTIONS 3
501 #define FILE_TEXT 0x200
502 #define RVA_TEXT 0x1000
503 #define RVA_BSS 0x2000
504 #define FILE_IDATA 0x400
505 #define RVA_IDATA 0x3000
506 #define FILE_TOTAL 0x600
507 #define RVA_TOTAL 0x4000
508 #include <pshpack1.h>
509 struct Imports {
510 IMAGE_IMPORT_DESCRIPTOR descriptors[2];
511 IMAGE_THUNK_DATA32 original_thunks[2];
512 IMAGE_THUNK_DATA32 thunks[2];
513 struct __IMPORT_BY_NAME {
514 WORD hint;
515 char funcname[0x20];
516 } ibn;
517 char dllname[0x10];
519 #define EXIT_PROCESS (VA_START+RVA_IDATA+FIELD_OFFSET(struct Imports, thunks[0]))
521 static struct _PeImage {
522 IMAGE_DOS_HEADER dos_header;
523 char __alignment1[FILE_PE_START - sizeof(IMAGE_DOS_HEADER)];
524 IMAGE_NT_HEADERS32 nt_headers;
525 IMAGE_SECTION_HEADER sections[NUM_SECTIONS];
526 char __alignment2[FILE_TEXT - FILE_PE_START - sizeof(IMAGE_NT_HEADERS32) -
527 NUM_SECTIONS * sizeof(IMAGE_SECTION_HEADER)];
528 unsigned char text_section[FILE_IDATA-FILE_TEXT];
529 struct Imports idata_section;
530 char __alignment3[FILE_TOTAL-FILE_IDATA-sizeof(struct Imports)];
531 } bin = {
532 /* dos header */
533 {IMAGE_DOS_SIGNATURE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {}, 0, 0, {}, FILE_PE_START},
534 /* alignment before PE header */
536 /* nt headers */
537 {IMAGE_NT_SIGNATURE,
538 /* basic headers - 3 sections, no symbols, EXE file */
539 {IMAGE_FILE_MACHINE_I386, NUM_SECTIONS, 0, 0, 0, sizeof(IMAGE_OPTIONAL_HEADER32),
540 IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE},
541 /* optional header */
542 {IMAGE_NT_OPTIONAL_HDR32_MAGIC, 4, 0, FILE_IDATA-FILE_TEXT,
543 FILE_TOTAL-FILE_IDATA + FILE_IDATA-FILE_TEXT, 0x400,
544 RVA_TEXT, RVA_TEXT, RVA_BSS, VA_START, 0x1000, 0x200, 4, 0, 1, 0, 4, 0, 0,
545 RVA_TOTAL, FILE_TEXT, 0, IMAGE_SUBSYSTEM_WINDOWS_GUI, 0,
546 0x200000, 0x1000, 0x100000, 0x1000, 0, 0x10,
547 {{0, 0},
548 {RVA_IDATA, sizeof(struct Imports)}
552 /* sections */
554 {".text", {0x100}, RVA_TEXT, FILE_IDATA-FILE_TEXT, FILE_TEXT,
555 0, 0, 0, 0, IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ},
556 {".bss", {0x400}, RVA_BSS, 0, 0, 0, 0, 0, 0,
557 IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE},
558 {".idata", {sizeof(struct Imports)}, RVA_IDATA, FILE_TOTAL-FILE_IDATA, FILE_IDATA, 0,
559 0, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE}
561 /* alignment before first section */
563 /* .text section */
565 0x31, 0xC0, /* xor eax, eax */
566 0xFF, 0x25, EXIT_PROCESS&0xFF, (EXIT_PROCESS>>8)&0xFF, (EXIT_PROCESS>>16)&0xFF,
567 (EXIT_PROCESS>>24)&0xFF, /* jmp ExitProcess */
570 /* .idata section */
573 {{RVA_IDATA + FIELD_OFFSET(struct Imports, original_thunks)}, 0, 0,
574 RVA_IDATA + FIELD_OFFSET(struct Imports, dllname),
575 RVA_IDATA + FIELD_OFFSET(struct Imports, thunks)
577 {{0}, 0, 0, 0, 0}
579 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
580 {{{RVA_IDATA+FIELD_OFFSET(struct Imports, ibn)}}, {{0}}},
581 {0,"ExitProcess"},
582 "KERNEL32.DLL"
584 /* final alignment */
587 #include <poppack.h>
589 /* Creates a test file and returns a handle to it. The file's path is returned
590 * in temp_file, which must be at least MAX_PATH characters in length.
592 static HANDLE create_temp_file(char *temp_file)
594 HANDLE file = INVALID_HANDLE_VALUE;
595 char temp_path[MAX_PATH];
597 if (GetTempPathA(sizeof(temp_path), temp_path))
599 if (GetTempFileNameA(temp_path, "img", 0, temp_file))
600 file = CreateFileA(temp_file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
601 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
603 return file;
606 static void test_sip_create_indirect_data(void)
608 static GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
609 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
610 static char oid_sha1[] = szOID_OIWSEC_sha1;
611 BOOL ret;
612 SIP_SUBJECTINFO subjinfo = { 0 };
613 char temp_file[MAX_PATH];
614 HANDLE file;
615 DWORD count;
617 if (!CryptSIPCreateIndirectData_p)
619 skip("Missing CryptSIPCreateIndirectData\n");
620 return;
622 SetLastError(0xdeadbeef);
623 ret = CryptSIPCreateIndirectData_p(NULL, NULL, NULL);
624 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
625 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
626 SetLastError(0xdeadbeef);
627 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
628 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
629 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
630 subjinfo.cbSize = sizeof(subjinfo);
631 SetLastError(0xdeadbeef);
632 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
633 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
634 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
635 file = create_temp_file(temp_file);
636 if (file == INVALID_HANDLE_VALUE)
638 skip("couldn't create temp file\n");
639 return;
641 WriteFile(file, &bin, sizeof(bin), &count, NULL);
642 FlushFileBuffers(file);
644 subjinfo.hFile = file;
645 SetLastError(0xdeadbeef);
646 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
647 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
648 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
649 subjinfo.pgSubjectType = &unknown;
650 SetLastError(0xdeadbeef);
651 ret = CryptSIPCreateIndirectData_p(&subjinfo, NULL, NULL);
652 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
653 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
654 count = 0xdeadbeef;
655 SetLastError(0xdeadbeef);
656 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
657 todo_wine
658 ok(!ret && (GetLastError() == NTE_BAD_ALGID ||
659 GetLastError() == ERROR_INVALID_PARAMETER /* Win7 */),
660 "expected NTE_BAD_ALGID or ERROR_INVALID_PARAMETER, got %08x\n",
661 GetLastError());
662 ok(count == 0xdeadbeef, "expected count to be unmodified, got %d\n", count);
663 subjinfo.DigestAlgorithm.pszObjId = oid_sha1;
664 count = 0xdeadbeef;
665 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, NULL);
666 todo_wine
667 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
668 ok(count, "expected a positive count\n");
669 if (ret)
671 SIP_INDIRECT_DATA *indirect = HeapAlloc(GetProcessHeap(), 0, count);
673 count = 256;
674 ret = CryptSIPCreateIndirectData_p(&subjinfo, &count, indirect);
675 ok(ret, "CryptSIPCreateIndirectData failed: %d\n", GetLastError());
676 /* If the count is larger than needed, it's unmodified */
677 ok(count == 256, "unexpected count %d\n", count);
678 ok(!strcmp(indirect->Data.pszObjId, SPC_PE_IMAGE_DATA_OBJID),
679 "unexpected data oid %s\n",
680 indirect->Data.pszObjId);
681 ok(!strcmp(indirect->DigestAlgorithm.pszObjId, oid_sha1),
682 "unexpected digest algorithm oid %s\n",
683 indirect->DigestAlgorithm.pszObjId);
684 ok(indirect->Digest.cbData == 20, "unexpected hash size %d\n",
685 indirect->Digest.cbData);
686 if (indirect->Digest.cbData == 20)
688 const BYTE hash[20] = {
689 0x8a,0xd5,0x45,0x53,0x3d,0x67,0xdf,0x2f,0x78,0xe0,
690 0x55,0x0a,0xe0,0xd9,0x7a,0x28,0x3e,0xbf,0x45,0x2b };
692 ok(!memcmp(indirect->Digest.pbData, hash, 20),
693 "unexpected value\n");
696 HeapFree(GetProcessHeap(), 0, indirect);
698 CloseHandle(file);
699 DeleteFileA(temp_file);
702 static void test_wintrust(void)
704 static GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
705 WINTRUST_DATA wtd;
706 WINTRUST_FILE_INFO file;
707 LONG r;
708 HRESULT hr;
709 WCHAR notepadPathW[MAX_PATH];
711 memset(&wtd, 0, sizeof(wtd));
712 wtd.cbStruct = sizeof(wtd);
713 wtd.dwUIChoice = WTD_UI_NONE;
714 wtd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
715 wtd.dwUnionChoice = WTD_CHOICE_FILE;
716 U(wtd).pFile = &file;
717 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
718 memset(&file, 0, sizeof(file));
719 file.cbStruct = sizeof(file);
720 getNotepadPath(notepadPathW, MAX_PATH);
721 file.pcwszFilePath = notepadPathW;
722 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
723 ok(r == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
724 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", r);
725 hr = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
726 ok(hr == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
727 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", hr);
730 static void test_get_known_usages(void)
732 BOOL ret;
733 PCCRYPT_OID_INFO *usages;
735 if (!pWTHelperGetKnownUsages)
737 skip("missing WTHelperGetKnownUsages\n");
738 return;
740 SetLastError(0xdeadbeef);
741 ret = pWTHelperGetKnownUsages(0, NULL);
742 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
743 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
744 SetLastError(0xdeadbeef);
745 ret = pWTHelperGetKnownUsages(1, NULL);
746 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
747 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
748 SetLastError(0xdeadbeef);
749 ret = pWTHelperGetKnownUsages(0, &usages);
750 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
751 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
752 /* A value of 1 for the first parameter seems to imply the value is
753 * allocated
755 SetLastError(0xdeadbeef);
756 usages = NULL;
757 ret = pWTHelperGetKnownUsages(1, &usages);
758 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
759 ok(usages != NULL, "expected a pointer\n");
760 if (ret && usages)
762 PCCRYPT_OID_INFO *ptr;
764 /* The returned usages are an array of PCCRYPT_OID_INFOs, terminated with a
765 * NULL pointer.
767 for (ptr = usages; *ptr; ptr++)
769 ok((*ptr)->cbSize == sizeof(CRYPT_OID_INFO) ||
770 (*ptr)->cbSize == (sizeof(CRYPT_OID_INFO) + 2 * sizeof(LPCWSTR)), /* Vista */
771 "unexpected size %d\n", (*ptr)->cbSize);
772 /* Each returned usage is in the CRYPT_ENHKEY_USAGE_OID_GROUP_ID group */
773 ok((*ptr)->dwGroupId == CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
774 "expected group CRYPT_ENHKEY_USAGE_OID_GROUP_ID, got %d\n",
775 (*ptr)->dwGroupId);
778 /* A value of 2 for the second parameter seems to imply the value is freed
780 SetLastError(0xdeadbeef);
781 ret = pWTHelperGetKnownUsages(2, &usages);
782 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
783 ok(usages == NULL, "expected pointer to be cleared\n");
784 SetLastError(0xdeadbeef);
785 usages = NULL;
786 ret = pWTHelperGetKnownUsages(2, &usages);
787 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
788 SetLastError(0xdeadbeef);
789 ret = pWTHelperGetKnownUsages(2, NULL);
790 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
791 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
794 START_TEST(softpub)
796 InitFunctionPtrs();
797 test_provider_funcs();
798 test_sip_create_indirect_data();
799 test_wintrust();
800 test_get_known_usages();