Import my Hybrid-CD stuff from last year.
[reactos.git] / rostests / winetests / wintrust / softpub.c
1 /*
2 * wintrust softpub functions tests
3 *
4 * Copyright 2007 Juan Lang
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20 #include <assert.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winerror.h>
26 #include <wintrust.h>
27 #include <softpub.h>
28 #include <mssip.h>
29 #include <winuser.h>
30 #include "winnls.h"
31
32 #include "wine/test.h"
33
34 /* Just in case we're being built with borked headers, redefine function
35 * pointers to have the correct calling convention.
36 */
37 typedef void *(WINAPI *SAFE_MEM_ALLOC)(DWORD);
38 typedef void (WINAPI *SAFE_MEM_FREE)(void *);
39 typedef BOOL (WINAPI *SAFE_ADD_STORE)(CRYPT_PROVIDER_DATA *,
40 HCERTSTORE);
41 typedef BOOL (WINAPI *SAFE_ADD_SGNR)(CRYPT_PROVIDER_DATA *,
42 BOOL, DWORD, struct _CRYPT_PROVIDER_SGNR *);
43 typedef BOOL (WINAPI *SAFE_ADD_CERT)(CRYPT_PROVIDER_DATA *,
44 DWORD, BOOL, DWORD, PCCERT_CONTEXT);
45 typedef BOOL (WINAPI *SAFE_ADD_PRIVDATA)(CRYPT_PROVIDER_DATA *,
46 CRYPT_PROVIDER_PRIVDATA *);
47 typedef HRESULT (WINAPI *SAFE_PROVIDER_INIT_CALL)(CRYPT_PROVIDER_DATA *);
48 typedef HRESULT (WINAPI *SAFE_PROVIDER_OBJTRUST_CALL)(CRYPT_PROVIDER_DATA *);
49 typedef HRESULT (WINAPI *SAFE_PROVIDER_SIGTRUST_CALL)(CRYPT_PROVIDER_DATA *);
50 typedef HRESULT (WINAPI *SAFE_PROVIDER_CERTTRUST_CALL)(CRYPT_PROVIDER_DATA *);
51 typedef HRESULT (WINAPI *SAFE_PROVIDER_FINALPOLICY_CALL)(CRYPT_PROVIDER_DATA *);
52 typedef HRESULT (WINAPI *SAFE_PROVIDER_TESTFINALPOLICY_CALL)(
53 CRYPT_PROVIDER_DATA *);
54 typedef HRESULT (WINAPI *SAFE_PROVIDER_CLEANUP_CALL)(CRYPT_PROVIDER_DATA *);
55 typedef BOOL (WINAPI *SAFE_PROVIDER_CERTCHKPOLICY_CALL)(
56 CRYPT_PROVIDER_DATA *, DWORD, BOOL, DWORD);
57
58 typedef struct _SAFE_PROVIDER_FUNCTIONS
59 {
60 DWORD cbStruct;
61 SAFE_MEM_ALLOC pfnAlloc;
62 SAFE_MEM_FREE pfnFree;
63 SAFE_ADD_STORE pfnAddStore2Chain;
64 SAFE_ADD_SGNR pfnAddSgnr2Chain;
65 SAFE_ADD_CERT pfnAddCert2Chain;
66 SAFE_ADD_PRIVDATA pfnAddPrivData2Chain;
67 SAFE_PROVIDER_INIT_CALL pfnInitialize;
68 SAFE_PROVIDER_OBJTRUST_CALL pfnObjectTrust;
69 SAFE_PROVIDER_SIGTRUST_CALL pfnSignatureTrust;
70 SAFE_PROVIDER_CERTTRUST_CALL pfnCertificateTrust;
71 SAFE_PROVIDER_FINALPOLICY_CALL pfnFinalPolicy;
72 SAFE_PROVIDER_CERTCHKPOLICY_CALL pfnCertCheckPolicy;
73 SAFE_PROVIDER_TESTFINALPOLICY_CALL pfnTestFinalPolicy;
74 struct _CRYPT_PROVUI_FUNCS *psUIpfns;
75 SAFE_PROVIDER_CLEANUP_CALL pfnCleanupPolicy;
76 } SAFE_PROVIDER_FUNCTIONS;
77
78 static const BYTE v1CertWithPubKey[] = {
79 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
80 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
81 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
82 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
83 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
84 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
85 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
86 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
87 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
88 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
89 0x01,0x01 };
90
91 static void test_utils(SAFE_PROVIDER_FUNCTIONS *funcs)
92 {
93 CRYPT_PROVIDER_DATA data = { 0 };
94 HCERTSTORE store;
95 CRYPT_PROVIDER_SGNR sgnr = { 0 };
96 BOOL ret;
97
98 /* Crash
99 ret = funcs->pfnAddStore2Chain(NULL, NULL);
100 ret = funcs->pfnAddStore2Chain(&data, NULL);
101 */
102 store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0,
103 CERT_STORE_CREATE_NEW_FLAG, NULL);
104 if (store)
105 {
106 ret = funcs->pfnAddStore2Chain(&data, store);
107 ok(ret, "pfnAddStore2Chain failed: %08x\n", GetLastError());
108 ok(data.chStores == 1, "Expected 1 store, got %d\n", data.chStores);
109 ok(data.pahStores != NULL, "Expected pahStores to be allocated\n");
110 if (data.pahStores)
111 {
112 ok(data.pahStores[0] == store, "Unexpected store\n");
113 CertCloseStore(data.pahStores[0], 0);
114 funcs->pfnFree(data.pahStores);
115 data.pahStores = NULL;
116 data.chStores = 0;
117 CertCloseStore(store, 0);
118 store = NULL;
119 }
120 }
121 else
122 skip("CertOpenStore failed: %08x\n", GetLastError());
123
124 /* Crash
125 ret = funcs->pfnAddSgnr2Chain(NULL, FALSE, 0, NULL);
126 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, NULL);
127 */
128 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
129 ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
130 ok(data.csSigners == 1, "Expected 1 signer, got %d\n", data.csSigners);
131 ok(data.pasSigners != NULL, "Expected pasSigners to be allocated\n");
132 if (data.pasSigners)
133 {
134 PCCERT_CONTEXT cert;
135
136 ok(!memcmp(&data.pasSigners[0], &sgnr, sizeof(sgnr)),
137 "Unexpected data in signer\n");
138 /* Adds into the location specified by the index */
139 sgnr.cbStruct = sizeof(CRYPT_PROVIDER_SGNR);
140 sgnr.sftVerifyAsOf.dwLowDateTime = 0xdeadbeef;
141 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 1, &sgnr);
142 ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
143 ok(data.csSigners == 2, "Expected 2 signers, got %d\n", data.csSigners);
144 ok(!memcmp(&data.pasSigners[1], &sgnr, sizeof(sgnr)),
145 "Unexpected data in signer\n");
146 /* This also adds, but the data aren't copied */
147 sgnr.cbStruct = sizeof(DWORD);
148 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
149 ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
150 ok(data.csSigners == 3, "Expected 3 signers, got %d\n", data.csSigners);
151 ok(data.pasSigners[0].cbStruct == 0, "Unexpected data size %d\n",
152 data.pasSigners[0].cbStruct);
153 ok(data.pasSigners[0].sftVerifyAsOf.dwLowDateTime == 0,
154 "Unexpected verify time %d\n",
155 data.pasSigners[0].sftVerifyAsOf.dwLowDateTime);
156 /* But too large a thing isn't added */
157 sgnr.cbStruct = sizeof(sgnr) + sizeof(DWORD);
158 SetLastError(0xdeadbeef);
159 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
160 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
161 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
162
163 /* Crash
164 ret = funcs->pfnAddCert2Chain(NULL, 0, FALSE, 0, NULL);
165 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, NULL);
166 */
167 cert = CertCreateCertificateContext(X509_ASN_ENCODING, v1CertWithPubKey,
168 sizeof(v1CertWithPubKey));
169 if (cert)
170 {
171 /* Notes on behavior that are hard to test:
172 * 1. If pasSigners is invalid, pfnAddCert2Chain crashes
173 * 2. An invalid signer index isn't checked.
174 */
175 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
176 ok(ret, "pfnAddCert2Chain failed: %08x\n", GetLastError());
177 ok(data.pasSigners[0].csCertChain == 1, "Expected 1 cert, got %d\n",
178 data.pasSigners[0].csCertChain);
179 ok(data.pasSigners[0].pasCertChain != NULL,
180 "Expected pasCertChain to be allocated\n");
181 if (data.pasSigners[0].pasCertChain)
182 {
183 ok(data.pasSigners[0].pasCertChain[0].pCert == cert,
184 "Unexpected cert\n");
185 CertFreeCertificateContext(
186 data.pasSigners[0].pasCertChain[0].pCert);
187 }
188 CertFreeCertificateContext(cert);
189 }
190 else
191 skip("CertCreateCertificateContext failed: %08x\n", GetLastError());
192 }
193 }
194
195 static void testInitialize(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
196 {
197 HRESULT ret;
198 CRYPT_PROVIDER_DATA data = { 0 };
199 WINTRUST_DATA wintrust_data = { 0 };
200
201 if (!funcs->pfnInitialize)
202 {
203 skip("missing pfnInitialize\n");
204 return;
205 }
206
207 /* Crashes
208 ret = funcs->pfnInitialize(NULL);
209 */
210 memset(&data, 0, sizeof(data));
211 ret = funcs->pfnInitialize(&data);
212 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
213 data.padwTrustStepErrors =
214 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
215 /* Without wintrust data set, crashes when padwTrustStepErrors is set */
216 data.pWintrustData = &wintrust_data;
217 if (data.padwTrustStepErrors)
218 {
219 /* Apparently, cdwTrustStepErrors does not need to be set. */
220 ret = funcs->pfnInitialize(&data);
221 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
222 data.cdwTrustStepErrors = 1;
223 ret = funcs->pfnInitialize(&data);
224 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
225 memset(data.padwTrustStepErrors, 0xba,
226 TRUSTERROR_MAX_STEPS * sizeof(DWORD));
227 ret = funcs->pfnInitialize(&data);
228 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
229 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] = 0;
230 ret = funcs->pfnInitialize(&data);
231 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
232 funcs->pfnFree(data.padwTrustStepErrors);
233 }
234 }
235
236 static void getNotepadPath(WCHAR *notepadPathW, DWORD size)
237 {
238 static const CHAR notepad[] = "\\notepad.exe";
239 CHAR notepadPath[MAX_PATH];
240
241 /* Workaround missing W-functions for win9x */
242 GetWindowsDirectoryA(notepadPath, MAX_PATH);
243 lstrcatA(notepadPath, notepad);
244 MultiByteToWideChar(0, 0, notepadPath, -1, notepadPathW, size);
245 }
246
247 static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
248 {
249 HRESULT ret;
250 CRYPT_PROVIDER_DATA data = { 0 };
251 WINTRUST_DATA wintrust_data = { 0 };
252 WINTRUST_CERT_INFO certInfo = { sizeof(WINTRUST_CERT_INFO), 0 };
253 WINTRUST_FILE_INFO fileInfo = { sizeof(WINTRUST_FILE_INFO), 0 };
254
255 if (!funcs->pfnObjectTrust)
256 {
257 skip("missing pfnObjectTrust\n");
258 return;
259 }
260
261 /* Crashes
262 ret = funcs->pfnObjectTrust(NULL);
263 */
264 data.pWintrustData = &wintrust_data;
265 data.padwTrustStepErrors =
266 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
267 if (data.padwTrustStepErrors)
268 {
269 WCHAR notepadPathW[MAX_PATH];
270 PROVDATA_SIP provDataSIP = { 0 };
271 static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
272 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
273 static GUID bogusGuid = { 0xdeadbeef, 0xbaad, 0xf00d, { 0x00,0x00,0x00,
274 0x00,0x00,0x00,0x00,0x00 } };
275
276 ret = funcs->pfnObjectTrust(&data);
277 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
278 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
279 ERROR_INVALID_PARAMETER,
280 "Expected ERROR_INVALID_PARAMETER, got %08x\n",
281 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
282 U(wintrust_data).pCert = &certInfo;
283 wintrust_data.dwUnionChoice = WTD_CHOICE_CERT;
284 ret = funcs->pfnObjectTrust(&data);
285 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
286 certInfo.psCertContext = (PCERT_CONTEXT)CertCreateCertificateContext(
287 X509_ASN_ENCODING, v1CertWithPubKey, sizeof(v1CertWithPubKey));
288 ret = funcs->pfnObjectTrust(&data);
289 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
290 CertFreeCertificateContext(certInfo.psCertContext);
291 certInfo.psCertContext = NULL;
292 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
293 U(wintrust_data).pFile = NULL;
294 ret = funcs->pfnObjectTrust(&data);
295 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
296 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
297 ERROR_INVALID_PARAMETER,
298 "Expected ERROR_INVALID_PARAMETER, got %08x\n",
299 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
300 U(wintrust_data).pFile = &fileInfo;
301 /* Crashes
302 ret = funcs->pfnObjectTrust(&data);
303 */
304 getNotepadPath(notepadPathW, MAX_PATH);
305 fileInfo.pcwszFilePath = notepadPathW;
306 /* pfnObjectTrust now crashes unless both pPDSip and psPfns are set */
307 U(data).pPDSip = &provDataSIP;
308 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
309 ret = funcs->pfnObjectTrust(&data);
310 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
311 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
312 TRUST_E_NOSIGNATURE ||
313 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
314 TRUST_E_SUBJECT_FORM_UNKNOWN,
315 "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
316 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
317 if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
318 TRUST_E_NOSIGNATURE)
319 {
320 ok(!memcmp(&provDataSIP.gSubject, &unknown, sizeof(unknown)),
321 "Unexpected subject GUID\n");
322 ok(provDataSIP.pSip != NULL, "Expected a SIP\n");
323 ok(provDataSIP.psSipSubjectInfo != NULL,
324 "Expected a subject info\n");
325 }
326 /* Specifying the GUID results in that GUID being the subject GUID */
327 fileInfo.pgKnownSubject = &bogusGuid;
328 ret = funcs->pfnObjectTrust(&data);
329 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
330 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
331 TRUST_E_NOSIGNATURE ||
332 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
333 TRUST_E_SUBJECT_FORM_UNKNOWN ||
334 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
335 TRUST_E_PROVIDER_UNKNOWN,
336 "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN or TRUST_E_PROVIDER_UNKNOWN, got %08x\n",
337 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
338 if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
339 TRUST_E_NOSIGNATURE)
340 {
341 ok(!memcmp(&provDataSIP.gSubject, &bogusGuid, sizeof(bogusGuid)),
342 "unexpected subject GUID\n");
343 }
344 /* Specifying a bogus GUID pointer crashes */
345 if (0)
346 {
347 fileInfo.pgKnownSubject = (GUID *)0xdeadbeef;
348 ret = funcs->pfnObjectTrust(&data);
349 }
350 funcs->pfnFree(data.padwTrustStepErrors);
351 }
352 }
353
354 static const BYTE selfSignedCert[] = {
355 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
356 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
357 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
358 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
359 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
360 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
361 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
362 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
363 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
364 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
365 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
366 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
367 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
368 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
369 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
370 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
371 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
372 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
373 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
374 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
375 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
376 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
377 0xa8, 0x76, 0x57, 0x92, 0x36 };
378
379 static void testCertTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
380 {
381 CRYPT_PROVIDER_DATA data = { 0 };
382 CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
383 HRESULT ret;
384
385 data.padwTrustStepErrors =
386 funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
387 if (!data.padwTrustStepErrors)
388 {
389 skip("pfnAlloc failed\n");
390 return;
391 }
392 ret = funcs->pfnCertificateTrust(&data);
393 ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
394 ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
395 TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
396 data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
397 ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
398 if (ret)
399 {
400 PCCERT_CONTEXT cert;
401
402 /* An empty signer "succeeds," even though there's no cert */
403 ret = funcs->pfnCertificateTrust(&data);
404 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
405 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
406 sizeof(selfSignedCert));
407 if (cert)
408 {
409 WINTRUST_DATA wintrust_data = { 0 };
410
411 ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
412 /* If pWintrustData isn't set, crashes attempting to access
413 * pWintrustData->fdwRevocationChecks
414 */
415 data.pWintrustData = &wintrust_data;
416 /* If psPfns isn't set, crashes attempting to access
417 * psPfns->pfnCertCheckPolicy
418 */
419 data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
420 ret = funcs->pfnCertificateTrust(&data);
421 ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
422 ok(data.csSigners == 1, "Unexpected number of signers %d\n",
423 data.csSigners);
424 ok(data.pasSigners[0].pChainContext != NULL,
425 "Expected a certificate chain\n");
426 ok(data.pasSigners[0].csCertChain == 1,
427 "Unexpected number of chain elements %d\n",
428 data.pasSigners[0].csCertChain);
429 /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
430 * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
431 */
432 ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
433 "Didn't expect cert to be trusted\n");
434 ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
435 "Expected cert to be self-signed\n");
436 ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
437 (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
438 "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
439 data.pasSigners[0].pasCertChain[0].dwConfidence);
440 CertFreeCertificateContext(
441 data.pasSigners[0].pasCertChain[0].pCert);
442 CertFreeCertificateChain(data.pasSigners[0].pChainContext);
443 CertFreeCertificateContext(cert);
444 }
445 }
446 }
447
448 static void test_provider_funcs(void)
449 {
450 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
451 SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
452 BOOL ret;
453
454 ret = WintrustLoadFunctionPointers(&generic_verify_v2,
455 (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
456 if (!ret)
457 skip("WintrustLoadFunctionPointers failed\n");
458 else
459 {
460 test_utils(&funcs);
461 testInitialize(&funcs, &generic_verify_v2);
462 testObjTrust(&funcs, &generic_verify_v2);
463 testCertTrust(&funcs, &generic_verify_v2);
464 }
465 }
466
467 static void test_wintrust(void)
468 {
469 static GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
470 WINTRUST_DATA wtd;
471 WINTRUST_FILE_INFO file;
472 LONG r;
473 HRESULT hr;
474 WCHAR notepadPathW[MAX_PATH];
475
476 memset(&wtd, 0, sizeof(wtd));
477 wtd.cbStruct = sizeof(wtd);
478 wtd.dwUIChoice = WTD_UI_NONE;
479 wtd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
480 wtd.dwUnionChoice = WTD_CHOICE_FILE;
481 U(wtd).pFile = &file;
482 wtd.dwStateAction = WTD_STATEACTION_VERIFY;
483 memset(&file, 0, sizeof(file));
484 file.cbStruct = sizeof(file);
485 getNotepadPath(notepadPathW, MAX_PATH);
486 file.pcwszFilePath = notepadPathW;
487 r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
488 ok(r == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
489 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", r);
490 hr = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
491 ok(hr == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
492 "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", hr);
493 }
494
495 static BOOL (WINAPI * pWTHelperGetKnownUsages)(DWORD action, PCCRYPT_OID_INFO **usages);
496
497 static void InitFunctionPtrs(void)
498 {
499 HMODULE hWintrust = GetModuleHandleA("wintrust.dll");
500
501 #define WINTRUST_GET_PROC(func) \
502 p ## func = (void*)GetProcAddress(hWintrust, #func); \
503 if(!p ## func) { \
504 trace("GetProcAddress(%s) failed\n", #func); \
505 }
506
507 WINTRUST_GET_PROC(WTHelperGetKnownUsages)
508
509 #undef WINTRUST_GET_PROC
510 }
511
512 static void test_get_known_usages(void)
513 {
514 BOOL ret;
515 PCCRYPT_OID_INFO *usages;
516
517 if (!pWTHelperGetKnownUsages)
518 {
519 skip("missing WTHelperGetKnownUsages\n");
520 return;
521 }
522 SetLastError(0xdeadbeef);
523 ret = pWTHelperGetKnownUsages(0, NULL);
524 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
525 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
526 SetLastError(0xdeadbeef);
527 ret = pWTHelperGetKnownUsages(1, NULL);
528 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
529 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
530 SetLastError(0xdeadbeef);
531 ret = pWTHelperGetKnownUsages(0, &usages);
532 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
533 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
534 /* A value of 1 for the first parameter seems to imply the value is
535 * allocated
536 */
537 SetLastError(0xdeadbeef);
538 usages = NULL;
539 ret = pWTHelperGetKnownUsages(1, &usages);
540 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
541 ok(usages != NULL, "expected a pointer\n");
542 if (ret && usages)
543 {
544 PCCRYPT_OID_INFO *ptr;
545
546 /* The returned usages are an array of PCCRYPT_OID_INFOs, terminated with a
547 * NULL pointer.
548 */
549 for (ptr = usages; *ptr; ptr++)
550 {
551 ok((*ptr)->cbSize == sizeof(CRYPT_OID_INFO) ||
552 (*ptr)->cbSize == (sizeof(CRYPT_OID_INFO) + 2 * sizeof(LPCWSTR)), /* Vista */
553 "unexpected size %d\n", (*ptr)->cbSize);
554 /* Each returned usage is in the CRYPT_ENHKEY_USAGE_OID_GROUP_ID group */
555 ok((*ptr)->dwGroupId == CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
556 "expected group CRYPT_ENHKEY_USAGE_OID_GROUP_ID, got %d\n",
557 (*ptr)->dwGroupId);
558 }
559 }
560 /* A value of 2 for the second parameter seems to imply the value is freed
561 */
562 SetLastError(0xdeadbeef);
563 ret = pWTHelperGetKnownUsages(2, &usages);
564 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
565 ok(usages == NULL, "expected pointer to be cleared\n");
566 SetLastError(0xdeadbeef);
567 usages = NULL;
568 ret = pWTHelperGetKnownUsages(2, &usages);
569 ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
570 SetLastError(0xdeadbeef);
571 ret = pWTHelperGetKnownUsages(2, NULL);
572 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
573 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
574 }
575
576 START_TEST(softpub)
577 {
578 InitFunctionPtrs();
579 test_provider_funcs();
580 test_wintrust();
581 test_get_known_usages();
582 }