Sync with trunk r63283
[reactos.git] / dll / win32 / wintrust / softpub.c
1 /*
2 * Copyright 2007 Juan Lang
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include "wintrust_priv.h"
20
21 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
22
23 HRESULT WINAPI SoftpubDefCertInit(CRYPT_PROVIDER_DATA *data)
24 {
25 HRESULT ret = S_FALSE;
26
27 TRACE("(%p)\n", data);
28
29 if (data->padwTrustStepErrors &&
30 !data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT])
31 ret = S_OK;
32 TRACE("returning %08x\n", ret);
33 return ret;
34 }
35
36 HRESULT WINAPI SoftpubInitialize(CRYPT_PROVIDER_DATA *data)
37 {
38 HRESULT ret = S_FALSE;
39
40 TRACE("(%p)\n", data);
41
42 if (data->padwTrustStepErrors &&
43 !data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT])
44 ret = S_OK;
45 TRACE("returning %08x\n", ret);
46 return ret;
47 }
48
49 HRESULT WINAPI DriverInitializePolicy(CRYPT_PROVIDER_DATA *data)
50 {
51 FIXME("stub\n");
52 return S_OK;
53 }
54
55 HRESULT WINAPI DriverCleanupPolicy(CRYPT_PROVIDER_DATA *data)
56 {
57 FIXME("stub\n");
58 return S_OK;
59 }
60
61 HRESULT WINAPI DriverFinalPolicy(CRYPT_PROVIDER_DATA *data)
62 {
63 FIXME("stub\n");
64 return S_OK;
65 }
66
67 /* Assumes data->pWintrustData->u.pFile exists. Makes sure a file handle is
68 * open for the file.
69 */
70 static DWORD SOFTPUB_OpenFile(CRYPT_PROVIDER_DATA *data)
71 {
72 DWORD err = ERROR_SUCCESS;
73
74 /* PSDK implies that all values should be initialized to NULL, so callers
75 * typically have hFile as NULL rather than INVALID_HANDLE_VALUE. Check
76 * for both.
77 */
78 if (!data->pWintrustData->u.pFile->hFile ||
79 data->pWintrustData->u.pFile->hFile == INVALID_HANDLE_VALUE)
80 {
81 data->pWintrustData->u.pFile->hFile =
82 CreateFileW(data->pWintrustData->u.pFile->pcwszFilePath, GENERIC_READ,
83 FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
84 if (data->pWintrustData->u.pFile->hFile != INVALID_HANDLE_VALUE)
85 data->fOpenedFile = TRUE;
86 else
87 err = GetLastError();
88 }
89 if (!err)
90 GetFileTime(data->pWintrustData->u.pFile->hFile, &data->sftSystemTime,
91 NULL, NULL);
92 TRACE("returning %d\n", err);
93 return err;
94 }
95
96 /* Assumes data->pWintrustData->u.pFile exists. Sets data->pPDSip->gSubject to
97 * the file's subject GUID.
98 */
99 static DWORD SOFTPUB_GetFileSubject(CRYPT_PROVIDER_DATA *data)
100 {
101 DWORD err = ERROR_SUCCESS;
102
103 if (!WVT_ISINSTRUCT(WINTRUST_FILE_INFO,
104 data->pWintrustData->u.pFile->cbStruct, pgKnownSubject) ||
105 !data->pWintrustData->u.pFile->pgKnownSubject)
106 {
107 if (!CryptSIPRetrieveSubjectGuid(
108 data->pWintrustData->u.pFile->pcwszFilePath,
109 data->pWintrustData->u.pFile->hFile,
110 &data->u.pPDSip->gSubject))
111 {
112 LARGE_INTEGER fileSize;
113 DWORD sipError = GetLastError();
114
115 /* Special case for empty files: the error is expected to be
116 * TRUST_E_SUBJECT_FORM_UNKNOWN, rather than whatever
117 * CryptSIPRetrieveSubjectGuid returns.
118 */
119 if (GetFileSizeEx(data->pWintrustData->u.pFile->hFile, &fileSize)
120 && !fileSize.QuadPart)
121 err = TRUST_E_SUBJECT_FORM_UNKNOWN;
122 else
123 err = sipError;
124 }
125 }
126 else
127 data->u.pPDSip->gSubject = *data->pWintrustData->u.pFile->pgKnownSubject;
128 TRACE("returning %d\n", err);
129 return err;
130 }
131
132 /* Assumes data->u.pPDSip exists, and its gSubject member set.
133 * Allocates data->u.pPDSip->pSip and loads it, if possible.
134 */
135 static DWORD SOFTPUB_GetSIP(CRYPT_PROVIDER_DATA *data)
136 {
137 DWORD err = ERROR_SUCCESS;
138
139 data->u.pPDSip->pSip = data->psPfns->pfnAlloc(sizeof(SIP_DISPATCH_INFO));
140 if (data->u.pPDSip->pSip)
141 {
142 if (!CryptSIPLoad(&data->u.pPDSip->gSubject, 0, data->u.pPDSip->pSip))
143 err = GetLastError();
144 }
145 else
146 err = ERROR_OUTOFMEMORY;
147 TRACE("returning %d\n", err);
148 return err;
149 }
150
151 /* Assumes data->u.pPDSip has been loaded, and data->u.pPDSip->pSip allocated.
152 * Calls data->u.pPDSip->pSip->pfGet to construct data->hMsg.
153 */
154 static DWORD SOFTPUB_GetMessageFromFile(CRYPT_PROVIDER_DATA *data, HANDLE file,
155 LPCWSTR filePath)
156 {
157 DWORD err = ERROR_SUCCESS;
158 BOOL ret;
159 LPBYTE buf = NULL;
160 DWORD size = 0;
161
162 data->u.pPDSip->psSipSubjectInfo =
163 data->psPfns->pfnAlloc(sizeof(SIP_SUBJECTINFO));
164 if (!data->u.pPDSip->psSipSubjectInfo)
165 return ERROR_OUTOFMEMORY;
166
167 data->u.pPDSip->psSipSubjectInfo->cbSize = sizeof(SIP_SUBJECTINFO);
168 data->u.pPDSip->psSipSubjectInfo->pgSubjectType = &data->u.pPDSip->gSubject;
169 data->u.pPDSip->psSipSubjectInfo->hFile = file;
170 data->u.pPDSip->psSipSubjectInfo->pwsFileName = filePath;
171 data->u.pPDSip->psSipSubjectInfo->hProv = data->hProv;
172 ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo,
173 &data->dwEncoding, 0, &size, 0);
174 if (!ret)
175 return TRUST_E_NOSIGNATURE;
176
177 buf = data->psPfns->pfnAlloc(size);
178 if (!buf)
179 return ERROR_OUTOFMEMORY;
180
181 ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo,
182 &data->dwEncoding, 0, &size, buf);
183 if (ret)
184 {
185 data->hMsg = CryptMsgOpenToDecode(data->dwEncoding, 0, 0, data->hProv,
186 NULL, NULL);
187 if (data->hMsg)
188 {
189 ret = CryptMsgUpdate(data->hMsg, buf, size, TRUE);
190 if (!ret)
191 err = GetLastError();
192 }
193 }
194 else
195 err = GetLastError();
196
197 data->psPfns->pfnFree(buf);
198 TRACE("returning %d\n", err);
199 return err;
200 }
201
202 static DWORD SOFTPUB_CreateStoreFromMessage(CRYPT_PROVIDER_DATA *data)
203 {
204 DWORD err = ERROR_SUCCESS;
205 HCERTSTORE store;
206
207 store = CertOpenStore(CERT_STORE_PROV_MSG, data->dwEncoding,
208 data->hProv, CERT_STORE_NO_CRYPT_RELEASE_FLAG, data->hMsg);
209 if (store)
210 {
211 if (!data->psPfns->pfnAddStore2Chain(data, store))
212 err = GetLastError();
213 CertCloseStore(store, 0);
214 }
215 else
216 err = GetLastError();
217 TRACE("returning %d\n", err);
218 return err;
219 }
220
221 static DWORD SOFTPUB_DecodeInnerContent(CRYPT_PROVIDER_DATA *data)
222 {
223 BOOL ret;
224 DWORD size, err = ERROR_SUCCESS;
225 LPSTR oid = NULL;
226 LPBYTE buf = NULL;
227
228 ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL,
229 &size);
230 if (!ret)
231 {
232 err = GetLastError();
233 goto error;
234 }
235 oid = data->psPfns->pfnAlloc(size);
236 if (!oid)
237 {
238 err = ERROR_OUTOFMEMORY;
239 goto error;
240 }
241 ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, oid,
242 &size);
243 if (!ret)
244 {
245 err = GetLastError();
246 goto error;
247 }
248 ret = CryptMsgGetParam(data->hMsg, CMSG_CONTENT_PARAM, 0, NULL, &size);
249 if (!ret)
250 {
251 err = GetLastError();
252 goto error;
253 }
254 buf = data->psPfns->pfnAlloc(size);
255 if (!buf)
256 {
257 err = ERROR_OUTOFMEMORY;
258 goto error;
259 }
260 ret = CryptMsgGetParam(data->hMsg, CMSG_CONTENT_PARAM, 0, buf, &size);
261 if (!ret)
262 {
263 err = GetLastError();
264 goto error;
265 }
266 ret = CryptDecodeObject(data->dwEncoding, oid, buf, size, 0, NULL, &size);
267 if (!ret)
268 {
269 err = GetLastError();
270 goto error;
271 }
272 data->u.pPDSip->psIndirectData = data->psPfns->pfnAlloc(size);
273 if (!data->u.pPDSip->psIndirectData)
274 {
275 err = ERROR_OUTOFMEMORY;
276 goto error;
277 }
278 ret = CryptDecodeObject(data->dwEncoding, oid, buf, size, 0,
279 data->u.pPDSip->psIndirectData, &size);
280 if (!ret)
281 err = GetLastError();
282
283 error:
284 TRACE("returning %d\n", err);
285 data->psPfns->pfnFree(oid);
286 data->psPfns->pfnFree(buf);
287 return err;
288 }
289
290 static DWORD SOFTPUB_LoadCertMessage(CRYPT_PROVIDER_DATA *data)
291 {
292 DWORD err = ERROR_SUCCESS;
293
294 if (data->pWintrustData->u.pCert &&
295 WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_CERT_INFO,
296 data->pWintrustData->u.pCert->cbStruct, psCertContext))
297 {
298 if (data->psPfns)
299 {
300 CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
301 DWORD i;
302 BOOL ret;
303
304 /* Add a signer with nothing but the time to verify, so we can
305 * add a cert to it
306 */
307 if (WVT_ISINSTRUCT(WINTRUST_CERT_INFO,
308 data->pWintrustData->u.pCert->cbStruct, psftVerifyAsOf) &&
309 data->pWintrustData->u.pCert->psftVerifyAsOf)
310 data->sftSystemTime = signer.sftVerifyAsOf;
311 else
312 {
313 SYSTEMTIME sysTime;
314
315 GetSystemTime(&sysTime);
316 SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
317 }
318 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
319 if (ret)
320 {
321 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
322 data->pWintrustData->u.pCert->psCertContext);
323 if (WVT_ISINSTRUCT(WINTRUST_CERT_INFO,
324 data->pWintrustData->u.pCert->cbStruct, pahStores))
325 for (i = 0;
326 ret && i < data->pWintrustData->u.pCert->chStores; i++)
327 ret = data->psPfns->pfnAddStore2Chain(data,
328 data->pWintrustData->u.pCert->pahStores[i]);
329 }
330 if (!ret)
331 err = GetLastError();
332 }
333 }
334 else
335 err = ERROR_INVALID_PARAMETER;
336 return err;
337 }
338
339 static DWORD SOFTPUB_LoadFileMessage(CRYPT_PROVIDER_DATA *data)
340 {
341 DWORD err = ERROR_SUCCESS;
342
343 if (!data->pWintrustData->u.pFile)
344 {
345 err = ERROR_INVALID_PARAMETER;
346 goto error;
347 }
348 err = SOFTPUB_OpenFile(data);
349 if (err)
350 goto error;
351 err = SOFTPUB_GetFileSubject(data);
352 if (err)
353 goto error;
354 err = SOFTPUB_GetSIP(data);
355 if (err)
356 goto error;
357 err = SOFTPUB_GetMessageFromFile(data, data->pWintrustData->u.pFile->hFile,
358 data->pWintrustData->u.pFile->pcwszFilePath);
359 if (err)
360 goto error;
361 err = SOFTPUB_CreateStoreFromMessage(data);
362 if (err)
363 goto error;
364 err = SOFTPUB_DecodeInnerContent(data);
365
366 error:
367 if (err && data->fOpenedFile && data->pWintrustData->u.pFile)
368 {
369 /* The caller won't expect the file to be open on failure, so close it.
370 */
371 CloseHandle(data->pWintrustData->u.pFile->hFile);
372 data->pWintrustData->u.pFile->hFile = INVALID_HANDLE_VALUE;
373 data->fOpenedFile = FALSE;
374 }
375 return err;
376 }
377
378 static DWORD SOFTPUB_LoadCatalogMessage(CRYPT_PROVIDER_DATA *data)
379 {
380 DWORD err;
381 HANDLE catalog = INVALID_HANDLE_VALUE;
382
383 if (!data->pWintrustData->u.pCatalog)
384 {
385 SetLastError(ERROR_INVALID_PARAMETER);
386 return FALSE;
387 }
388 catalog = CreateFileW(data->pWintrustData->u.pCatalog->pcwszCatalogFilePath,
389 GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
390 NULL);
391 if (catalog == INVALID_HANDLE_VALUE)
392 return GetLastError();
393 if (!CryptSIPRetrieveSubjectGuid(
394 data->pWintrustData->u.pCatalog->pcwszCatalogFilePath, catalog,
395 &data->u.pPDSip->gSubject))
396 {
397 err = GetLastError();
398 goto error;
399 }
400 err = SOFTPUB_GetSIP(data);
401 if (err)
402 goto error;
403 err = SOFTPUB_GetMessageFromFile(data, catalog,
404 data->pWintrustData->u.pCatalog->pcwszCatalogFilePath);
405 if (err)
406 goto error;
407 err = SOFTPUB_CreateStoreFromMessage(data);
408 if (err)
409 goto error;
410 err = SOFTPUB_DecodeInnerContent(data);
411 /* FIXME: this loads the catalog file, but doesn't validate the member. */
412 error:
413 CloseHandle(catalog);
414 return err;
415 }
416
417 HRESULT WINAPI SoftpubLoadMessage(CRYPT_PROVIDER_DATA *data)
418 {
419 DWORD err = ERROR_SUCCESS;
420
421 TRACE("(%p)\n", data);
422
423 if (!data->padwTrustStepErrors)
424 return S_FALSE;
425
426 switch (data->pWintrustData->dwUnionChoice)
427 {
428 case WTD_CHOICE_CERT:
429 err = SOFTPUB_LoadCertMessage(data);
430 break;
431 case WTD_CHOICE_FILE:
432 err = SOFTPUB_LoadFileMessage(data);
433 break;
434 case WTD_CHOICE_CATALOG:
435 err = SOFTPUB_LoadCatalogMessage(data);
436 break;
437 default:
438 FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
439 err = ERROR_INVALID_PARAMETER;
440 }
441
442 if (err)
443 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] = err;
444 TRACE("returning %d (%08x)\n", !err ? S_OK : S_FALSE,
445 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
446 return !err ? S_OK : S_FALSE;
447 }
448
449 static CMSG_SIGNER_INFO *WINTRUST_GetSigner(CRYPT_PROVIDER_DATA *data,
450 DWORD signerIdx)
451 {
452 BOOL ret;
453 CMSG_SIGNER_INFO *signerInfo = NULL;
454 DWORD size;
455
456 ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_INFO_PARAM, signerIdx,
457 NULL, &size);
458 if (ret)
459 {
460 signerInfo = data->psPfns->pfnAlloc(size);
461 if (signerInfo)
462 {
463 ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_INFO_PARAM,
464 signerIdx, signerInfo, &size);
465 if (!ret)
466 {
467 data->psPfns->pfnFree(signerInfo);
468 signerInfo = NULL;
469 }
470 }
471 else
472 SetLastError(ERROR_OUTOFMEMORY);
473 }
474 return signerInfo;
475 }
476
477 static BOOL WINTRUST_GetTimeFromCounterSigner(
478 const CMSG_CMS_SIGNER_INFO *counterSignerInfo, FILETIME *time)
479 {
480 DWORD i;
481 BOOL foundTimeStamp = FALSE;
482
483 for (i = 0; !foundTimeStamp && i < counterSignerInfo->AuthAttrs.cAttr; i++)
484 {
485 if (!strcmp(counterSignerInfo->AuthAttrs.rgAttr[i].pszObjId,
486 szOID_RSA_signingTime))
487 {
488 const CRYPT_ATTRIBUTE *attr =
489 &counterSignerInfo->AuthAttrs.rgAttr[i];
490 DWORD j;
491
492 for (j = 0; !foundTimeStamp && j < attr->cValue; j++)
493 {
494 static const DWORD encoding = X509_ASN_ENCODING |
495 PKCS_7_ASN_ENCODING;
496 DWORD size = sizeof(FILETIME);
497
498 foundTimeStamp = CryptDecodeObjectEx(encoding,
499 X509_CHOICE_OF_TIME,
500 attr->rgValue[j].pbData, attr->rgValue[j].cbData, 0, NULL,
501 time, &size);
502 }
503 }
504 }
505 return foundTimeStamp;
506 }
507
508 static LPCSTR filetime_to_str(const FILETIME *time)
509 {
510 static char date[80];
511 char dateFmt[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
512 SYSTEMTIME sysTime;
513
514 if (!time) return NULL;
515
516 GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_SSHORTDATE, dateFmt,
517 sizeof(dateFmt) / sizeof(dateFmt[0]));
518 FileTimeToSystemTime(time, &sysTime);
519 GetDateFormatA(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, dateFmt, date,
520 sizeof(date) / sizeof(date[0]));
521 return date;
522 }
523
524 static FILETIME WINTRUST_GetTimeFromSigner(const CRYPT_PROVIDER_DATA *data,
525 const CMSG_SIGNER_INFO *signerInfo)
526 {
527 DWORD i;
528 FILETIME time;
529 BOOL foundTimeStamp = FALSE;
530
531 for (i = 0; !foundTimeStamp && i < signerInfo->UnauthAttrs.cAttr; i++)
532 {
533 if (!strcmp(signerInfo->UnauthAttrs.rgAttr[i].pszObjId,
534 szOID_RSA_counterSign))
535 {
536 const CRYPT_ATTRIBUTE *attr = &signerInfo->UnauthAttrs.rgAttr[i];
537 DWORD j;
538
539 for (j = 0; j < attr->cValue; j++)
540 {
541 static const DWORD encoding = X509_ASN_ENCODING |
542 PKCS_7_ASN_ENCODING;
543 CMSG_CMS_SIGNER_INFO *counterSignerInfo;
544 DWORD size;
545 BOOL ret = CryptDecodeObjectEx(encoding, CMS_SIGNER_INFO,
546 attr->rgValue[j].pbData, attr->rgValue[j].cbData,
547 CRYPT_DECODE_ALLOC_FLAG, NULL, &counterSignerInfo, &size);
548 if (ret)
549 {
550 /* FIXME: need to verify countersigner signature too */
551 foundTimeStamp = WINTRUST_GetTimeFromCounterSigner(
552 counterSignerInfo, &time);
553 LocalFree(counterSignerInfo);
554 }
555 }
556 }
557 }
558 if (!foundTimeStamp)
559 {
560 TRACE("returning system time %s\n",
561 filetime_to_str(&data->sftSystemTime));
562 time = data->sftSystemTime;
563 }
564 else
565 TRACE("returning time from message %s\n", filetime_to_str(&time));
566 return time;
567 }
568
569 static DWORD WINTRUST_SaveSigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
570 {
571 DWORD err;
572 CMSG_SIGNER_INFO *signerInfo = WINTRUST_GetSigner(data, signerIdx);
573
574 if (signerInfo)
575 {
576 CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
577
578 sgnr.psSigner = signerInfo;
579 sgnr.sftVerifyAsOf = WINTRUST_GetTimeFromSigner(data, signerInfo);
580 if (!data->psPfns->pfnAddSgnr2Chain(data, FALSE, signerIdx, &sgnr))
581 err = GetLastError();
582 else
583 err = ERROR_SUCCESS;
584 }
585 else
586 err = GetLastError();
587 return err;
588 }
589
590 static CERT_INFO *WINTRUST_GetSignerCertInfo(CRYPT_PROVIDER_DATA *data,
591 DWORD signerIdx)
592 {
593 BOOL ret;
594 CERT_INFO *certInfo = NULL;
595 DWORD size;
596
597 ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_CERT_INFO_PARAM, signerIdx,
598 NULL, &size);
599 if (ret)
600 {
601 certInfo = data->psPfns->pfnAlloc(size);
602 if (certInfo)
603 {
604 ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_CERT_INFO_PARAM,
605 signerIdx, certInfo, &size);
606 if (!ret)
607 {
608 data->psPfns->pfnFree(certInfo);
609 certInfo = NULL;
610 }
611 }
612 else
613 SetLastError(ERROR_OUTOFMEMORY);
614 }
615 return certInfo;
616 }
617
618 static DWORD WINTRUST_VerifySigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
619 {
620 DWORD err;
621 CERT_INFO *certInfo = WINTRUST_GetSignerCertInfo(data, signerIdx);
622
623 if (certInfo)
624 {
625 PCCERT_CONTEXT subject = CertGetSubjectCertificateFromStore(
626 data->pahStores[0], data->dwEncoding, certInfo);
627
628 if (subject)
629 {
630 CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para = { sizeof(para), 0,
631 signerIdx, CMSG_VERIFY_SIGNER_CERT, (LPVOID)subject };
632
633 if (!CryptMsgControl(data->hMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE_EX,
634 &para))
635 err = TRUST_E_CERT_SIGNATURE;
636 else
637 {
638 data->psPfns->pfnAddCert2Chain(data, signerIdx, FALSE, 0,
639 subject);
640 err = ERROR_SUCCESS;
641 }
642 CertFreeCertificateContext(subject);
643 }
644 else
645 err = TRUST_E_NO_SIGNER_CERT;
646 data->psPfns->pfnFree(certInfo);
647 }
648 else
649 err = GetLastError();
650 return err;
651 }
652
653 HRESULT WINAPI SoftpubLoadSignature(CRYPT_PROVIDER_DATA *data)
654 {
655 DWORD err;
656
657 TRACE("(%p)\n", data);
658
659 if (!data->padwTrustStepErrors)
660 return S_FALSE;
661
662 if (data->hMsg)
663 {
664 DWORD signerCount, size;
665
666 size = sizeof(signerCount);
667 if (CryptMsgGetParam(data->hMsg, CMSG_SIGNER_COUNT_PARAM, 0,
668 &signerCount, &size))
669 {
670 DWORD i;
671
672 err = ERROR_SUCCESS;
673 for (i = 0; !err && i < signerCount; i++)
674 {
675 if (!(err = WINTRUST_SaveSigner(data, i)))
676 err = WINTRUST_VerifySigner(data, i);
677 }
678 }
679 else
680 err = TRUST_E_NOSIGNATURE;
681 }
682 else
683 err = ERROR_SUCCESS;
684 if (err)
685 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = err;
686 return !err ? S_OK : S_FALSE;
687 }
688
689 static DWORD WINTRUST_TrustStatusToConfidence(DWORD errorStatus)
690 {
691 DWORD confidence = 0;
692
693 confidence = 0;
694 if (!(errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
695 confidence |= CERT_CONFIDENCE_SIG;
696 if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_VALID))
697 confidence |= CERT_CONFIDENCE_TIME;
698 if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_NESTED))
699 confidence |= CERT_CONFIDENCE_TIMENEST;
700 return confidence;
701 }
702
703 BOOL WINAPI SoftpubCheckCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
704 BOOL fCounterSignerChain, DWORD idxCounterSigner)
705 {
706 BOOL ret;
707
708 TRACE("(%p, %d, %d, %d)\n", data, idxSigner, fCounterSignerChain,
709 idxCounterSigner);
710
711 if (fCounterSignerChain)
712 {
713 FIXME("unimplemented for counter signers\n");
714 ret = FALSE;
715 }
716 else
717 {
718 PCERT_SIMPLE_CHAIN simpleChain =
719 data->pasSigners[idxSigner].pChainContext->rgpChain[0];
720 DWORD i;
721
722 ret = TRUE;
723 for (i = 0; i < simpleChain->cElement; i++)
724 {
725 /* Set confidence */
726 data->pasSigners[idxSigner].pasCertChain[i].dwConfidence =
727 WINTRUST_TrustStatusToConfidence(
728 simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus);
729 /* Set additional flags */
730 if (!(simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus &
731 CERT_TRUST_IS_UNTRUSTED_ROOT))
732 data->pasSigners[idxSigner].pasCertChain[i].fTrustedRoot = TRUE;
733 if (simpleChain->rgpElement[i]->TrustStatus.dwInfoStatus &
734 CERT_TRUST_IS_SELF_SIGNED)
735 data->pasSigners[idxSigner].pasCertChain[i].fSelfSigned = TRUE;
736 if (simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus &
737 CERT_TRUST_IS_CYCLIC)
738 data->pasSigners[idxSigner].pasCertChain[i].fIsCyclic = TRUE;
739 }
740 }
741 return ret;
742 }
743
744 static DWORD WINTRUST_TrustStatusToError(DWORD errorStatus)
745 {
746 DWORD error;
747
748 if (errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID)
749 error = TRUST_E_CERT_SIGNATURE;
750 else if (errorStatus & CERT_TRUST_IS_UNTRUSTED_ROOT)
751 error = CERT_E_UNTRUSTEDROOT;
752 else if (errorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
753 error = CERT_E_EXPIRED;
754 else if (errorStatus & CERT_TRUST_IS_NOT_TIME_NESTED)
755 error = CERT_E_VALIDITYPERIODNESTING;
756 else if (errorStatus & CERT_TRUST_IS_REVOKED)
757 error = CERT_E_REVOKED;
758 else if (errorStatus & CERT_TRUST_IS_OFFLINE_REVOCATION ||
759 errorStatus & CERT_TRUST_REVOCATION_STATUS_UNKNOWN)
760 error = CERT_E_REVOCATION_FAILURE;
761 else if (errorStatus & CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
762 error = CERT_E_WRONG_USAGE;
763 else if (errorStatus & CERT_TRUST_IS_CYCLIC)
764 error = CERT_E_CHAINING;
765 else if (errorStatus & CERT_TRUST_INVALID_EXTENSION)
766 error = CERT_E_CRITICAL;
767 else if (errorStatus & CERT_TRUST_INVALID_POLICY_CONSTRAINTS)
768 error = CERT_E_INVALID_POLICY;
769 else if (errorStatus & CERT_TRUST_INVALID_BASIC_CONSTRAINTS)
770 error = TRUST_E_BASIC_CONSTRAINTS;
771 else if (errorStatus & CERT_TRUST_INVALID_NAME_CONSTRAINTS ||
772 errorStatus & CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT ||
773 errorStatus & CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT ||
774 errorStatus & CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT ||
775 errorStatus & CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT)
776 error = CERT_E_INVALID_NAME;
777 else if (errorStatus & CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY)
778 error = CERT_E_INVALID_POLICY;
779 else if (errorStatus)
780 {
781 FIXME("unknown error status %08x\n", errorStatus);
782 error = TRUST_E_SYSTEM_ERROR;
783 }
784 else
785 error = S_OK;
786 return error;
787 }
788
789 static DWORD WINTRUST_CopyChain(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
790 {
791 DWORD err, i;
792 PCERT_SIMPLE_CHAIN simpleChain =
793 data->pasSigners[signerIdx].pChainContext->rgpChain[0];
794
795 data->pasSigners[signerIdx].pasCertChain[0].dwConfidence =
796 WINTRUST_TrustStatusToConfidence(
797 simpleChain->rgpElement[0]->TrustStatus.dwErrorStatus);
798 data->pasSigners[signerIdx].pasCertChain[0].pChainElement =
799 simpleChain->rgpElement[0];
800 err = ERROR_SUCCESS;
801 for (i = 1; !err && i < simpleChain->cElement; i++)
802 {
803 if (data->psPfns->pfnAddCert2Chain(data, signerIdx, FALSE, 0,
804 simpleChain->rgpElement[i]->pCertContext))
805 {
806 data->pasSigners[signerIdx].pasCertChain[i].pChainElement =
807 simpleChain->rgpElement[i];
808 data->pasSigners[signerIdx].pasCertChain[i].dwConfidence =
809 WINTRUST_TrustStatusToConfidence(
810 simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus);
811 }
812 else
813 err = GetLastError();
814 }
815 data->pasSigners[signerIdx].pasCertChain[simpleChain->cElement - 1].dwError
816 = WINTRUST_TrustStatusToError(
817 simpleChain->rgpElement[simpleChain->cElement - 1]->
818 TrustStatus.dwErrorStatus);
819 return err;
820 }
821
822 static void WINTRUST_CreateChainPolicyCreateInfo(
823 const CRYPT_PROVIDER_DATA *data, PWTD_GENERIC_CHAIN_POLICY_CREATE_INFO info,
824 PCERT_CHAIN_PARA chainPara)
825 {
826 chainPara->cbSize = sizeof(CERT_CHAIN_PARA);
827 if (data->pRequestUsage)
828 chainPara->RequestedUsage = *data->pRequestUsage;
829 else
830 {
831 chainPara->RequestedUsage.dwType = 0;
832 chainPara->RequestedUsage.Usage.cUsageIdentifier = 0;
833 }
834 info->u.cbSize = sizeof(WTD_GENERIC_CHAIN_POLICY_CREATE_INFO);
835 info->hChainEngine = NULL;
836 info->pChainPara = chainPara;
837 if (data->dwProvFlags & CPD_REVOCATION_CHECK_END_CERT)
838 info->dwFlags = CERT_CHAIN_REVOCATION_CHECK_END_CERT;
839 else if (data->dwProvFlags & CPD_REVOCATION_CHECK_CHAIN)
840 info->dwFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
841 else if (data->dwProvFlags & CPD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT)
842 info->dwFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
843 else
844 info->dwFlags = 0;
845 info->pvReserved = NULL;
846 }
847
848 static DWORD WINTRUST_CreateChainForSigner(CRYPT_PROVIDER_DATA *data,
849 DWORD signer, PWTD_GENERIC_CHAIN_POLICY_CREATE_INFO createInfo,
850 PCERT_CHAIN_PARA chainPara)
851 {
852 DWORD err = ERROR_SUCCESS;
853 HCERTSTORE store = NULL;
854
855 if (data->chStores)
856 {
857 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
858 CERT_STORE_CREATE_NEW_FLAG, NULL);
859 if (store)
860 {
861 DWORD i;
862
863 for (i = 0; i < data->chStores; i++)
864 CertAddStoreToCollection(store, data->pahStores[i], 0, 0);
865 }
866 else
867 err = GetLastError();
868 }
869 if (!err)
870 {
871 /* Expect the end certificate for each signer to be the only cert in
872 * the chain:
873 */
874 if (data->pasSigners[signer].csCertChain)
875 {
876 BOOL ret;
877
878 /* Create a certificate chain for each signer */
879 ret = CertGetCertificateChain(createInfo->hChainEngine,
880 data->pasSigners[signer].pasCertChain[0].pCert,
881 &data->pasSigners[signer].sftVerifyAsOf, store,
882 chainPara, createInfo->dwFlags, createInfo->pvReserved,
883 &data->pasSigners[signer].pChainContext);
884 if (ret)
885 {
886 if (data->pasSigners[signer].pChainContext->cChain != 1)
887 {
888 FIXME("unimplemented for more than 1 simple chain\n");
889 err = E_NOTIMPL;
890 }
891 else
892 {
893 if (!(err = WINTRUST_CopyChain(data, signer)))
894 {
895 if (data->psPfns->pfnCertCheckPolicy)
896 {
897 ret = data->psPfns->pfnCertCheckPolicy(data, signer,
898 FALSE, 0);
899 if (!ret)
900 err = GetLastError();
901 }
902 else
903 TRACE(
904 "no cert check policy, skipping policy check\n");
905 }
906 }
907 }
908 else
909 err = GetLastError();
910 }
911 CertCloseStore(store, 0);
912 }
913 return err;
914 }
915
916 HRESULT WINAPI WintrustCertificateTrust(CRYPT_PROVIDER_DATA *data)
917 {
918 DWORD err;
919
920 TRACE("(%p)\n", data);
921
922 if (!data->csSigners)
923 err = TRUST_E_NOSIGNATURE;
924 else
925 {
926 DWORD i;
927 WTD_GENERIC_CHAIN_POLICY_CREATE_INFO createInfo;
928 CERT_CHAIN_PARA chainPara;
929
930 WINTRUST_CreateChainPolicyCreateInfo(data, &createInfo, &chainPara);
931 err = ERROR_SUCCESS;
932 for (i = 0; !err && i < data->csSigners; i++)
933 err = WINTRUST_CreateChainForSigner(data, i, &createInfo,
934 &chainPara);
935 }
936 if (err)
937 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = err;
938 TRACE("returning %d (%08x)\n", !err ? S_OK : S_FALSE,
939 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
940 return !err ? S_OK : S_FALSE;
941 }
942
943 HRESULT WINAPI GenericChainCertificateTrust(CRYPT_PROVIDER_DATA *data)
944 {
945 DWORD err;
946 WTD_GENERIC_CHAIN_POLICY_DATA *policyData =
947 data->pWintrustData->pPolicyCallbackData;
948
949 TRACE("(%p)\n", data);
950
951 if (policyData && policyData->u.cbSize !=
952 sizeof(WTD_GENERIC_CHAIN_POLICY_CREATE_INFO))
953 {
954 err = ERROR_INVALID_PARAMETER;
955 goto end;
956 }
957 if (!data->csSigners)
958 err = TRUST_E_NOSIGNATURE;
959 else
960 {
961 DWORD i;
962 WTD_GENERIC_CHAIN_POLICY_CREATE_INFO createInfo, *pCreateInfo;
963 CERT_CHAIN_PARA chainPara, *pChainPara;
964
965 if (policyData)
966 {
967 pCreateInfo = policyData->pSignerChainInfo;
968 pChainPara = pCreateInfo->pChainPara;
969 }
970 else
971 {
972 WINTRUST_CreateChainPolicyCreateInfo(data, &createInfo, &chainPara);
973 pChainPara = &chainPara;
974 pCreateInfo = &createInfo;
975 }
976 err = ERROR_SUCCESS;
977 for (i = 0; !err && i < data->csSigners; i++)
978 err = WINTRUST_CreateChainForSigner(data, i, pCreateInfo,
979 pChainPara);
980 }
981
982 end:
983 if (err)
984 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = err;
985 TRACE("returning %d (%08x)\n", !err ? S_OK : S_FALSE,
986 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
987 return !err ? S_OK : S_FALSE;
988 }
989
990 HRESULT WINAPI SoftpubAuthenticode(CRYPT_PROVIDER_DATA *data)
991 {
992 BOOL ret;
993 CERT_CHAIN_POLICY_STATUS policyStatus = { sizeof(policyStatus), 0 };
994
995 TRACE("(%p)\n", data);
996
997 if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
998 FIXME("unimplemented for UI choice %d\n",
999 data->pWintrustData->dwUIChoice);
1000 if (!data->csSigners)
1001 {
1002 ret = FALSE;
1003 policyStatus.dwError = TRUST_E_NOSIGNATURE;
1004 }
1005 else
1006 {
1007 DWORD i;
1008
1009 ret = TRUE;
1010 for (i = 0; ret && i < data->csSigners; i++)
1011 {
1012 BYTE hash[20];
1013 DWORD size = sizeof(hash);
1014
1015 /* First make sure cert isn't disallowed */
1016 if ((ret = CertGetCertificateContextProperty(
1017 data->pasSigners[i].pasCertChain[0].pCert,
1018 CERT_SIGNATURE_HASH_PROP_ID, hash, &size)))
1019 {
1020 static const WCHAR disallowedW[] =
1021 { 'D','i','s','a','l','l','o','w','e','d',0 };
1022 HCERTSTORE disallowed = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
1023 X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER,
1024 disallowedW);
1025
1026 if (disallowed)
1027 {
1028 PCCERT_CONTEXT found = CertFindCertificateInStore(
1029 disallowed, X509_ASN_ENCODING, 0, CERT_FIND_SIGNATURE_HASH,
1030 hash, NULL);
1031
1032 if (found)
1033 {
1034 /* Disallowed! Can't verify it. */
1035 policyStatus.dwError = TRUST_E_SUBJECT_NOT_TRUSTED;
1036 ret = FALSE;
1037 CertFreeCertificateContext(found);
1038 }
1039 CertCloseStore(disallowed, 0);
1040 }
1041 }
1042 if (ret)
1043 {
1044 CERT_CHAIN_POLICY_PARA policyPara = { sizeof(policyPara), 0 };
1045
1046 if (data->dwRegPolicySettings & WTPF_TRUSTTEST)
1047 policyPara.dwFlags |= CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG;
1048 if (data->dwRegPolicySettings & WTPF_TESTCANBEVALID)
1049 policyPara.dwFlags |= CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG;
1050 if (data->dwRegPolicySettings & WTPF_IGNOREEXPIRATION)
1051 policyPara.dwFlags |=
1052 CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG |
1053 CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG |
1054 CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG;
1055 if (data->dwRegPolicySettings & WTPF_IGNOREREVOKATION)
1056 policyPara.dwFlags |=
1057 CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG |
1058 CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG |
1059 CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG |
1060 CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG;
1061 CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_AUTHENTICODE,
1062 data->pasSigners[i].pChainContext, &policyPara, &policyStatus);
1063 if (policyStatus.dwError != NO_ERROR)
1064 ret = FALSE;
1065 }
1066 }
1067 }
1068 if (!ret)
1069 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV] =
1070 policyStatus.dwError;
1071 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
1072 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV]);
1073 return ret ? S_OK : S_FALSE;
1074 }
1075
1076 static HRESULT WINAPI WINTRUST_DefaultPolicy(CRYPT_PROVIDER_DATA *pProvData,
1077 DWORD dwStepError, DWORD dwRegPolicySettings, DWORD cSigner,
1078 PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO rgpSigner, void *pvPolicyArg)
1079 {
1080 DWORD i;
1081 CERT_CHAIN_POLICY_STATUS policyStatus = { sizeof(policyStatus), 0 };
1082
1083 for (i = 0; !policyStatus.dwError && i < cSigner; i++)
1084 {
1085 CERT_CHAIN_POLICY_PARA policyPara = { sizeof(policyPara), 0 };
1086
1087 if (dwRegPolicySettings & WTPF_IGNOREEXPIRATION)
1088 policyPara.dwFlags |=
1089 CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG |
1090 CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG |
1091 CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG;
1092 if (dwRegPolicySettings & WTPF_IGNOREREVOKATION)
1093 policyPara.dwFlags |=
1094 CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG |
1095 CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG |
1096 CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG |
1097 CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG;
1098 CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE,
1099 rgpSigner[i].pChainContext, &policyPara, &policyStatus);
1100 }
1101 return policyStatus.dwError;
1102 }
1103
1104 HRESULT WINAPI GenericChainFinalProv(CRYPT_PROVIDER_DATA *data)
1105 {
1106 HRESULT err = NO_ERROR; /* not a typo, MS confused the types */
1107 WTD_GENERIC_CHAIN_POLICY_DATA *policyData =
1108 data->pWintrustData->pPolicyCallbackData;
1109
1110 TRACE("(%p)\n", data);
1111
1112 if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
1113 FIXME("unimplemented for UI choice %d\n",
1114 data->pWintrustData->dwUIChoice);
1115 if (!data->csSigners)
1116 err = TRUST_E_NOSIGNATURE;
1117 else
1118 {
1119 PFN_WTD_GENERIC_CHAIN_POLICY_CALLBACK policyCallback;
1120 void *policyArg;
1121 WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO *signers = NULL;
1122
1123 if (policyData)
1124 {
1125 policyCallback = policyData->pfnPolicyCallback;
1126 policyArg = policyData->pvPolicyArg;
1127 }
1128 else
1129 {
1130 policyCallback = WINTRUST_DefaultPolicy;
1131 policyArg = NULL;
1132 }
1133 if (data->csSigners)
1134 {
1135 DWORD i;
1136
1137 signers = data->psPfns->pfnAlloc(
1138 data->csSigners * sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO));
1139 if (signers)
1140 {
1141 for (i = 0; i < data->csSigners; i++)
1142 {
1143 signers[i].u.cbSize =
1144 sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO);
1145 signers[i].pChainContext =
1146 data->pasSigners[i].pChainContext;
1147 signers[i].dwSignerType = data->pasSigners[i].dwSignerType;
1148 signers[i].pMsgSignerInfo = data->pasSigners[i].psSigner;
1149 signers[i].dwError = data->pasSigners[i].dwError;
1150 if (data->pasSigners[i].csCounterSigners)
1151 FIXME("unimplemented for counter signers\n");
1152 signers[i].cCounterSigner = 0;
1153 signers[i].rgpCounterSigner = NULL;
1154 }
1155 }
1156 else
1157 err = ERROR_OUTOFMEMORY;
1158 }
1159 if (err == NO_ERROR)
1160 err = policyCallback(data, TRUSTERROR_STEP_FINAL_POLICYPROV,
1161 data->dwRegPolicySettings, data->csSigners, signers, policyArg);
1162 data->psPfns->pfnFree(signers);
1163 }
1164 if (err != NO_ERROR)
1165 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV] = err;
1166 TRACE("returning %d (%08x)\n", err == NO_ERROR ? S_OK : S_FALSE,
1167 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV]);
1168 return err == NO_ERROR ? S_OK : S_FALSE;
1169 }
1170
1171 HRESULT WINAPI SoftpubCleanup(CRYPT_PROVIDER_DATA *data)
1172 {
1173 DWORD i, j;
1174
1175 for (i = 0; i < data->csSigners; i++)
1176 {
1177 for (j = 0; j < data->pasSigners[i].csCertChain; j++)
1178 CertFreeCertificateContext(data->pasSigners[i].pasCertChain[j].pCert);
1179 data->psPfns->pfnFree(data->pasSigners[i].pasCertChain);
1180 data->psPfns->pfnFree(data->pasSigners[i].psSigner);
1181 CertFreeCertificateChain(data->pasSigners[i].pChainContext);
1182 }
1183 data->psPfns->pfnFree(data->pasSigners);
1184
1185 for (i = 0; i < data->chStores; i++)
1186 CertCloseStore(data->pahStores[i], 0);
1187 data->psPfns->pfnFree(data->pahStores);
1188
1189 if (data->u.pPDSip)
1190 {
1191 data->psPfns->pfnFree(data->u.pPDSip->pSip);
1192 data->psPfns->pfnFree(data->u.pPDSip->pCATSip);
1193 data->psPfns->pfnFree(data->u.pPDSip->psSipSubjectInfo);
1194 data->psPfns->pfnFree(data->u.pPDSip->psSipCATSubjectInfo);
1195 data->psPfns->pfnFree(data->u.pPDSip->psIndirectData);
1196 }
1197
1198 CryptMsgClose(data->hMsg);
1199
1200 if (data->fOpenedFile &&
1201 data->pWintrustData->dwUnionChoice == WTD_CHOICE_FILE &&
1202 data->pWintrustData->u.pFile)
1203 CloseHandle(data->pWintrustData->u.pFile->hFile);
1204
1205 return S_OK;
1206 }
1207
1208 HRESULT WINAPI HTTPSCertificateTrust(CRYPT_PROVIDER_DATA *data)
1209 {
1210 FIXME("(%p)\n", data);
1211 return S_OK;
1212 }
1213
1214 HRESULT WINAPI HTTPSFinalProv(CRYPT_PROVIDER_DATA *data)
1215 {
1216 FIXME("(%p)\n", data);
1217 return S_OK;
1218 }