Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1196 lines
37 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: timereq.cpp
//
// Contents: Digital Timestamping APIs
//
// History: June-25-1997 Xiaohs Created
//----------------------------------------------------------------------------
#include "global.hxx"
#include <stdio.h>
static char szCrypt32[]="crypt32.dll";
//The version for crtyp32.dll which shipped with NT sp3: "4.0.1381.4"
static DWORD dwLowVersion=0x05650004;
static DWORD dwHighVersion=0x00040000;
HRESULT WINAPI
GetSignedMessageSignerInfoSubj(IN DWORD dwEncodingType,
IN HCRYPTPROV hCryptProv,
IN LPSIP_SUBJECTINFO pSipInfo,
IN DWORD* pdwIndex,
IN OUT PBYTE* ppbSignerInfo,
IN OUT DWORD* pcbSignerInfo)
{
HRESULT hr = S_OK;
SIP_DISPATCH_INFO sSip; ZERO(sSip); // Table of sip functions
DWORD cbSignedMsg = 0;
PBYTE pbSignedMsg = 0;
DWORD dwCertEncoding = 0;
DWORD dwMsgType = 0;
HCRYPTMSG hMsg = NULL;
DWORD cbSignerInfo=0;
BYTE *pbSignerInfo=NULL;
PKITRY {
if(!pcbSignerInfo || !ppbSignerInfo)
PKITHROW(E_INVALIDARG);
//init
*pcbSignerInfo=0;
*ppbSignerInfo=NULL;
// Load up the sip functions.
if(!CryptSIPLoad(pSipInfo->pgSubjectType, // GUID for the requried sip
0, // Reserved
&sSip)) // Table of functions
PKITHROW(SignError());
sSip.pfGet(pSipInfo,
&dwCertEncoding,
*pdwIndex,
&cbSignedMsg,
NULL);
if(cbSignedMsg == 0) PKITHROW(SignError());
pbSignedMsg = (PBYTE) malloc(cbSignedMsg);
if (!pbSignedMsg) PKITHROW(E_OUTOFMEMORY);
if(!sSip.pfGet(pSipInfo,
&dwCertEncoding,
*pdwIndex,
&cbSignedMsg,
pbSignedMsg))
PKITHROW(SignError()); // Real error.
if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
{
if(dwCertEncoding != dwEncodingType)
PKITHROW(TRUST_E_NOSIGNATURE);
}
if ((GET_CMSG_ENCODING_TYPE(dwEncodingType) & PKCS_7_ASN_ENCODING) &&
SignNoContentWrap(pbSignedMsg, cbSignedMsg))
dwMsgType = CMSG_SIGNED;
// Use CryptMsg to crack the encoded PKCS7 Signed Message
if (!(hMsg = CryptMsgOpenToDecode(dwEncodingType,
0, // dwFlags
dwMsgType,
hCryptProv,
NULL, // pRecipientInfo
NULL)))
PKITHROW(E_UNEXPECTED);
if (!CryptMsgUpdate(hMsg,
pbSignedMsg,
cbSignedMsg,
TRUE)) // fFinal
PKITHROW(SignError());
if(!CryptMsgGetParam(hMsg,
CMSG_ENCODED_SIGNER,
0, // First signer
NULL,
&cbSignerInfo))
PKITHROW(SignError());
pbSignerInfo=(PBYTE)malloc(cbSignerInfo);
if(!pbSignerInfo)
PKITHROW(E_OUTOFMEMORY);
if(!CryptMsgGetParam(hMsg,
CMSG_ENCODED_SIGNER,
0, // First signer
pbSignerInfo,
&cbSignerInfo))
PKITHROW(SignError());
//copy to the out put
*ppbSignerInfo=pbSignerInfo;
*pcbSignerInfo=cbSignerInfo;
hr=S_OK;
}
PKICATCH(err) {
hr = err.pkiError;
} PKIEND;
if (hMsg)
CryptMsgClose(hMsg);
if(pbSignedMsg)
free(pbSignedMsg);
if( (hr!=S_OK) && (pbSignerInfo))
free(pbSignerInfo);
return hr;
}
HRESULT WINAPI
GetSignedMessageSignerInfo(IN HCRYPTPROV hCryptProv,
IN SIGNER_SUBJECT_INFO *pSubjectInfo,
IN LPVOID pSipInfo,
IN OUT PBYTE* ppbSignerInfo,
IN OUT DWORD* pcbSignerInfo)
{
HRESULT hr = S_OK;
HANDLE hFile = NULL;
BOOL fFileOpen=FALSE;
GUID gSubjectGuid; // The subject guid used to load the sip
MS_ADDINFO_BLOB sBlob;
SIP_SUBJECTINFO sSubjInfo; ZERO(sSubjInfo);
DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; // For this version we default to this.
PKITRY {
if(!pcbSignerInfo || !ppbSignerInfo)
PKITHROW(E_INVALIDARG);
sSubjInfo.dwEncodingType = dwEncodingType;
sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO); // Version
sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
sSubjInfo.hProv=hCryptProv;
//set up file information
if(pSubjectInfo->dwSubjectChoice==SIGNER_SUBJECT_FILE)
{
// Open up the file
if((pSubjectInfo->pSignerFileInfo->hFile)==NULL ||
(pSubjectInfo->pSignerFileInfo->hFile)==INVALID_HANDLE_VALUE)
{
if(S_OK != (hr = SignOpenFile(
pSubjectInfo->pSignerFileInfo->pwszFileName, &hFile)))
PKITHROW(hr);
fFileOpen=TRUE;
}
else
hFile=pSubjectInfo->pSignerFileInfo->hFile;
// Get the subject type.
if(S_OK != (hr=SignGetFileType(hFile, pSubjectInfo->pSignerFileInfo->pwszFileName, &gSubjectGuid)))
PKITHROW(hr);
sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
sSubjInfo.hFile = hFile;
sSubjInfo.pwsFileName = pSubjectInfo->pSignerFileInfo->pwszFileName;
}
else
{
memset(&sBlob, 0, sizeof(MS_ADDINFO_BLOB));
sSubjInfo.pgSubjectType=pSubjectInfo->pSignerBlobInfo->pGuidSubject;
sSubjInfo.pwsDisplayName=pSubjectInfo->pSignerBlobInfo->pwszDisplayName;
sSubjInfo.dwUnionChoice=MSSIP_ADDINFO_BLOB;
sSubjInfo.psBlob=&sBlob;
sBlob.cbStruct=sizeof(MS_ADDINFO_BLOB);
sBlob.cbMemObject=pSubjectInfo->pSignerBlobInfo->cbBlob;
sBlob.pbMemObject=pSubjectInfo->pSignerBlobInfo->pbBlob;
}
hr = GetSignedMessageSignerInfoSubj(
dwEncodingType,
hCryptProv,
&sSubjInfo,
pSubjectInfo->pdwIndex,
ppbSignerInfo,
pcbSignerInfo);
if ((hFile) && (fFileOpen == TRUE) && !(sSubjInfo.hFile))
{
fFileOpen = FALSE; // we opened it, but, the SIP closed it!
}
if(hr != S_OK) PKITHROW(hr);
}
PKICATCH(err) {
hr = err.pkiError;
} PKIEND;
if(hFile && (fFileOpen==TRUE)) CloseHandle(hFile);
return hr;
}
HRESULT WINAPI
SignerAddTimeStampResponse(
IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to which the timestamp request should be added
IN PBYTE pbTimeStampResponse,
IN DWORD cbTimeStampResponse,
IN LPVOID pSipData)
{
return SignerAddTimeStampResponseEx(
0,
pSubjectInfo,
pbTimeStampResponse,
cbTimeStampResponse,
pSipData,
NULL);
}
HRESULT WINAPI
SignerAddTimeStampResponseEx(
IN DWORD dwFlags, //Reserved: Has to be set to 0.
IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject to which the timestamp request should be added
IN PBYTE pbTimeStampResponse,
IN DWORD cbTimeStampResponse,
IN LPVOID pSipData,
OUT SIGNER_CONTEXT **ppSignerContext
)
{
HRESULT hr = S_OK;
HANDLE hFile = NULL;
BOOL fFileOpen=FALSE;
DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
GUID gSubjectGuid; // The subject guid used to load the sip
SIP_SUBJECTINFO sSubjInfo; ZERO(sSubjInfo);
MS_ADDINFO_BLOB sBlob;
HCRYPTPROV hCryptProv = NULL;
DWORD cbSignerInfo=0;
BYTE *pbSignerInfo=NULL;
PBYTE pbEncodedMessage=NULL;
DWORD cbEncodedMessage=0;
PKITRY {
//init
if(ppSignerContext)
*ppSignerContext=NULL;
if(FALSE==CheckSigncodeSubjectInfo(pSubjectInfo))
PKITHROW(E_INVALIDARG);
// Use the default provider
if(!CryptAcquireContext(&hCryptProv,
NULL,
MS_DEF_PROV,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
PKITHROW(SignError());
//retrieve the enccoded signer info
hr = GetSignedMessageSignerInfo(hCryptProv,
pSubjectInfo,
pSipData,
&pbSignerInfo,
&cbSignerInfo);
if(hr != S_OK) PKITHROW(hr);
sSubjInfo.hProv = hCryptProv;
sSubjInfo.DigestAlgorithm.pszObjId = NULL;
sSubjInfo.dwEncodingType = dwEncodingType;
sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO); // Version
sSubjInfo.pClientData = pSipData;
//set up file information
if(pSubjectInfo->dwSubjectChoice==SIGNER_SUBJECT_FILE)
{
// Open up the file
if((pSubjectInfo->pSignerFileInfo->hFile)==NULL ||
(pSubjectInfo->pSignerFileInfo->hFile)==INVALID_HANDLE_VALUE)
{
if(S_OK != (hr = SignOpenFile(
pSubjectInfo->pSignerFileInfo->pwszFileName, &hFile)))
PKITHROW(hr);
fFileOpen=TRUE;
}
else
hFile=pSubjectInfo->pSignerFileInfo->hFile;
// Get the subject type.
if(S_OK != (hr=SignGetFileType(hFile, pSubjectInfo->pSignerFileInfo->pwszFileName, &gSubjectGuid)))
PKITHROW(hr);
sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
sSubjInfo.hFile = hFile;
sSubjInfo.pwsFileName = pSubjectInfo->pSignerFileInfo->pwszFileName;
}
else
{
memset(&sBlob, 0, sizeof(MS_ADDINFO_BLOB));
sSubjInfo.pgSubjectType=pSubjectInfo->pSignerBlobInfo->pGuidSubject;
sSubjInfo.pwsDisplayName=pSubjectInfo->pSignerBlobInfo->pwszDisplayName;
sSubjInfo.dwUnionChoice=MSSIP_ADDINFO_BLOB;
sSubjInfo.psBlob=&sBlob;
sBlob.cbStruct=sizeof(MS_ADDINFO_BLOB);
sBlob.cbMemObject=pSubjectInfo->pSignerBlobInfo->cbBlob;
sBlob.pbMemObject=pSubjectInfo->pSignerBlobInfo->pbBlob;
}
hr = AddTimeStampSubj(dwEncodingType,
hCryptProv,
&sSubjInfo,
pSubjectInfo->pdwIndex,
pbTimeStampResponse,
cbTimeStampResponse,
pbSignerInfo,
cbSignerInfo,
&pbEncodedMessage,
&cbEncodedMessage);
if ((hFile) && (fFileOpen == TRUE) && !(sSubjInfo.hFile))
{
fFileOpen = FALSE; // we opened it, but, the SIP closed it!
}
if(hr != S_OK) PKITHROW(hr);
//set up the signer context
if(ppSignerContext)
{
//set up the context information
*ppSignerContext=(SIGNER_CONTEXT *)malloc(sizeof(SIGNER_CONTEXT));
if(NULL==(*ppSignerContext))
{
hr=E_OUTOFMEMORY;
PKITHROW(hr);
}
(*ppSignerContext)->cbSize=sizeof(SIGNER_CONTEXT);
(*ppSignerContext)->cbBlob=cbEncodedMessage;
(*ppSignerContext)->pbBlob=pbEncodedMessage;
pbEncodedMessage=NULL;
}
hr=S_OK;
}
PKICATCH(err) {
hr = err.pkiError;
} PKIEND;
if(hFile && (fFileOpen==TRUE)) CloseHandle(hFile);
if(hCryptProv) CryptReleaseContext(hCryptProv, 0);
if(pbSignerInfo) free(pbSignerInfo);
if(pbEncodedMessage)
free(pbEncodedMessage);
return hr;
}
HRESULT WINAPI
AddTimeStampSubj(IN DWORD dwEncodingType,
IN HCRYPTPROV hCryptProv,
IN LPSIP_SUBJECTINFO pSipInfo,
IN DWORD *pdwIndex,
IN PBYTE pbTimeStampResponse,
IN DWORD cbTimeStampResponse,
IN PBYTE pbEncodedSignerInfo,
IN DWORD cbEncodedSignerInfo,
OUT PBYTE* ppbMessage,
OUT DWORD* pcbMessage
)
{
HRESULT hr = S_OK;
SIP_DISPATCH_INFO sSip; ZERO(sSip); // Table of sip functions
DWORD cbSignedMsg = 0;
PBYTE pbSignedMsg = 0;
DWORD dwCertEncoding = 0;
DWORD dwMsgType = 0;
HCRYPTMSG hMsg = NULL;
PBYTE pbEncodedSigner = NULL;
DWORD cbEncodedSigner = 0;
PBYTE pbEncodedSignMsg = NULL; // Encoding for the statement attribute
DWORD cbEncodedSignMsg = 0; // :
PBYTE pbCounterSign = NULL;
DWORD cbCounterSign = 0;
CERT_INFO *pbCertInfo = NULL;
DWORD cbCertInfo = 0;
HCERTSTORE hTmpCertStore=NULL;
PCCERT_CONTEXT pCert = NULL;
PCCRL_CONTEXT pCrl = NULL;
PCRYPT_ATTRIBUTES pbUnauth = NULL;
DWORD cbUnauth = 0;
DWORD dwFileVersionSize=0;
DWORD dwFile=0;
BYTE *pVersionInfo=NULL;
VS_FIXEDFILEINFO *pFixedFileInfo=NULL;
UINT unitFixedFileInfo=0;
PKITRY {
// Use CryptMsg to crack the encoded PKCS7 Signed Message
if (!(hMsg = CryptMsgOpenToDecode(dwEncodingType,
0, // dwFlags
dwMsgType,
hCryptProv,
NULL, // pRecipientInfo
NULL)))
PKITHROW(E_UNEXPECTED);
if (!CryptMsgUpdate(hMsg,
pbTimeStampResponse,
cbTimeStampResponse,
TRUE)) // fFinal
PKITHROW(SignError());
//get the encoded signer BLOB
CryptMsgGetParam(hMsg,
CMSG_ENCODED_SIGNER,
0,
NULL,
&cbEncodedSigner);
if (cbEncodedSigner == 0) PKITHROW(S_FALSE); // no attributes
pbEncodedSigner = (PBYTE) malloc(cbEncodedSigner);
if(!pbEncodedSigner) PKITHROW(E_OUTOFMEMORY);
if (!CryptMsgGetParam(hMsg,
CMSG_ENCODED_SIGNER,
0,
pbEncodedSigner,
&cbEncodedSigner))
PKITHROW(SignError());
//get the timestamp signer's cert info
if(!CryptMsgGetParam(hMsg,
CMSG_SIGNER_CERT_INFO_PARAM,
0,
NULL,
&cbCertInfo))
PKITHROW(SignError());
if (cbCertInfo == 0) PKITHROW(SignError());
pbCertInfo = (CERT_INFO *) malloc(cbCertInfo);
if(!pbCertInfo) PKITHROW(E_OUTOFMEMORY);
if (!CryptMsgGetParam(hMsg,
CMSG_SIGNER_CERT_INFO_PARAM,
0,
pbCertInfo,
&cbCertInfo))
PKITHROW(SignError());
// get the cert store from the timestamp response
hTmpCertStore = CertOpenStore(CERT_STORE_PROV_MSG,
dwEncodingType,
hCryptProv,
CERT_STORE_NO_CRYPT_RELEASE_FLAG,
hMsg);
if (hTmpCertStore == NULL) PKITHROW(SignError());
//find the timestamper's certificate
pCert = CertGetSubjectCertificateFromStore(
hTmpCertStore,
X509_ASN_ENCODING,
pbCertInfo);
if(NULL == pCert)
{
hr=HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
PKITHROW(hr);
}
//make sure the timestamper's certiricate is either from verisign,
// or has the correct key usage
/* if(!ValidTimestampCert(pCert))
{
hr=TRUST_E_TIME_STAMP;
PKITHROW(hr);
} */
//Compare hashed signature of the orinigal signed message
//with the authenticated attribute from the timestamp respoonse.
//they have to match
if(pbEncodedSignerInfo!=NULL && cbEncodedSignerInfo!=0)
{
//verify the signature of the timestamp
if(0==CryptMsgControl(hMsg,0,CMSG_CTRL_VERIFY_SIGNATURE,
pCert->pCertInfo))
{
hr=HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
PKITHROW(hr);
}
//verify the signatures
if(!CryptMsgVerifyCountersignatureEncoded(
hCryptProv,
dwEncodingType,
pbEncodedSignerInfo,
cbEncodedSignerInfo,
pbEncodedSigner,
cbEncodedSigner,
pCert->pCertInfo))
{
hr=HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
PKITHROW(hr);
}
}//end of the counter signature verificate
//release the cert context
if(pCert)
{
CertFreeCertificateContext(pCert);
pCert=NULL;
}
//close the certstore
if(hTmpCertStore)
{
CertCloseStore(hTmpCertStore, 0);
hTmpCertStore=NULL;
}
// get the cert store from the file
hTmpCertStore = CertOpenStore(CERT_STORE_PROV_MSG,
dwEncodingType,
hCryptProv,
CERT_STORE_NO_CRYPT_RELEASE_FLAG,
hMsg);
if (hTmpCertStore == NULL) PKITHROW(SignError());
CryptMsgClose(hMsg);
hMsg = NULL;
// Load up the sip functions.
if(!CryptSIPLoad(pSipInfo->pgSubjectType, // GUID for the requried sip
0, // Reserved
&sSip)) // Table of functions
PKITHROW(SignError());
sSip.pfGet(pSipInfo,
&dwCertEncoding,
*pdwIndex,
&cbSignedMsg,
NULL);
if(cbSignedMsg == 0) PKITHROW(SignError());
pbSignedMsg = (PBYTE) malloc(cbSignedMsg);
if (!pbSignedMsg) PKITHROW(E_OUTOFMEMORY);
if(!sSip.pfGet(pSipInfo,
&dwCertEncoding,
*pdwIndex,
&cbSignedMsg,
pbSignedMsg))
PKITHROW(SignError()); // Real error.
if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
{
if(dwCertEncoding != dwEncodingType)
PKITHROW(TRUST_E_NOSIGNATURE);
}
if ((GET_CMSG_ENCODING_TYPE(dwEncodingType) & PKCS_7_ASN_ENCODING) &&
SignNoContentWrap(pbSignedMsg, cbSignedMsg))
dwMsgType = CMSG_SIGNED;
// Use CryptMsg to crack the encoded PKCS7 Signed Message
if (!(hMsg = CryptMsgOpenToDecode(dwEncodingType,
0, // dwFlags
dwMsgType,
hCryptProv,
NULL, // pRecipientInfo
NULL)))
PKITHROW(E_UNEXPECTED);
if (!CryptMsgUpdate(hMsg,
pbSignedMsg,
cbSignedMsg,
TRUE)) // fFinal
PKITHROW(SignError());
// Encode up the signer info from the timestamp response and
// add it as an unauthenticated attribute.
CRYPT_ATTRIBUTE sAttr;
CRYPT_ATTR_BLOB sSig;
sSig.pbData = pbEncodedSigner;
sSig.cbData = cbEncodedSigner;
sAttr.pszObjId = szOID_RSA_counterSign;
sAttr.cValue = 1;
sAttr.rgValue = &sSig;
CryptEncodeObject(dwEncodingType,
PKCS_ATTRIBUTE,
&sAttr,
pbCounterSign,
&cbCounterSign);
if(cbCounterSign == 0) PKITHROW(SignError());
pbCounterSign = (PBYTE) malloc(cbCounterSign);
if(!pbCounterSign) PKITHROW(E_OUTOFMEMORY);
if(!CryptEncodeObject(dwEncodingType,
PKCS_ATTRIBUTE,
&sAttr,
pbCounterSign,
&cbCounterSign))
PKITHROW(SignError());
CryptMsgGetParam(hMsg,
CMSG_SIGNER_UNAUTH_ATTR_PARAM,
0,
NULL,
&cbUnauth);
if(cbUnauth)
{
//check the version of "crytp32.dll". If it is more than
//"4.0.1381.4", we should be able to timestamp a timestamped
//file
dwFileVersionSize=GetFileVersionInfoSize(szCrypt32,&dwFile);
if(!dwFileVersionSize)
PKITHROW(SignError());
pVersionInfo=(BYTE *)malloc(dwFileVersionSize);
if(!pVersionInfo)
PKITHROW(SignError());
if(!GetFileVersionInfo(szCrypt32, NULL,dwFileVersionSize,
pVersionInfo))
PKITHROW(SignError());
if(!VerQueryValue(pVersionInfo, "\\", (LPVOID *)&pFixedFileInfo,
&unitFixedFileInfo))
PKITHROW(SignError());
if(pFixedFileInfo->dwFileVersionMS <= dwHighVersion &&
pFixedFileInfo->dwFileVersionLS <= dwLowVersion)
PKITHROW(SignError());
// we delete any existing time stamps since our policy provider
//only support one timestamp per file
pbUnauth = (PCRYPT_ATTRIBUTES) malloc(cbUnauth);
if(!pbUnauth) PKITHROW(E_OUTOFMEMORY);
if(!CryptMsgGetParam(hMsg,
CMSG_SIGNER_UNAUTH_ATTR_PARAM,
0,
pbUnauth,
&cbUnauth))
PKITHROW(SignError());
CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA sAttrDel; ZERO(sAttrDel);
sAttrDel.cbSize = sizeof(CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA);
//we always assume there is only one signer
sAttrDel.dwSignerIndex = 0;
for(DWORD ii = 0; ii < pbUnauth->cAttr; ii++)
{
if(strcmp(pbUnauth->rgAttr[ii].pszObjId, szOID_RSA_counterSign) == 0)
{
sAttrDel.dwUnauthAttrIndex = ii;
if (!CryptMsgControl(hMsg,
0,
CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR,
&sAttrDel))
PKITHROW(SignError());
}
}
}
CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA sAttrPara; ZERO(sAttrPara);
sAttrPara.cbSize = sizeof(CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA);
sAttrPara.dwSignerIndex = 0;
sAttrPara.blob.pbData = pbCounterSign;
sAttrPara.blob.cbData = cbCounterSign;
if (!CryptMsgControl(hMsg,
0,
CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR,
&sAttrPara))
PKITHROW(SignError());
// merge all the certificates from the time stamp response
DWORD dwFlags = 0;
while ((pCert = CertEnumCertificatesInStore(hTmpCertStore, pCert))) {
CRYPT_DATA_BLOB blob;
blob.pbData = pCert->pbCertEncoded;
blob.cbData = pCert->cbCertEncoded;
if (!CryptMsgControl(hMsg,
0,
CMSG_CTRL_ADD_CERT,
&blob))
PKITHROW(SignError());
}
while ((pCrl = CertGetCRLFromStore(hTmpCertStore, NULL, pCrl, &dwFlags))) {
CRYPT_DATA_BLOB blob;
blob.pbData = pCrl->pbCrlEncoded;
blob.cbData = pCrl->cbCrlEncoded;
if (!CryptMsgControl(hMsg,
0,
CMSG_CTRL_ADD_CRL,
&blob))
PKITHROW(SignError());
}
// Re-encode up the message and away we go.
CryptMsgGetParam(hMsg,
CMSG_ENCODED_MESSAGE,
0, // dwIndex
NULL, // pbSignedData
&cbEncodedSignMsg);
if (cbEncodedSignMsg == 0) PKITHROW(SignError());
pbEncodedSignMsg = (PBYTE) malloc(cbEncodedSignMsg);
if(!pbEncodedSignMsg) PKITHROW(E_OUTOFMEMORY);
if (!CryptMsgGetParam(hMsg,
CMSG_ENCODED_MESSAGE,
0, // dwIndex
pbEncodedSignMsg,
&cbEncodedSignMsg))
PKITHROW(SignError());
//put the signatures if we are dealing with anything other than the BLOB
if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
{
// Purge all the signatures in the subject
sSip.pfRemove(pSipInfo, *pdwIndex);
// Store the Signed Message in the sip
if(!sSip.pfPut(pSipInfo,
dwEncodingType,
pdwIndex,
cbEncodedSignMsg,
pbEncodedSignMsg))
PKITHROW(SignError());
}
if(ppbMessage && pcbMessage)
{
*ppbMessage = pbEncodedSignMsg;
pbEncodedSignMsg = NULL;
*pcbMessage = cbEncodedSignMsg;
}
}
PKICATCH(err) {
hr = err.pkiError;
} PKIEND;
if(pbUnauth)
free(pbUnauth);
if(pCert)
CertFreeCertificateContext(pCert);
if(pCrl)
CertFreeCRLContext(pCrl);
if(hTmpCertStore)
CertCloseStore(hTmpCertStore, 0);
if(pbCounterSign)
free(pbCounterSign);
if(pbEncodedSignMsg)
free(pbEncodedSignMsg);
if (hMsg)
CryptMsgClose(hMsg);
if(pbEncodedSigner)
free(pbEncodedSigner);
if(pbSignedMsg)
free(pbSignedMsg);
if(pVersionInfo)
free(pVersionInfo);
if(pbCertInfo)
free(pbCertInfo);
return hr;
}
HRESULT WINAPI
SignerCreateTimeStampRequest(
IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject based on which to create a timestamp request
IN PCRYPT_ATTRIBUTES psRequest, // Optional, attributes added to Time stamp request
IN LPVOID pSipData,
OUT PBYTE pbTimeStampRequest,
IN OUT DWORD* pcbTimeStampRequest)
{
HRESULT hr = S_OK;
BOOL fResult=FALSE;
DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; // For this version we default to this.
PBYTE pbDigest = NULL;
DWORD cbDigest = 0;
PKITRY {
if((!pcbTimeStampRequest) ||(FALSE==CheckSigncodeSubjectInfo(pSubjectInfo)))
PKITHROW(E_INVALIDARG);
if(*pcbTimeStampRequest == 0)
pbTimeStampRequest = NULL;
// Retrieve the digest from the signature on the file.
hr = GetSignedMessageDigest(pSubjectInfo,
pSipData,
&pbDigest,
&cbDigest);
if(hr != S_OK) PKITHROW(hr);
hr = TimeStampRequest(dwEncodingType,
psRequest,
pbDigest,
cbDigest,
pbTimeStampRequest,
pcbTimeStampRequest);
if(hr != S_OK) PKITHROW(hr);
}
PKICATCH(err) {
hr = err.pkiError;
} PKIEND;
if(pbDigest) free(pbDigest);
return hr;
}
HRESULT WINAPI
GetSignedMessageDigest(IN SIGNER_SUBJECT_INFO *pSubjectInfo, //Required: The subject based on which to create a timestamp request
IN LPVOID pSipData,
IN OUT PBYTE* ppbDigest,
IN OUT DWORD* pcbDigest)
{
HRESULT hr = S_OK;
HANDLE hFile = NULL;
BOOL fFileOpen=FALSE;
GUID gSubjectGuid; // The subject guid used to load the sip
MS_ADDINFO_BLOB sBlob;
SIP_SUBJECTINFO sSubjInfo; ZERO(sSubjInfo);
DWORD dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; // For this version we default to this.
PKITRY {
if((!pcbDigest) || (!ppbDigest) || (FALSE==CheckSigncodeSubjectInfo(pSubjectInfo)))
PKITHROW(E_INVALIDARG);
*ppbDigest = NULL;
// Set up the sip information (this is based on mssip.h)
sSubjInfo.dwEncodingType = dwEncodingType;
sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO); // Version
sSubjInfo.pClientData = pSipData;
//set up file information
if(pSubjectInfo->dwSubjectChoice==SIGNER_SUBJECT_FILE)
{
// Open up the file
if((pSubjectInfo->pSignerFileInfo->hFile)==NULL ||
(pSubjectInfo->pSignerFileInfo->hFile)==INVALID_HANDLE_VALUE)
{
if(S_OK != (hr = SignOpenFile(
pSubjectInfo->pSignerFileInfo->pwszFileName, &hFile)))
PKITHROW(hr);
fFileOpen=TRUE;
}
else
hFile=pSubjectInfo->pSignerFileInfo->hFile;
// Get the subject type.
if(S_OK != (hr=SignGetFileType(hFile, pSubjectInfo->pSignerFileInfo->pwszFileName, &gSubjectGuid)))
PKITHROW(hr);
sSubjInfo.pgSubjectType = (GUID*) &gSubjectGuid;
sSubjInfo.hFile = hFile;
sSubjInfo.pwsFileName = pSubjectInfo->pSignerFileInfo->pwszFileName;
}
else
{
memset(&sBlob, 0, sizeof(MS_ADDINFO_BLOB));
sSubjInfo.pgSubjectType=pSubjectInfo->pSignerBlobInfo->pGuidSubject;
sSubjInfo.pwsDisplayName=pSubjectInfo->pSignerBlobInfo->pwszDisplayName;
sSubjInfo.dwUnionChoice=MSSIP_ADDINFO_BLOB;
sSubjInfo.psBlob=&sBlob;
sBlob.cbStruct=sizeof(MS_ADDINFO_BLOB);
sBlob.cbMemObject=pSubjectInfo->pSignerBlobInfo->cbBlob;
sBlob.pbMemObject=pSubjectInfo->pSignerBlobInfo->pbBlob;
}
hr = GetSignedMessageDigestSubj(dwEncodingType,
NULL,
&sSubjInfo,
pSubjectInfo->pdwIndex,
ppbDigest,
pcbDigest);
if ((hFile) && (fFileOpen == TRUE) && !(sSubjInfo.hFile))
{
fFileOpen = FALSE; // we opened it, but, the SIP closed it!
}
if(hr != S_OK) PKITHROW(hr);
}
PKICATCH(err) {
hr = err.pkiError;
} PKIEND;
if(hFile && (fFileOpen==TRUE)) CloseHandle(hFile);
return hr;
}
HRESULT WINAPI
GetSignedMessageDigestSubj(IN DWORD dwEncodingType,
IN HCRYPTPROV hCryptProv,
IN LPSIP_SUBJECTINFO pSipInfo,
IN DWORD *pdwIndex,
IN OUT PBYTE* ppbTimeDigest,
IN OUT DWORD* pcbTimeDigest)
{
HRESULT hr = S_OK;
SIP_DISPATCH_INFO sSip; ZERO(sSip); // Table of sip functions
DWORD cbSignedMsg = 0;
PBYTE pbSignedMsg = 0;
DWORD dwCertEncoding = 0;
DWORD dwMsgType = 0;
HCRYPTMSG hMsg = NULL;
BOOL fAcquiredCryptProv = FALSE;
DWORD cbTimeDigest=0;
BYTE *pbTimeDigest=NULL;
PKITRY {
if(!pcbTimeDigest || !ppbTimeDigest)
PKITHROW(E_INVALIDARG);
*ppbTimeDigest=NULL;
*pcbTimeDigest=0;
if(hCryptProv == NULL)
{
if(!CryptAcquireContext(&hCryptProv,
NULL,
MS_DEF_PROV,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
PKITHROW(SignError());
fAcquiredCryptProv = TRUE;
//update the subject Info
if(NULL==(pSipInfo->hProv))
pSipInfo->hProv=hCryptProv;
}
// Load up the sip functions.
if(!CryptSIPLoad(pSipInfo->pgSubjectType, // GUID for the requried sip
0, // Reserved
&sSip)) // Table of functions
PKITHROW(SignError());
sSip.pfGet(pSipInfo,
&dwCertEncoding,
*pdwIndex,
&cbSignedMsg,
NULL);
if(cbSignedMsg == 0) PKITHROW(SignError());
pbSignedMsg = (PBYTE) malloc(cbSignedMsg);
if (!pbSignedMsg) PKITHROW(E_OUTOFMEMORY);
if(!sSip.pfGet(pSipInfo,
&dwCertEncoding,
*pdwIndex,
&cbSignedMsg,
pbSignedMsg))
PKITHROW(SignError()); // Real error.
if(pSipInfo->dwUnionChoice != MSSIP_ADDINFO_BLOB)
{
if(dwCertEncoding != dwEncodingType)
PKITHROW(TRUST_E_NOSIGNATURE);
}
if ((GET_CMSG_ENCODING_TYPE(dwEncodingType) & PKCS_7_ASN_ENCODING) &&
SignNoContentWrap(pbSignedMsg, cbSignedMsg))
dwMsgType = CMSG_SIGNED;
// Use CryptMsg to crack the encoded PKCS7 Signed Message
if (!(hMsg = CryptMsgOpenToDecode(dwEncodingType,
0, // dwFlags
dwMsgType,
hCryptProv,
NULL, // pRecipientInfo
NULL)))
PKITHROW(E_UNEXPECTED);
if (!CryptMsgUpdate(hMsg,
pbSignedMsg,
cbSignedMsg,
TRUE)) // fFinal
PKITHROW(SignError());
if(!CryptMsgGetParam(hMsg,
CMSG_ENCRYPTED_DIGEST,
0,
NULL,
&cbTimeDigest))
PKITHROW(SignError());
//allocate memory
pbTimeDigest = (PBYTE)malloc(cbTimeDigest);
if(!pbTimeDigest)
PKITHROW(E_OUTOFMEMORY);
if(!CryptMsgGetParam(hMsg,
CMSG_ENCRYPTED_DIGEST,
0,
pbTimeDigest,
&cbTimeDigest))
PKITHROW(SignError());
//copy the information
*ppbTimeDigest=pbTimeDigest;
*pcbTimeDigest=cbTimeDigest;
hr=S_OK;
}
PKICATCH(err) {
hr = err.pkiError;
} PKIEND;
if (hMsg)
CryptMsgClose(hMsg);
if(pbSignedMsg)
free(pbSignedMsg);
if((hr!=S_OK) && (pbTimeDigest))
free(pbTimeDigest);
if(fAcquiredCryptProv)
CryptReleaseContext(hCryptProv, 0);
return hr;
}
HRESULT WINAPI
TimeStampRequest(IN DWORD dwEncodingType,
IN PCRYPT_ATTRIBUTES psRequest,
IN PBYTE pbDigest,
IN DWORD cbDigest,
OUT PBYTE pbTimeRequest,
IN OUT DWORD* pcbTimeRequest)
{
HRESULT hr = S_OK;
CRYPT_TIME_STAMP_REQUEST_INFO sTimeRequest; ZERO(sTimeRequest);
PBYTE pbEncodedRequest = NULL;
DWORD cbEncodedRequest = 0;
PKITRY {
if(!pcbTimeRequest)
PKITHROW(E_INVALIDARG);
if(*pcbTimeRequest == 0)
pbTimeRequest = NULL;
sTimeRequest.pszTimeStampAlgorithm = SPC_TIME_STAMP_REQUEST_OBJID;
sTimeRequest.pszContentType = szOID_RSA_data;
sTimeRequest.Content.pbData = pbDigest;
sTimeRequest.Content.cbData = cbDigest;
if(psRequest) {
sTimeRequest.cAttribute = psRequest->cAttr;
sTimeRequest.rgAttribute = psRequest->rgAttr;
}
CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
PKCS_TIME_REQUEST,
&sTimeRequest,
pbEncodedRequest,
&cbEncodedRequest);
if(cbEncodedRequest == 0) PKITHROW(SignError());
pbEncodedRequest = (PBYTE) malloc(cbEncodedRequest);
if(!pbEncodedRequest) PKITHROW(E_OUTOFMEMORY);
if(!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
PKCS_TIME_REQUEST,
&sTimeRequest,
pbEncodedRequest,
&cbEncodedRequest))
PKITHROW(SignError());
//return the infomation
if(*pcbTimeRequest==0)
{
*pcbTimeRequest=cbEncodedRequest;
hr=S_OK;
}
else
{
if(*pcbTimeRequest < cbEncodedRequest)
{
hr=ERROR_MORE_DATA;
PKITHROW(SignError());
}
else
{
memcpy(pbTimeRequest, pbEncodedRequest, cbEncodedRequest);
hr=S_OK;
}
}
}
PKICATCH(err) {
hr = err.pkiError;
} PKIEND;
if(pbEncodedRequest)
free(pbEncodedRequest);
return hr;
}