push 573c111636dcd80fa61914ac833187ced6019cb7
[wine/hacks.git] / dlls / wintrust / softpub.c
blob9c79fa8bcd3a8cd363e3e3b94249102deb801cc8
1 /*
2 * Copyright 2007 Juan Lang
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.
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.
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
18 #include <stdarg.h>
20 #define NONAMELESSUNION
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wintrust.h"
25 #include "mssip.h"
26 #include "softpub.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
31 HRESULT WINAPI SoftpubDefCertInit(CRYPT_PROVIDER_DATA *data)
33 HRESULT ret = S_FALSE;
35 TRACE("(%p)\n", data);
37 if (data->padwTrustStepErrors &&
38 !data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT])
39 ret = S_OK;
40 TRACE("returning %08x\n", ret);
41 return ret;
44 HRESULT WINAPI SoftpubInitialize(CRYPT_PROVIDER_DATA *data)
46 HRESULT ret = S_FALSE;
48 TRACE("(%p)\n", data);
50 if (data->padwTrustStepErrors &&
51 !data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT])
52 ret = S_OK;
53 TRACE("returning %08x\n", ret);
54 return ret;
57 /* Assumes data->pWintrustData->u.pFile exists. Makes sure a file handle is
58 * open for the file.
60 static BOOL SOFTPUB_OpenFile(CRYPT_PROVIDER_DATA *data)
62 BOOL ret = TRUE;
64 /* PSDK implies that all values should be initialized to NULL, so callers
65 * typically have hFile as NULL rather than INVALID_HANDLE_VALUE. Check
66 * for both.
68 if (!data->pWintrustData->u.pFile->hFile ||
69 data->pWintrustData->u.pFile->hFile == INVALID_HANDLE_VALUE)
71 data->pWintrustData->u.pFile->hFile =
72 CreateFileW(data->pWintrustData->u.pFile->pcwszFilePath, GENERIC_READ,
73 FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
74 if (data->pWintrustData->u.pFile->hFile != INVALID_HANDLE_VALUE)
75 data->fOpenedFile = TRUE;
76 else
77 ret = FALSE;
79 if (ret)
80 GetFileTime(data->pWintrustData->u.pFile->hFile, &data->sftSystemTime,
81 NULL, NULL);
82 TRACE("returning %d\n", ret);
83 return ret;
86 /* Assumes data->pWintrustData->u.pFile exists. Sets data->pPDSip->gSubject to
87 * the file's subject GUID.
89 static BOOL SOFTPUB_GetFileSubject(CRYPT_PROVIDER_DATA *data)
91 BOOL ret;
93 if (!WVT_ISINSTRUCT(WINTRUST_FILE_INFO,
94 data->pWintrustData->u.pFile->cbStruct, pgKnownSubject) ||
95 !data->pWintrustData->u.pFile->pgKnownSubject)
97 ret = CryptSIPRetrieveSubjectGuid(
98 data->pWintrustData->u.pFile->pcwszFilePath,
99 data->pWintrustData->u.pFile->hFile,
100 &data->u.pPDSip->gSubject);
102 else
104 data->u.pPDSip->gSubject = *data->pWintrustData->u.pFile->pgKnownSubject;
105 ret = TRUE;
107 TRACE("returning %d\n", ret);
108 return ret;
111 /* Assumes data->u.pPDSip exists, and its gSubject member set.
112 * Allocates data->u.pPDSip->pSip and loads it, if possible.
114 static BOOL SOFTPUB_GetSIP(CRYPT_PROVIDER_DATA *data)
116 BOOL ret;
118 data->u.pPDSip->pSip = data->psPfns->pfnAlloc(sizeof(SIP_DISPATCH_INFO));
119 if (data->u.pPDSip->pSip)
120 ret = CryptSIPLoad(&data->u.pPDSip->gSubject, 0, data->u.pPDSip->pSip);
121 else
123 SetLastError(ERROR_OUTOFMEMORY);
124 ret = FALSE;
126 TRACE("returning %d\n", ret);
127 return ret;
130 /* Assumes data->u.pPDSip has been loaded, and data->u.pPDSip->pSip allocated.
131 * Calls data->u.pPDSip->pSip->pfGet to construct data->hMsg.
133 static BOOL SOFTPUB_GetMessageFromFile(CRYPT_PROVIDER_DATA *data, HANDLE file,
134 LPCWSTR filePath)
136 BOOL ret;
137 LPBYTE buf = NULL;
138 DWORD size = 0;
140 data->u.pPDSip->psSipSubjectInfo =
141 data->psPfns->pfnAlloc(sizeof(SIP_SUBJECTINFO));
142 if (!data->u.pPDSip->psSipSubjectInfo)
144 SetLastError(ERROR_OUTOFMEMORY);
145 return FALSE;
148 data->u.pPDSip->psSipSubjectInfo->cbSize = sizeof(SIP_SUBJECTINFO);
149 data->u.pPDSip->psSipSubjectInfo->pgSubjectType = &data->u.pPDSip->gSubject;
150 data->u.pPDSip->psSipSubjectInfo->hFile = file;
151 data->u.pPDSip->psSipSubjectInfo->pwsFileName = filePath;
152 data->u.pPDSip->psSipSubjectInfo->hProv = data->hProv;
153 ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo,
154 &data->dwEncoding, 0, &size, 0);
155 if (!ret)
157 SetLastError(TRUST_E_NOSIGNATURE);
158 return FALSE;
161 buf = data->psPfns->pfnAlloc(size);
162 if (!buf)
164 SetLastError(ERROR_OUTOFMEMORY);
165 return FALSE;
168 ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo,
169 &data->dwEncoding, 0, &size, buf);
170 if (ret)
172 data->hMsg = CryptMsgOpenToDecode(data->dwEncoding, 0, 0, data->hProv,
173 NULL, NULL);
174 if (data->hMsg)
175 ret = CryptMsgUpdate(data->hMsg, buf, size, TRUE);
178 data->psPfns->pfnFree(buf);
179 TRACE("returning %d\n", ret);
180 return ret;
183 static BOOL SOFTPUB_CreateStoreFromMessage(CRYPT_PROVIDER_DATA *data)
185 BOOL ret = FALSE;
186 HCERTSTORE store;
188 store = CertOpenStore(CERT_STORE_PROV_MSG, data->dwEncoding,
189 data->hProv, CERT_STORE_NO_CRYPT_RELEASE_FLAG, data->hMsg);
190 if (store)
192 ret = data->psPfns->pfnAddStore2Chain(data, store);
193 CertCloseStore(store, 0);
195 TRACE("returning %d\n", ret);
196 return ret;
199 static DWORD SOFTPUB_DecodeInnerContent(CRYPT_PROVIDER_DATA *data)
201 BOOL ret;
202 DWORD size;
203 LPSTR oid = NULL;
204 LPBYTE buf = NULL;
206 ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL,
207 &size);
208 if (!ret)
209 goto error;
210 oid = data->psPfns->pfnAlloc(size);
211 if (!oid)
213 SetLastError(ERROR_OUTOFMEMORY);
214 ret = FALSE;
215 goto error;
217 ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, oid,
218 &size);
219 if (!ret)
220 goto error;
221 ret = CryptMsgGetParam(data->hMsg, CMSG_CONTENT_PARAM, 0, NULL, &size);
222 if (!ret)
223 goto error;
224 buf = data->psPfns->pfnAlloc(size);
225 if (!buf)
227 SetLastError(ERROR_OUTOFMEMORY);
228 ret = FALSE;
229 goto error;
231 ret = CryptMsgGetParam(data->hMsg, CMSG_CONTENT_PARAM, 0, buf, &size);
232 if (!ret)
233 goto error;
234 ret = CryptDecodeObject(data->dwEncoding, oid, buf, size, 0, NULL, &size);
235 if (!ret)
236 goto error;
237 data->u.pPDSip->psIndirectData = data->psPfns->pfnAlloc(size);
238 if (!data->u.pPDSip->psIndirectData)
240 SetLastError(ERROR_OUTOFMEMORY);
241 ret = FALSE;
242 goto error;
244 ret = CryptDecodeObject(data->dwEncoding, oid, buf, size, 0,
245 data->u.pPDSip->psIndirectData, &size);
247 error:
248 TRACE("returning %d\n", ret);
249 data->psPfns->pfnFree(oid);
250 data->psPfns->pfnFree(buf);
251 return ret;
254 static BOOL SOFTPUB_LoadCertMessage(CRYPT_PROVIDER_DATA *data)
256 BOOL ret;
258 if (data->pWintrustData->u.pCert &&
259 data->pWintrustData->u.pCert->cbStruct == sizeof(WINTRUST_CERT_INFO))
261 if (data->psPfns)
263 CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
264 DWORD i;
266 /* Add a signer with nothing but the time to verify, so we can
267 * add a cert to it
269 if (data->pWintrustData->u.pCert->psftVerifyAsOf)
270 data->sftSystemTime = signer.sftVerifyAsOf;
271 else
273 SYSTEMTIME sysTime;
275 GetSystemTime(&sysTime);
276 SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
278 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
279 if (ret)
281 ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
282 data->pWintrustData->u.pCert->psCertContext);
283 for (i = 0; ret && i < data->pWintrustData->u.pCert->chStores;
284 i++)
285 ret = data->psPfns->pfnAddStore2Chain(data,
286 data->pWintrustData->u.pCert->pahStores[i]);
289 else
291 /* Do nothing!? See the tests */
292 ret = TRUE;
295 else
297 SetLastError(ERROR_INVALID_PARAMETER);
298 ret = FALSE;
300 return ret;
303 static BOOL SOFTPUB_LoadFileMessage(CRYPT_PROVIDER_DATA *data)
305 BOOL ret;
307 if (!data->pWintrustData->u.pFile)
309 SetLastError(ERROR_INVALID_PARAMETER);
310 ret = FALSE;
311 goto error;
313 ret = SOFTPUB_OpenFile(data);
314 if (!ret)
315 goto error;
316 ret = SOFTPUB_GetFileSubject(data);
317 if (!ret)
318 goto error;
319 ret = SOFTPUB_GetSIP(data);
320 if (!ret)
321 goto error;
322 ret = SOFTPUB_GetMessageFromFile(data, data->pWintrustData->u.pFile->hFile,
323 data->pWintrustData->u.pFile->pcwszFilePath);
324 if (!ret)
325 goto error;
326 ret = SOFTPUB_CreateStoreFromMessage(data);
327 if (!ret)
328 goto error;
329 ret = SOFTPUB_DecodeInnerContent(data);
330 error:
331 return ret;
334 static BOOL SOFTPUB_LoadCatalogMessage(CRYPT_PROVIDER_DATA *data)
336 BOOL ret;
337 HANDLE catalog = INVALID_HANDLE_VALUE;
339 if (!data->pWintrustData->u.pCatalog)
341 SetLastError(ERROR_INVALID_PARAMETER);
342 return FALSE;
344 catalog = CreateFileW(data->pWintrustData->u.pCatalog->pcwszCatalogFilePath,
345 GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
346 NULL);
347 if (catalog == INVALID_HANDLE_VALUE)
348 return FALSE;
349 ret = CryptSIPRetrieveSubjectGuid(
350 data->pWintrustData->u.pCatalog->pcwszCatalogFilePath, catalog,
351 &data->u.pPDSip->gSubject);
352 if (!ret)
353 goto error;
354 ret = SOFTPUB_GetSIP(data);
355 if (!ret)
356 goto error;
357 ret = SOFTPUB_GetMessageFromFile(data, catalog,
358 data->pWintrustData->u.pCatalog->pcwszCatalogFilePath);
359 if (!ret)
360 goto error;
361 ret = SOFTPUB_CreateStoreFromMessage(data);
362 if (!ret)
363 goto error;
364 ret = SOFTPUB_DecodeInnerContent(data);
365 /* FIXME: this loads the catalog file, but doesn't validate the member. */
366 error:
367 CloseHandle(catalog);
368 return ret;
371 HRESULT WINAPI SoftpubLoadMessage(CRYPT_PROVIDER_DATA *data)
373 BOOL ret;
375 TRACE("(%p)\n", data);
377 if (!data->padwTrustStepErrors)
378 return S_FALSE;
380 switch (data->pWintrustData->dwUnionChoice)
382 case WTD_CHOICE_CERT:
383 ret = SOFTPUB_LoadCertMessage(data);
384 break;
385 case WTD_CHOICE_FILE:
386 ret = SOFTPUB_LoadFileMessage(data);
387 break;
388 case WTD_CHOICE_CATALOG:
389 ret = SOFTPUB_LoadCatalogMessage(data);
390 break;
391 default:
392 FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
393 SetLastError(ERROR_INVALID_PARAMETER);
394 ret = FALSE;
397 if (!ret)
398 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
399 GetLastError();
400 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
401 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
402 return ret ? S_OK : S_FALSE;
405 static CMSG_SIGNER_INFO *WINTRUST_GetSigner(CRYPT_PROVIDER_DATA *data,
406 DWORD signerIdx)
408 BOOL ret;
409 CMSG_SIGNER_INFO *signerInfo = NULL;
410 DWORD size;
412 ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_INFO_PARAM, signerIdx,
413 NULL, &size);
414 if (ret)
416 signerInfo = data->psPfns->pfnAlloc(size);
417 if (signerInfo)
419 ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_INFO_PARAM,
420 signerIdx, signerInfo, &size);
421 if (!ret)
423 data->psPfns->pfnFree(signerInfo);
424 signerInfo = NULL;
427 else
428 SetLastError(ERROR_OUTOFMEMORY);
430 return signerInfo;
433 static BOOL WINTRUST_SaveSigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
435 BOOL ret;
436 CMSG_SIGNER_INFO *signerInfo = WINTRUST_GetSigner(data, signerIdx);
438 if (signerInfo)
440 CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
442 sgnr.psSigner = signerInfo;
443 sgnr.sftVerifyAsOf = data->sftSystemTime;
444 ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, signerIdx, &sgnr);
446 else
447 ret = FALSE;
448 return ret;
451 static CERT_INFO *WINTRUST_GetSignerCertInfo(CRYPT_PROVIDER_DATA *data,
452 DWORD signerIdx)
454 BOOL ret;
455 CERT_INFO *certInfo = NULL;
456 DWORD size;
458 ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_CERT_INFO_PARAM, signerIdx,
459 NULL, &size);
460 if (ret)
462 certInfo = data->psPfns->pfnAlloc(size);
463 if (certInfo)
465 ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_CERT_INFO_PARAM,
466 signerIdx, certInfo, &size);
467 if (!ret)
469 data->psPfns->pfnFree(certInfo);
470 certInfo = NULL;
473 else
474 SetLastError(ERROR_OUTOFMEMORY);
476 return certInfo;
479 static BOOL WINTRUST_VerifySigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
481 BOOL ret;
482 CERT_INFO *certInfo = WINTRUST_GetSignerCertInfo(data, signerIdx);
484 if (certInfo)
486 PCCERT_CONTEXT subject = CertGetSubjectCertificateFromStore(
487 data->pahStores[0], data->dwEncoding, certInfo);
489 if (subject)
491 CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para = { sizeof(para), 0,
492 signerIdx, CMSG_VERIFY_SIGNER_CERT, (LPVOID)subject };
494 ret = CryptMsgControl(data->hMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE_EX,
495 &para);
496 if (!ret)
497 SetLastError(TRUST_E_CERT_SIGNATURE);
498 else
499 data->psPfns->pfnAddCert2Chain(data, signerIdx, FALSE, 0,
500 subject);
501 CertFreeCertificateContext(subject);
503 else
505 SetLastError(TRUST_E_NO_SIGNER_CERT);
506 ret = FALSE;
508 data->psPfns->pfnFree(certInfo);
510 else
511 ret = FALSE;
512 return ret;
515 HRESULT WINAPI SoftpubLoadSignature(CRYPT_PROVIDER_DATA *data)
517 BOOL ret;
519 TRACE("(%p)\n", data);
521 if (!data->padwTrustStepErrors)
522 return S_FALSE;
524 if (data->hMsg)
526 DWORD signerCount, size;
528 size = sizeof(signerCount);
529 ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_COUNT_PARAM, 0,
530 &signerCount, &size);
531 if (ret)
533 DWORD i;
535 for (i = 0; ret && i < signerCount; i++)
537 if ((ret = WINTRUST_SaveSigner(data, i)))
538 ret = WINTRUST_VerifySigner(data, i);
541 else
542 SetLastError(TRUST_E_NOSIGNATURE);
544 else
545 ret = TRUE;
546 if (!ret)
547 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] =
548 GetLastError();
549 return ret ? S_OK : S_FALSE;
552 static DWORD WINTRUST_TrustStatusToConfidence(DWORD errorStatus)
554 DWORD confidence = 0;
556 confidence = 0;
557 if (!(errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
558 confidence |= CERT_CONFIDENCE_SIG;
559 if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_VALID))
560 confidence |= CERT_CONFIDENCE_TIME;
561 if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_NESTED))
562 confidence |= CERT_CONFIDENCE_TIMENEST;
563 return confidence;
566 BOOL WINAPI SoftpubCheckCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
567 BOOL fCounterSignerChain, DWORD idxCounterSigner)
569 BOOL ret;
571 TRACE("(%p, %d, %d, %d)\n", data, idxSigner, fCounterSignerChain,
572 idxCounterSigner);
574 if (fCounterSignerChain)
576 FIXME("unimplemented for counter signers\n");
577 ret = FALSE;
579 else
581 PCERT_SIMPLE_CHAIN simpleChain =
582 data->pasSigners[idxSigner].pChainContext->rgpChain[0];
583 DWORD i;
585 ret = TRUE;
586 for (i = 0; i < simpleChain->cElement; i++)
588 /* Set confidence */
589 data->pasSigners[idxSigner].pasCertChain[i].dwConfidence =
590 WINTRUST_TrustStatusToConfidence(
591 simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus);
592 /* Set additional flags */
593 if (!(simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus &
594 CERT_TRUST_IS_UNTRUSTED_ROOT))
595 data->pasSigners[idxSigner].pasCertChain[i].fTrustedRoot = TRUE;
596 if (simpleChain->rgpElement[i]->TrustStatus.dwInfoStatus &
597 CERT_TRUST_IS_SELF_SIGNED)
598 data->pasSigners[idxSigner].pasCertChain[i].fSelfSigned = TRUE;
599 if (simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus &
600 CERT_TRUST_IS_CYCLIC)
601 data->pasSigners[idxSigner].pasCertChain[i].fIsCyclic = TRUE;
604 return ret;
607 static DWORD WINTRUST_TrustStatusToError(DWORD errorStatus)
609 DWORD error;
611 if (errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID)
612 error = TRUST_E_CERT_SIGNATURE;
613 else if (errorStatus & CERT_TRUST_IS_UNTRUSTED_ROOT)
614 error = CERT_E_UNTRUSTEDROOT;
615 else if (errorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
616 error = CERT_E_EXPIRED;
617 else if (errorStatus & CERT_TRUST_IS_NOT_TIME_NESTED)
618 error = CERT_E_VALIDITYPERIODNESTING;
619 else if (errorStatus & CERT_TRUST_IS_REVOKED)
620 error = CERT_E_REVOKED;
621 else if (errorStatus & CERT_TRUST_IS_OFFLINE_REVOCATION ||
622 errorStatus & CERT_TRUST_REVOCATION_STATUS_UNKNOWN)
623 error = CERT_E_REVOCATION_FAILURE;
624 else if (errorStatus & CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
625 error = CERT_E_WRONG_USAGE;
626 else if (errorStatus & CERT_TRUST_IS_CYCLIC)
627 error = CERT_E_CHAINING;
628 else if (errorStatus & CERT_TRUST_INVALID_EXTENSION)
629 error = CERT_E_CRITICAL;
630 else if (errorStatus & CERT_TRUST_INVALID_POLICY_CONSTRAINTS)
631 error = CERT_E_INVALID_POLICY;
632 else if (errorStatus & CERT_TRUST_INVALID_BASIC_CONSTRAINTS)
633 error = TRUST_E_BASIC_CONSTRAINTS;
634 else if (errorStatus & CERT_TRUST_INVALID_NAME_CONSTRAINTS ||
635 errorStatus & CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT ||
636 errorStatus & CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT ||
637 errorStatus & CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT ||
638 errorStatus & CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT)
639 error = CERT_E_INVALID_NAME;
640 else if (errorStatus & CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY)
641 error = CERT_E_INVALID_POLICY;
642 else if (errorStatus)
644 FIXME("unknown error status %08x\n", errorStatus);
645 error = TRUST_E_SYSTEM_ERROR;
647 else
648 error = S_OK;
649 return error;
652 static BOOL WINTRUST_CopyChain(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
654 BOOL ret;
655 PCERT_SIMPLE_CHAIN simpleChain =
656 data->pasSigners[signerIdx].pChainContext->rgpChain[0];
657 DWORD i;
659 data->pasSigners[signerIdx].pasCertChain[0].dwConfidence =
660 WINTRUST_TrustStatusToConfidence(
661 simpleChain->rgpElement[0]->TrustStatus.dwErrorStatus);
662 data->pasSigners[signerIdx].pasCertChain[0].pChainElement =
663 simpleChain->rgpElement[0];
664 ret = TRUE;
665 for (i = 1; ret && i < simpleChain->cElement; i++)
667 ret = data->psPfns->pfnAddCert2Chain(data, signerIdx, FALSE, 0,
668 simpleChain->rgpElement[i]->pCertContext);
669 if (ret)
671 data->pasSigners[signerIdx].pasCertChain[i].pChainElement =
672 simpleChain->rgpElement[i];
673 data->pasSigners[signerIdx].pasCertChain[i].dwConfidence =
674 WINTRUST_TrustStatusToConfidence(
675 simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus);
678 data->pasSigners[signerIdx].pasCertChain[simpleChain->cElement - 1].dwError
679 = WINTRUST_TrustStatusToError(
680 simpleChain->rgpElement[simpleChain->cElement - 1]->
681 TrustStatus.dwErrorStatus);
682 return ret;
685 static void WINTRUST_CreateChainPolicyCreateInfo(
686 const CRYPT_PROVIDER_DATA *data, PWTD_GENERIC_CHAIN_POLICY_CREATE_INFO info,
687 PCERT_CHAIN_PARA chainPara)
689 chainPara->cbSize = sizeof(CERT_CHAIN_PARA);
690 if (data->pRequestUsage)
691 chainPara->RequestedUsage = *data->pRequestUsage;
692 else
694 chainPara->RequestedUsage.dwType = 0;
695 chainPara->RequestedUsage.Usage.cUsageIdentifier = 0;
697 info->u.cbSize = sizeof(WTD_GENERIC_CHAIN_POLICY_CREATE_INFO);
698 info->hChainEngine = NULL;
699 info->pChainPara = chainPara;
700 if (data->dwProvFlags & CPD_REVOCATION_CHECK_END_CERT)
701 info->dwFlags = CERT_CHAIN_REVOCATION_CHECK_END_CERT;
702 else if (data->dwProvFlags & CPD_REVOCATION_CHECK_CHAIN)
703 info->dwFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
704 else if (data->dwProvFlags & CPD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT)
705 info->dwFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
706 else
707 info->dwFlags = 0;
708 info->pvReserved = NULL;
711 static BOOL WINTRUST_CreateChainForSigner(CRYPT_PROVIDER_DATA *data,
712 DWORD signer, PWTD_GENERIC_CHAIN_POLICY_CREATE_INFO createInfo,
713 PCERT_CHAIN_PARA chainPara)
715 BOOL ret = TRUE;
716 HCERTSTORE store = NULL;
718 if (data->chStores)
720 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
721 CERT_STORE_CREATE_NEW_FLAG, NULL);
722 if (store)
724 DWORD i;
726 for (i = 0; i < data->chStores; i++)
727 CertAddStoreToCollection(store, data->pahStores[i], 0, 0);
730 /* Expect the end certificate for each signer to be the only cert in the
731 * chain:
733 if (data->pasSigners[signer].csCertChain)
735 /* Create a certificate chain for each signer */
736 ret = CertGetCertificateChain(createInfo->hChainEngine,
737 data->pasSigners[signer].pasCertChain[0].pCert,
738 &data->pasSigners[signer].sftVerifyAsOf, store,
739 chainPara, createInfo->dwFlags, createInfo->pvReserved,
740 &data->pasSigners[signer].pChainContext);
741 if (ret)
743 if (data->pasSigners[signer].pChainContext->cChain != 1)
745 FIXME("unimplemented for more than 1 simple chain\n");
746 ret = FALSE;
748 else
750 if ((ret = WINTRUST_CopyChain(data, signer)))
752 if (data->psPfns->pfnCertCheckPolicy)
753 ret = data->psPfns->pfnCertCheckPolicy(data, signer,
754 FALSE, 0);
755 else
756 TRACE("no cert check policy, skipping policy check\n");
761 CertCloseStore(store, 0);
762 return ret;
765 HRESULT WINAPI WintrustCertificateTrust(CRYPT_PROVIDER_DATA *data)
767 BOOL ret;
769 TRACE("(%p)\n", data);
771 if (!data->csSigners)
773 ret = FALSE;
774 SetLastError(TRUST_E_NOSIGNATURE);
776 else
778 DWORD i;
779 WTD_GENERIC_CHAIN_POLICY_CREATE_INFO createInfo;
780 CERT_CHAIN_PARA chainPara;
782 WINTRUST_CreateChainPolicyCreateInfo(data, &createInfo, &chainPara);
783 ret = TRUE;
784 for (i = 0; i < data->csSigners; i++)
785 ret = WINTRUST_CreateChainForSigner(data, i, &createInfo,
786 &chainPara);
788 if (!ret)
789 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
790 GetLastError();
791 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
792 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
793 return ret ? S_OK : S_FALSE;
796 HRESULT WINAPI GenericChainCertificateTrust(CRYPT_PROVIDER_DATA *data)
798 BOOL ret;
799 WTD_GENERIC_CHAIN_POLICY_DATA *policyData =
800 data->pWintrustData->pPolicyCallbackData;
802 TRACE("(%p)\n", data);
804 if (policyData && policyData->u.cbSize !=
805 sizeof(WTD_GENERIC_CHAIN_POLICY_CREATE_INFO))
807 SetLastError(ERROR_INVALID_PARAMETER);
808 ret = FALSE;
809 goto end;
811 if (!data->csSigners)
813 ret = FALSE;
814 SetLastError(TRUST_E_NOSIGNATURE);
816 else
818 DWORD i;
819 WTD_GENERIC_CHAIN_POLICY_CREATE_INFO createInfo, *pCreateInfo;
820 CERT_CHAIN_PARA chainPara, *pChainPara;
822 if (policyData)
824 pCreateInfo = policyData->pSignerChainInfo;
825 pChainPara = pCreateInfo->pChainPara;
827 else
829 WINTRUST_CreateChainPolicyCreateInfo(data, &createInfo, &chainPara);
830 pChainPara = &chainPara;
831 pCreateInfo = &createInfo;
833 ret = TRUE;
834 for (i = 0; i < data->csSigners; i++)
835 ret = WINTRUST_CreateChainForSigner(data, i, pCreateInfo,
836 pChainPara);
839 end:
840 if (!ret)
841 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
842 GetLastError();
843 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
844 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
845 return ret ? S_OK : S_FALSE;
848 HRESULT WINAPI SoftpubAuthenticode(CRYPT_PROVIDER_DATA *data)
850 BOOL ret;
851 CERT_CHAIN_POLICY_STATUS policyStatus = { sizeof(policyStatus), 0 };
853 TRACE("(%p)\n", data);
855 if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
856 FIXME("unimplemented for UI choice %d\n",
857 data->pWintrustData->dwUIChoice);
858 if (!data->csSigners)
860 ret = FALSE;
861 policyStatus.dwError = TRUST_E_NOSIGNATURE;
863 else
865 DWORD i;
867 ret = TRUE;
868 for (i = 0; ret && i < data->csSigners; i++)
870 BYTE hash[20];
871 DWORD size = sizeof(hash);
873 /* First make sure cert isn't disallowed */
874 if ((ret = CertGetCertificateContextProperty(
875 data->pasSigners[i].pasCertChain[0].pCert,
876 CERT_SIGNATURE_HASH_PROP_ID, hash, &size)))
878 static const WCHAR disallowedW[] =
879 { 'D','i','s','a','l','l','o','w','e','d',0 };
880 HCERTSTORE disallowed = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
881 X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER,
882 disallowedW);
884 if (disallowed)
886 PCCERT_CONTEXT found = CertFindCertificateInStore(
887 disallowed, X509_ASN_ENCODING, 0, CERT_FIND_SIGNATURE_HASH,
888 hash, NULL);
890 if (found)
892 /* Disallowed! Can't verify it. */
893 policyStatus.dwError = TRUST_E_SUBJECT_NOT_TRUSTED;
894 ret = FALSE;
895 CertFreeCertificateContext(found);
897 CertCloseStore(disallowed, 0);
900 if (ret)
902 CERT_CHAIN_POLICY_PARA policyPara = { sizeof(policyPara), 0 };
904 if (data->dwRegPolicySettings & WTPF_TRUSTTEST)
905 policyPara.dwFlags |= CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG;
906 if (data->dwRegPolicySettings & WTPF_TESTCANBEVALID)
907 policyPara.dwFlags |= CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG;
908 if (data->dwRegPolicySettings & WTPF_IGNOREEXPIRATION)
909 policyPara.dwFlags |=
910 CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG |
911 CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG |
912 CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG;
913 if (data->dwRegPolicySettings & WTPF_IGNOREREVOKATION)
914 policyPara.dwFlags |=
915 CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG |
916 CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG |
917 CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG |
918 CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG;
919 CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_AUTHENTICODE,
920 data->pasSigners[i].pChainContext, &policyPara, &policyStatus);
921 if (policyStatus.dwError != NO_ERROR)
922 ret = FALSE;
926 if (!ret)
927 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV] =
928 policyStatus.dwError;
929 TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
930 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV]);
931 return ret ? S_OK : S_FALSE;
934 static HRESULT WINAPI WINTRUST_DefaultPolicy(CRYPT_PROVIDER_DATA *pProvData,
935 DWORD dwStepError, DWORD dwRegPolicySettings, DWORD cSigner,
936 PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO rgpSigner, void *pvPolicyArg)
938 DWORD i;
939 CERT_CHAIN_POLICY_STATUS policyStatus = { sizeof(policyStatus), 0 };
941 for (i = 0; !policyStatus.dwError && i < cSigner; i++)
943 CERT_CHAIN_POLICY_PARA policyPara = { sizeof(policyPara), 0 };
945 if (dwRegPolicySettings & WTPF_IGNOREEXPIRATION)
946 policyPara.dwFlags |=
947 CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG |
948 CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG |
949 CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG;
950 if (dwRegPolicySettings & WTPF_IGNOREREVOKATION)
951 policyPara.dwFlags |=
952 CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG |
953 CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG |
954 CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG |
955 CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG;
956 CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE,
957 rgpSigner[i].pChainContext, &policyPara, &policyStatus);
959 return policyStatus.dwError;
962 HRESULT WINAPI GenericChainFinalProv(CRYPT_PROVIDER_DATA *data)
964 HRESULT err = NO_ERROR; /* not a typo, MS confused the types */
965 WTD_GENERIC_CHAIN_POLICY_DATA *policyData =
966 data->pWintrustData->pPolicyCallbackData;
968 TRACE("(%p)\n", data);
970 if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
971 FIXME("unimplemented for UI choice %d\n",
972 data->pWintrustData->dwUIChoice);
973 if (!data->csSigners)
974 err = TRUST_E_NOSIGNATURE;
975 else
977 PFN_WTD_GENERIC_CHAIN_POLICY_CALLBACK policyCallback;
978 void *policyArg;
979 WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO *signers = NULL;
981 if (policyData)
983 policyCallback = policyData->pfnPolicyCallback;
984 policyArg = policyData->pvPolicyArg;
986 else
988 policyCallback = WINTRUST_DefaultPolicy;
989 policyArg = NULL;
991 if (data->csSigners)
993 DWORD i;
995 signers = data->psPfns->pfnAlloc(
996 data->csSigners * sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO));
997 if (signers)
999 for (i = 0; i < data->csSigners; i++)
1001 signers[i].u.cbSize =
1002 sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO);
1003 signers[i].pChainContext =
1004 data->pasSigners[i].pChainContext;
1005 signers[i].dwSignerType = data->pasSigners[i].dwSignerType;
1006 signers[i].pMsgSignerInfo = data->pasSigners[i].psSigner;
1007 signers[i].dwError = data->pasSigners[i].dwError;
1008 if (data->pasSigners[i].csCounterSigners)
1009 FIXME("unimplemented for counter signers\n");
1010 signers[i].cCounterSigner = 0;
1011 signers[i].rgpCounterSigner = NULL;
1014 else
1015 err = ERROR_OUTOFMEMORY;
1017 if (err == NO_ERROR)
1018 err = policyCallback(data, TRUSTERROR_STEP_FINAL_POLICYPROV,
1019 data->dwRegPolicySettings, data->csSigners, signers, policyArg);
1020 data->psPfns->pfnFree(signers);
1022 if (err != NO_ERROR)
1023 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV] = err;
1024 TRACE("returning %d (%08x)\n", err == NO_ERROR ? S_OK : S_FALSE,
1025 data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV]);
1026 return err == NO_ERROR ? S_OK : S_FALSE;
1029 HRESULT WINAPI SoftpubCleanup(CRYPT_PROVIDER_DATA *data)
1031 DWORD i, j;
1033 for (i = 0; i < data->csSigners; i++)
1035 for (j = 0; j < data->pasSigners[i].csCertChain; j++)
1036 CertFreeCertificateContext(data->pasSigners[i].pasCertChain[j].pCert);
1037 data->psPfns->pfnFree(data->pasSigners[i].pasCertChain);
1038 data->psPfns->pfnFree(data->pasSigners[i].psSigner);
1039 CertFreeCertificateChain(data->pasSigners[i].pChainContext);
1041 data->psPfns->pfnFree(data->pasSigners);
1043 for (i = 0; i < data->chStores; i++)
1044 CertCloseStore(data->pahStores[i], 0);
1045 data->psPfns->pfnFree(data->pahStores);
1047 if (data->u.pPDSip)
1049 data->psPfns->pfnFree(data->u.pPDSip->pSip);
1050 data->psPfns->pfnFree(data->u.pPDSip->pCATSip);
1051 data->psPfns->pfnFree(data->u.pPDSip->psSipSubjectInfo);
1052 data->psPfns->pfnFree(data->u.pPDSip->psSipCATSubjectInfo);
1053 data->psPfns->pfnFree(data->u.pPDSip->psIndirectData);
1056 CryptMsgClose(data->hMsg);
1058 if (data->fOpenedFile)
1059 CloseHandle(data->pWintrustData->u.pFile->hFile);
1061 return S_OK;
1064 HRESULT WINAPI HTTPSCertificateTrust(CRYPT_PROVIDER_DATA *data)
1066 FIXME("(%p)\n", data);
1067 return S_OK;
1070 HRESULT WINAPI HTTPSFinalProv(CRYPT_PROVIDER_DATA *data)
1072 FIXME("(%p)\n", data);
1073 return S_OK;