windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/pkitrust/softpub/sigprov.cpp
2020-09-26 16:20:57 +08:00

986 lines
31 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: sigprov.cpp
//
// Contents: Microsoft Internet Security Authenticode Policy Provider
//
// Functions: SoftpubLoadSignature
//
// *** local functions ***
// _ExtractSigner
// _ExtractCounterSigners
// _HandleCertChoice
// _HandleSignerChoice
// _FindCertificate
// _FindCounterSignersCert
// _IsValidTimeStampCert
//
// History: 05-Jun-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
BOOL _ExtractSigner(HCRYPTMSG hMsg, CRYPT_PROVIDER_DATA *pProvData,
int idxSigner);
BOOL _ExtractCounterSigners(CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner);
HRESULT _HandleCertChoice(CRYPT_PROVIDER_DATA *pProvData);
HRESULT _HandleSignerChoice(CRYPT_PROVIDER_DATA *pProvData);
PCCERT_CONTEXT _FindCertificate(CRYPT_PROVIDER_DATA *pProvData, CERT_INFO *pCert);
PCCERT_CONTEXT _FindCounterSignersCert(CRYPT_PROVIDER_DATA *pProvData,
CERT_NAME_BLOB *psIssuer,
CRYPT_INTEGER_BLOB *psSerial);
BOOL WINAPI _IsValidTimeStampCert(
PCCERT_CONTEXT pCertContext,
BOOL *pfVerisignTimeStampCert
);
#ifdef CMS_PKCS7
BOOL _VerifyMessageSignatureWithChainPubKeyParaInheritance(
IN CRYPT_PROVIDER_DATA *pProvData,
IN DWORD dwSignerIndex,
IN PCCERT_CONTEXT pSigner
);
BOOL _VerifyCountersignatureWithChainPubKeyParaInheritance(
IN CRYPT_PROVIDER_DATA *pProvData,
IN PBYTE pbSignerInfo,
IN DWORD cbSignerInfo,
IN PBYTE pbSignerInfoCountersignature,
IN DWORD cbSignerInfoCountersignature,
IN PCCERT_CONTEXT pSigner
);
#endif // CMS_PKCS7
HRESULT SoftpubLoadSignature(CRYPT_PROVIDER_DATA *pProvData)
{
if (!(pProvData->padwTrustStepErrors) ||
(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] != ERROR_SUCCESS) ||
(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_INITPROV] != ERROR_SUCCESS))
{
return(S_FALSE);
}
switch (pProvData->pWintrustData->dwUnionChoice)
{
case WTD_CHOICE_CERT:
return(_HandleCertChoice(pProvData));
case WTD_CHOICE_SIGNER:
return(_HandleSignerChoice(pProvData));
case WTD_CHOICE_FILE:
case WTD_CHOICE_CATALOG:
case WTD_CHOICE_BLOB:
break;
default:
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NOSIGNATURE;
return(S_FALSE);
}
if (!(pProvData->hMsg))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NOSIGNATURE;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_SIGNERCOUNT] = GetLastError();
return(S_FALSE);
}
if ((_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, fRecallWithState)) &&
(pProvData->fRecallWithState))
{
return(S_OK);
}
int i;
DWORD cbSize;
DWORD csSigners;
CRYPT_PROVIDER_SGNR *pSgnr;
CRYPT_PROVIDER_SGNR sSgnr;
CRYPT_PROVIDER_CERT *pCert;
cbSize = sizeof(DWORD);
// signer count
if (!(CryptMsgGetParam(pProvData->hMsg,
CMSG_SIGNER_COUNT_PARAM,
0,
&csSigners,
&cbSize)))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NOSIGNATURE;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_SIGNERCOUNT] = GetLastError();
return(S_FALSE);
}
if (csSigners == 0)
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NOSIGNATURE;
return(S_FALSE);
}
for (i = 0; i < (int)csSigners; i++)
{
memset(&sSgnr, 0x00, sizeof(CRYPT_PROVIDER_SGNR));
sSgnr.cbStruct = sizeof(CRYPT_PROVIDER_SGNR);
if (!(pProvData->psPfns->pfnAddSgnr2Chain(pProvData, FALSE, i, &sSgnr)))
{
pProvData->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_SYSTEM_ERROR;
return(S_FALSE);
}
pSgnr = WTHelperGetProvSignerFromChain(pProvData, i, FALSE, 0);
if (_ExtractSigner(pProvData->hMsg, pProvData, i))
{
memcpy(&pSgnr->sftVerifyAsOf, &pProvData->sftSystemTime, sizeof(FILETIME));
_ExtractCounterSigners(pProvData, i);
}
}
//
// verify the integrity of the signature(s)
//
for (i = 0; i < (int)pProvData->csSigners; i++)
{
pSgnr = WTHelperGetProvSignerFromChain(pProvData, i, FALSE, 0);
pCert = WTHelperGetProvCertFromChain(pSgnr, 0);
if (pSgnr->csCertChain > 0)
{
#ifdef CMS_PKCS7
if(!_VerifyMessageSignatureWithChainPubKeyParaInheritance(
pProvData,
i,
pCert->pCert))
#else
if (!(CryptMsgControl(pProvData->hMsg,
0,
CMSG_CTRL_VERIFY_SIGNATURE,
pCert->pCert->pCertInfo)))
#endif // CMS_PKCS7
{
if (pSgnr->dwError == 0)
{
pSgnr->dwError = GetLastError();
}
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NOSIGNATURE;
return(S_FALSE);
}
}
}
return(S_OK);
}
HRESULT _HandleCertChoice(CRYPT_PROVIDER_DATA *pProvData)
{
if (!(pProvData->pWintrustData->pCert) ||
!(WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_CERT_INFO,
pProvData->pWintrustData->pCert->cbStruct,
pahStores)) ||
!(pProvData->pWintrustData->pCert->psCertContext))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = ERROR_INVALID_PARAMETER;
return(S_FALSE);
}
//
// add the stores passed in by the client
//
for (int i = 0; i < (int)pProvData->pWintrustData->pCert->chStores; i++)
{
if (!(pProvData->psPfns->pfnAddStore2Chain(pProvData,
pProvData->pWintrustData->pCert->pahStores[i])))
{
pProvData->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_SYSTEM_ERROR;
return(S_FALSE);
}
}
//
// add a dummy signer
//
CRYPT_PROVIDER_SGNR sSgnr;
memset(&sSgnr, 0x00, sizeof(CRYPT_PROVIDER_SGNR));
sSgnr.cbStruct = sizeof(CRYPT_PROVIDER_SGNR);
memcpy(&sSgnr.sftVerifyAsOf, &pProvData->sftSystemTime, sizeof(FILETIME));
if ((_ISINSTRUCT(WINTRUST_CERT_INFO, pProvData->pWintrustData->pCert->cbStruct, psftVerifyAsOf)) &&
(pProvData->pWintrustData->pCert->psftVerifyAsOf))
{
memcpy(&sSgnr.sftVerifyAsOf, pProvData->pWintrustData->pCert->psftVerifyAsOf, sizeof(FILETIME));
}
if (!(pProvData->psPfns->pfnAddSgnr2Chain(pProvData, FALSE, 0, &sSgnr)))
{
pProvData->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_SYSTEM_ERROR;
return(S_FALSE);
}
//
// add the "signer's" cert...
//
pProvData->psPfns->pfnAddCert2Chain(pProvData, 0, FALSE, 0,
pProvData->pWintrustData->pCert->psCertContext);
return(ERROR_SUCCESS);
}
HRESULT _HandleSignerChoice(CRYPT_PROVIDER_DATA *pProvData)
{
if (!(pProvData->pWintrustData->pSgnr) ||
!(WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_SGNR_INFO,
pProvData->pWintrustData->pSgnr->cbStruct,
pahStores)) ||
!(pProvData->pWintrustData->pSgnr->psSignerInfo))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = ERROR_INVALID_PARAMETER;
return(S_FALSE);
}
int i;
if (1 < pProvData->pWintrustData->pCert->chStores &&
0 == pProvData->chStores)
WTHelperOpenKnownStores(pProvData);
//
// add the stores passed in by the client
//
for (i = 0; i < (int)pProvData->pWintrustData->pCert->chStores; i++)
{
if (!(pProvData->psPfns->pfnAddStore2Chain(pProvData,
pProvData->pWintrustData->pCert->pahStores[i])))
{
pProvData->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_SYSTEM_ERROR;
return(S_FALSE);
}
}
CRYPT_PROVIDER_SGNR sSgnr;
CRYPT_PROVIDER_SGNR *pSgnr;
memset(&sSgnr, 0x00, sizeof(CRYPT_PROVIDER_SGNR));
sSgnr.cbStruct = sizeof(CRYPT_PROVIDER_SGNR);
if (!(sSgnr.psSigner = (CMSG_SIGNER_INFO *)pProvData->psPfns->pfnAlloc(sizeof(CMSG_SIGNER_INFO))))
{
pProvData->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_SYSTEM_ERROR;
return(S_FALSE);
}
memcpy(sSgnr.psSigner, pProvData->pWintrustData->pSgnr->psSignerInfo,
sizeof(CMSG_SIGNER_INFO));
memcpy(&sSgnr.sftVerifyAsOf, &pProvData->sftSystemTime, sizeof(FILETIME));
if (!(pProvData->psPfns->pfnAddSgnr2Chain(pProvData, FALSE, 0, &sSgnr)))
{
pProvData->psPfns->pfnFree(sSgnr.psSigner);
pProvData->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_SYSTEM_ERROR;
return(S_FALSE);
}
if (!(pSgnr = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0)))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = GetLastError();
return(S_FALSE);
}
CERT_INFO sCert;
PCCERT_CONTEXT pCertContext;
memset(&sCert, 0x00, sizeof(CERT_INFO));
sCert.Issuer.cbData = pSgnr->psSigner->Issuer.cbData;
sCert.Issuer.pbData = pSgnr->psSigner->Issuer.pbData;
sCert.SerialNumber.cbData = pSgnr->psSigner->SerialNumber.cbData;
sCert.SerialNumber.pbData = pSgnr->psSigner->SerialNumber.pbData;
if (!(pCertContext = _FindCertificate(pProvData, &sCert)))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NO_SIGNER_CERT;
return(FALSE);
}
pProvData->psPfns->pfnAddCert2Chain(pProvData, 0, FALSE, 0, pCertContext);
_ExtractCounterSigners(pProvData, 0);
return(ERROR_SUCCESS);
}
BOOL _ExtractSigner(HCRYPTMSG hMsg, CRYPT_PROVIDER_DATA *pProvData, int idxSigner)
{
DWORD cb;
BYTE *pb;
CRYPT_PROVIDER_SGNR *pSgnr;
PCCERT_CONTEXT pCertContext;
pSgnr = WTHelperGetProvSignerFromChain(pProvData, idxSigner, FALSE, 0);
if (pSgnr == NULL)
{
return(FALSE);
}
//
// signer info
//
cb = 0;
CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, idxSigner, NULL, &cb);
if (cb == 0)
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NOSIGNATURE;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_SIGNERINFO] = GetLastError();
return(FALSE);
}
if (!(pSgnr->psSigner = (CMSG_SIGNER_INFO *)pProvData->psPfns->pfnAlloc(cb)))
{
pProvData->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_SYSTEM_ERROR;
return(FALSE);
}
memset(pSgnr->psSigner, 0x00, cb);
if (!(CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, idxSigner, pSgnr->psSigner, &cb)))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NOSIGNATURE;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_SIGNERINFO] = GetLastError();
return(FALSE);
}
//
// cert info
//
cb = 0;
CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, idxSigner, NULL, &cb);
if (cb == 0)
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NO_SIGNER_CERT;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_SIGNERINFO] = GetLastError();
return(FALSE);
}
if (!(pb = (BYTE *)pProvData->psPfns->pfnAlloc(cb)))
{
pProvData->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_SYSTEM_ERROR;
return(FALSE);
}
memset(pb, 0x00, cb);
if (!(CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, idxSigner, pb, &cb)))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NO_SIGNER_CERT;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_SIGNERINFO] = GetLastError();
pProvData->psPfns->pfnFree(pb);
return(FALSE);
}
if (!(pCertContext = _FindCertificate(pProvData, (CERT_INFO *)pb)))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_NO_SIGNER_CERT;
pProvData->psPfns->pfnFree(pb);
return(FALSE);
}
pProvData->psPfns->pfnFree(pb);
pProvData->psPfns->pfnAddCert2Chain(pProvData, idxSigner, FALSE, 0, pCertContext);
CertFreeCertificateContext(pCertContext);
return(TRUE);
}
BOOL _ExtractCounterSigners(CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner)
{
if ((_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, fRecallWithState)) &&
(pProvData->fRecallWithState))
{
return(TRUE);
}
CRYPT_ATTRIBUTE *pAttr;
PCCERT_CONTEXT pCertContext;
CRYPT_PROVIDER_SGNR *pSgnr;
CRYPT_PROVIDER_SGNR sCS;
CRYPT_PROVIDER_SGNR *pCS;
CRYPT_PROVIDER_CERT *pCert;
DWORD cbSize;
BOOL fVerisignTimeStampCert = FALSE;
pSgnr = WTHelperGetProvSignerFromChain(pProvData, idxSigner, FALSE, 0);
if (pSgnr == NULL)
{
return(FALSE);
}
//
// counter signers are stored in the UN-authenticated attributes of the
// signer.
//
if ((pAttr = CertFindAttribute(szOID_RSA_counterSign,
pSgnr->psSigner->UnauthAttrs.cAttr,
pSgnr->psSigner->UnauthAttrs.rgAttr)) == NULL)
{
//
// no counter signature
//
return(FALSE);
}
memset(&sCS, 0x00, sizeof(CRYPT_PROVIDER_SGNR));
sCS.cbStruct = sizeof(CRYPT_PROVIDER_SGNR);
memcpy(&sCS.sftVerifyAsOf, &pProvData->sftSystemTime, sizeof(FILETIME));
if (!(pProvData->psPfns->pfnAddSgnr2Chain(pProvData, TRUE, idxSigner, &sCS)))
{
pProvData->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_SYSTEM_ERROR;
return(FALSE);
}
pCS = WTHelperGetProvSignerFromChain(pProvData, idxSigner, TRUE, pSgnr->csCounterSigners - 1);
// Crack the encoded signer
if (!(TrustDecode(WVT_MODID_SOFTPUB, (BYTE **)&pCS->psSigner, &cbSize, 1024,
pProvData->dwEncoding, PKCS7_SIGNER_INFO, pAttr->rgValue[0].pbData, pAttr->rgValue[0].cbData,
CRYPT_DECODE_NOCOPY_FLAG)))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_COUNTER_SIGNER;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_COUNTERSIGINFO] = GetLastError();
pCS->dwError = GetLastError();
return(FALSE);
}
//
// counter signers cert
//
if (!(pCertContext = _FindCounterSignersCert(pProvData,
&pCS->psSigner->Issuer,
&pCS->psSigner->SerialNumber)))
{
pCS->dwError = TRUST_E_NO_SIGNER_CERT;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_COUNTER_SIGNER;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_COUNTERSIGCERT] = GetLastError();
return(FALSE);
}
pProvData->psPfns->pfnAddCert2Chain(pProvData, idxSigner, TRUE,
pProvData->pasSigners[idxSigner].csCounterSigners - 1,
pCertContext);
CertFreeCertificateContext(pCertContext);
pCert = WTHelperGetProvCertFromChain(pCS, pCS->csCertChain - 1);
pCertContext = pCert->pCert;
{
//
// Verify the counter's signature
//
BYTE *pbEncodedSigner = NULL;
DWORD cbEncodedSigner;
BOOL fResult;
// First need to re-encode the Signer.
fResult = CryptEncodeObjectEx(
PKCS_7_ASN_ENCODING | CRYPT_ASN_ENCODING,
PKCS7_SIGNER_INFO,
pSgnr->psSigner,
CRYPT_ENCODE_ALLOC_FLAG,
NULL, // pEncodePara
(void *) &pbEncodedSigner,
&cbEncodedSigner
);
if (fResult)
#ifdef CMS_PKCS7
fResult = _VerifyCountersignatureWithChainPubKeyParaInheritance(
pProvData,
pbEncodedSigner,
cbEncodedSigner,
pAttr->rgValue[0].pbData,
pAttr->rgValue[0].cbData,
pCertContext
);
#else
fResult = CryptMsgVerifyCountersignatureEncoded(
NULL, //HCRYPTPROV
PKCS_7_ASN_ENCODING | CRYPT_ASN_ENCODING,
pbEncodedSigner,
cbEncodedSigner,
pAttr->rgValue[0].pbData,
pAttr->rgValue[0].cbData,
pCertContext->pCertInfo
);
#endif // CMS_PKCS7
if (pbEncodedSigner)
LocalFree((HLOCAL) pbEncodedSigner);
if (!fResult)
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_COUNTER_SIGNER;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_COUNTERSIGINFO] = GetLastError();
pCS->dwError = GetLastError();
return(FALSE);
}
}
//
// see if the counter signer is a TimeStamp.
//
if (!(_IsValidTimeStampCert(pCertContext, &fVerisignTimeStampCert)))
{
return(TRUE);
}
// get the time
if (!(pAttr = CertFindAttribute(szOID_RSA_signingTime,
pCS->psSigner->AuthAttrs.cAttr,
pCS->psSigner->AuthAttrs.rgAttr)))
{
//
// not a time stamp...
//
return(TRUE);
}
//
// the time stamp counter signature must have 1 value!
//
if (pAttr->cValue <= 0)
{
//
// not a time stamp...
//
return(TRUE);
}
//
// Crack the time stamp and get the file time.
//
FILETIME ftHold;
cbSize = sizeof(FILETIME);
CryptDecodeObject(pProvData->dwEncoding,
PKCS_UTC_TIME,
pAttr->rgValue[0].pbData,
pAttr->rgValue[0].cbData,
0,
&ftHold,
&cbSize);
if (cbSize == 0)
{
pCS->dwError = GetLastError();
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] = TRUST_E_TIME_STAMP;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_MSG_COUNTERSIGINFO] = GetLastError();
return(FALSE);
}
//
// set the signer's verify date to the date in the time stamp!
//
memcpy(&pSgnr->sftVerifyAsOf, &ftHold, sizeof(FILETIME));
// On 12-January-99 Keithv gave me the orders to change the
// countersigning to use the current time
//
// On 25-January-99 backed out the above change
//
// On 28-August-99 changed to use the current time for all
// countersigners excluding the first Verisign Time Stamp
// certificate
//
// On 12-January-00 added a second Verisign Time Stamp cert to exclude
//
// On 05-April-01 changed back to W2K semantics. A time stamp chain
// never expires.
//
memcpy(&pCS->sftVerifyAsOf, &ftHold, sizeof(FILETIME));
pCS->dwSignerType |= SGNR_TYPE_TIMESTAMP;
return(TRUE);
}
PCCERT_CONTEXT _FindCertificate(CRYPT_PROVIDER_DATA *pProvData, CERT_INFO *pCert)
{
PCCERT_CONTEXT pCertContext;
DWORD i;
if (!(pCert))
{
return(NULL);
}
for (i = 0; i < pProvData->chStores; i++)
{
if (pCertContext = CertGetSubjectCertificateFromStore(pProvData->pahStores[i],
pProvData->dwEncoding,
pCert))
{
return(pCertContext);
}
}
if (1 >= pProvData->chStores) {
DWORD cOrig = pProvData->chStores;
WTHelperOpenKnownStores(pProvData);
for (i = cOrig; i < pProvData->chStores; i++) {
if (pCertContext = CertGetSubjectCertificateFromStore(
pProvData->pahStores[i],
pProvData->dwEncoding,
pCert))
return (pCertContext);
}
}
return(NULL);
}
PCCERT_CONTEXT _FindCounterSignersCert(CRYPT_PROVIDER_DATA *pProvData,
CERT_NAME_BLOB *psIssuer,
CRYPT_INTEGER_BLOB *psSerial)
{
CERT_INFO sCert;
PCCERT_CONTEXT pCertContext;
DWORD i;
memset(&sCert, 0x00, sizeof(CERT_INFO));
sCert.Issuer = *psIssuer;
sCert.SerialNumber = *psSerial;
for (i = 0; i < pProvData->chStores; i++)
{
if (pCertContext = CertGetSubjectCertificateFromStore(pProvData->pahStores[i],
pProvData->dwEncoding,
&sCert))
{
return(pCertContext);
}
}
if (1 >= pProvData->chStores) {
DWORD cOrig = pProvData->chStores;
WTHelperOpenKnownStores(pProvData);
for (i = cOrig; i < pProvData->chStores; i++) {
if (pCertContext = CertGetSubjectCertificateFromStore(
pProvData->pahStores[i],
pProvData->dwEncoding,
&sCert))
return (pCertContext);
}
}
return(NULL);
}
#define SH1_HASH_LENGTH 20
BOOL WINAPI _IsValidTimeStampCert(
PCCERT_CONTEXT pCertContext,
BOOL *pfVerisignTimeStampCert
)
{
DWORD cbSize;
PCERT_ENHKEY_USAGE pCertEKU;
BYTE baSignersThumbPrint[SH1_HASH_LENGTH];
static BYTE baVerisignTimeStampThumbPrint[SH1_HASH_LENGTH] =
{ 0x38, 0x73, 0xB6, 0x99, 0xF3, 0x5B, 0x9C, 0xCC, 0x36, 0x62,
0xB6, 0x48, 0x3A, 0x96, 0xBD, 0x6E, 0xEC, 0x97, 0xCF, 0xB7 };
static BYTE baVerisignTimeStampThumbPrint2[SH1_HASH_LENGTH] = {
0x9A, 0x3F, 0xF0, 0x5B, 0x42, 0x88, 0x52, 0x64,
0x84, 0xA9, 0xFC, 0xB8, 0xBC, 0x14, 0x7D, 0x53,
0xE1, 0x5A, 0x43, 0xBB
};
cbSize = SH1_HASH_LENGTH;
if (!(CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID,
&baSignersThumbPrint[0], &cbSize)))
{
return(FALSE);
}
//
// 1st, check to see if it's Verisign's first timestamp certificate. This one did NOT
// have the enhanced key usage in it.
//
// 12-January-00
// Also, check for the second Verisign timestamp certificate. Its only
// valid for 5 years. Will grandfather in to be valid forever.
//
if (memcmp(&baSignersThumbPrint[0], &baVerisignTimeStampThumbPrint[0],
SH1_HASH_LENGTH) == 0
||
memcmp(&baSignersThumbPrint[0], &baVerisignTimeStampThumbPrint2[0],
SH1_HASH_LENGTH) == 0)
{
*pfVerisignTimeStampCert = TRUE;
return(TRUE);
}
else
{
*pfVerisignTimeStampCert = FALSE;
}
//
// see if the certificate has the proper enhanced key usage OID
//
cbSize = 0;
CertGetEnhancedKeyUsage(pCertContext,
CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
NULL,
&cbSize);
if (cbSize == 0)
{
return(FALSE);
}
if (!(pCertEKU = (PCERT_ENHKEY_USAGE)new BYTE[cbSize]))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(FALSE);
}
if (!(CertGetEnhancedKeyUsage(pCertContext,
CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
pCertEKU,
&cbSize)))
{
delete pCertEKU;
return(FALSE);
}
for (int i = 0; i < (int)pCertEKU->cUsageIdentifier; i++)
{
if (strcmp(pCertEKU->rgpszUsageIdentifier[i], szOID_KP_TIME_STAMP_SIGNING) == 0)
{
delete pCertEKU;
return(TRUE);
}
if (strcmp(pCertEKU->rgpszUsageIdentifier[i], szOID_PKIX_KP_TIMESTAMP_SIGNING) == 0)
{
delete pCertEKU;
return(TRUE);
}
}
delete pCertEKU;
return(FALSE);
}
#ifdef CMS_PKCS7
void _BuildChainForPubKeyParaInheritance(
IN CRYPT_PROVIDER_DATA *pProvData,
IN PCCERT_CONTEXT pSigner
)
{
PCCERT_CHAIN_CONTEXT pChainContext;
CERT_CHAIN_PARA ChainPara;
HCERTSTORE hAdditionalStore;
if (0 == pProvData->chStores)
hAdditionalStore = NULL;
else if (1 < pProvData->chStores) {
if (hAdditionalStore = CertOpenStore(
CERT_STORE_PROV_COLLECTION,
0, // dwEncodingType
0, // hCryptProv
0, // dwFlags
NULL // pvPara
)) {
DWORD i;
for (i = 0; i < pProvData->chStores; i++)
CertAddStoreToCollection(
hAdditionalStore,
pProvData->pahStores[i],
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
0 // dwPriority
);
}
} else
hAdditionalStore = CertDuplicateStore(pProvData->pahStores[0]);
// Build a chain. Hopefully, the signer inherit's its public key
// parameters from up the chain
memset(&ChainPara, 0, sizeof(ChainPara));
ChainPara.cbSize = sizeof(ChainPara);
if (CertGetCertificateChain(
NULL, // hChainEngine
pSigner,
NULL, // pTime
hAdditionalStore,
&ChainPara,
CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL,
NULL, // pvReserved
&pChainContext
))
CertFreeCertificateChain(pChainContext);
if (hAdditionalStore)
CertCloseStore(hAdditionalStore, 0);
}
//+-------------------------------------------------------------------------
// If the verify signature fails with CRYPT_E_MISSING_PUBKEY_PARA,
// build a certificate chain. Retry. Hopefully, the signer's
// CERT_PUBKEY_ALG_PARA_PROP_ID property gets set while building the chain.
//--------------------------------------------------------------------------
BOOL _VerifyMessageSignatureWithChainPubKeyParaInheritance(
IN CRYPT_PROVIDER_DATA *pProvData,
IN DWORD dwSignerIndex,
IN PCCERT_CONTEXT pSigner
)
{
CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA CtrlPara;
memset(&CtrlPara, 0, sizeof(CtrlPara));
CtrlPara.cbSize = sizeof(CtrlPara);
// CtrlPara.hCryptProv =
CtrlPara.dwSignerIndex = dwSignerIndex;
CtrlPara.dwSignerType = CMSG_VERIFY_SIGNER_CERT;
CtrlPara.pvSigner = (void *) pSigner;
if (CryptMsgControl(
pProvData->hMsg,
0, // dwFlags
CMSG_CTRL_VERIFY_SIGNATURE_EX,
&CtrlPara
))
return TRUE;
else if (CRYPT_E_MISSING_PUBKEY_PARA != GetLastError())
return FALSE;
else {
_BuildChainForPubKeyParaInheritance(pProvData, pSigner);
// Try again. Hopefully the above chain building updated the signer's
// context property with the missing public key parameters
return CryptMsgControl(
pProvData->hMsg,
0, // dwFlags
CMSG_CTRL_VERIFY_SIGNATURE_EX,
&CtrlPara
);
}
}
//+-------------------------------------------------------------------------
// If the verify counter signature fails with CRYPT_E_MISSING_PUBKEY_PARA,
// build a certificate chain. Retry. Hopefully, the signer's
// CERT_PUBKEY_ALG_PARA_PROP_ID property gets set while building the chain.
//--------------------------------------------------------------------------
BOOL _VerifyCountersignatureWithChainPubKeyParaInheritance(
IN CRYPT_PROVIDER_DATA *pProvData,
IN PBYTE pbSignerInfo,
IN DWORD cbSignerInfo,
IN PBYTE pbSignerInfoCountersignature,
IN DWORD cbSignerInfoCountersignature,
IN PCCERT_CONTEXT pSigner
)
{
if (CryptMsgVerifyCountersignatureEncodedEx(
0, // hCryptProv
PKCS_7_ASN_ENCODING | CRYPT_ASN_ENCODING,
pbSignerInfo,
cbSignerInfo,
pbSignerInfoCountersignature,
cbSignerInfoCountersignature,
CMSG_VERIFY_SIGNER_CERT,
(void *) pSigner,
0, // dwFlags
NULL // pvReserved
))
return TRUE;
else if (CRYPT_E_MISSING_PUBKEY_PARA != GetLastError())
return FALSE;
else {
_BuildChainForPubKeyParaInheritance(pProvData, pSigner);
// Try again. Hopefully the above chain building updated the signer's
// context property with the missing public key parameters
return CryptMsgVerifyCountersignatureEncodedEx(
0, // hCryptProv
PKCS_7_ASN_ENCODING | CRYPT_ASN_ENCODING,
pbSignerInfo,
cbSignerInfo,
pbSignerInfoCountersignature,
cbSignerInfoCountersignature,
CMSG_VERIFY_SIGNER_CERT,
(void *) pSigner,
0, // dwFlags
NULL // pvReserved
);
}
}
#endif // CMS_PKCS7