1197 lines
37 KiB
C++
1197 lines
37 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|
|
|