273 lines
6.6 KiB
C++
273 lines
6.6 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: SIPObjPE.cpp
|
|
//
|
|
// Contents: Microsoft SIP Provider
|
|
//
|
|
// History: 15-Feb-1997 pberkman created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "global.hxx"
|
|
|
|
#include "sipobjpe.hxx"
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// construct/destruct:
|
|
//
|
|
|
|
SIPObjectPE_::SIPObjectPE_(DWORD id) : SIPObject_(id)
|
|
{
|
|
this->fUseFileMap = FALSE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// public:
|
|
//
|
|
|
|
BOOL SIPObjectPE_::RemoveSignedDataMsg(SIP_SUBJECTINFO *pSI,DWORD dwIdx)
|
|
{
|
|
if (this->FileHandleFromSubject(pSI, GENERIC_READ | GENERIC_WRITE))
|
|
{
|
|
return(ImageRemoveCertificate(this->hFile, dwIdx));
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
BOOL SIPObjectPE_::CreateIndirectData(SIP_SUBJECTINFO *pSI,DWORD *pdwDLen,
|
|
SIP_INDIRECT_DATA *psData)
|
|
{
|
|
SPC_LINK PeLink;
|
|
BOOL fRet;
|
|
|
|
memset(&PeInfo,0x00,sizeof(SPC_PE_IMAGE_DATA));
|
|
|
|
PeLink.dwLinkChoice = SPC_FILE_LINK_CHOICE;
|
|
PeLink.pwszFile = OBSOLETE_TEXT_W;
|
|
|
|
PeInfo.pFile = &PeLink;
|
|
|
|
this->AllocateAndFillCryptBitBlob(&PeInfo.Flags,pSI->dwFlags,5);
|
|
|
|
fRet = SIPObject_::CreateIndirectData(pSI, pdwDLen, psData);
|
|
|
|
this->DestroyCryptBitBlob(&PeInfo.Flags);
|
|
|
|
return(fRet);
|
|
}
|
|
|
|
BOOL SIPObjectPE_::VerifyIndirectData(SIP_SUBJECTINFO *pSI,
|
|
SIP_INDIRECT_DATA *psData)
|
|
{
|
|
SPC_PE_IMAGE_DATA *pPeInfo;
|
|
DWORD cbPeInfo;
|
|
BOOL fRet;
|
|
|
|
pPeInfo = NULL;
|
|
|
|
|
|
if (!(psData))
|
|
{
|
|
if (this->FileHandleFromSubject(pSI)) // if the file exists, set bad parameter!
|
|
{
|
|
goto InvalidParameter;
|
|
}
|
|
|
|
goto FileOpenFailed;
|
|
}
|
|
|
|
if (!(this->FileHandleFromSubject(pSI)))
|
|
{
|
|
goto FileOpenFailed;
|
|
}
|
|
|
|
if (!(TrustDecode(WVT_MODID_MSSIP, (BYTE **)&pPeInfo, &cbPeInfo, 201,
|
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, this->GetDataOIDHint(),
|
|
psData->Data.Value.pbData, psData->Data.Value.cbData,
|
|
CRYPT_DECODE_NOCOPY_FLAG)))
|
|
{
|
|
goto DecodeError;
|
|
}
|
|
|
|
|
|
if (uCertVersion < WIN_CERT_REVISION_2_0)
|
|
{
|
|
//
|
|
// We are looking at a PE that was signed PRIOR to this version.
|
|
// We need to:
|
|
// 1. if there is "extra" bits at the end (e.g.: InstallShield),
|
|
// FAIL!
|
|
// 2. if there is no "extra" bits, go through the old
|
|
// ImageHelper function to digest. (e.g.: set the version
|
|
// flag.)
|
|
//
|
|
if (!(imagehack_IsImagePEOnly(this->hFile)))
|
|
{
|
|
goto BadDigest;
|
|
}
|
|
}
|
|
|
|
pSI->dwFlags = this->CryptBitBlobToFlags(&pPeInfo->Flags);
|
|
|
|
fRet = SIPObject_::VerifyIndirectData(pSI, psData);
|
|
|
|
CommonReturn:
|
|
|
|
if (pPeInfo)
|
|
{
|
|
TrustFreeDecode(WVT_MODID_MSSIP, (BYTE **)&pPeInfo);
|
|
}
|
|
|
|
return(fRet);
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR_EX(DBG_SS, FileOpenFailed);
|
|
TRACE_ERROR_EX(DBG_SS, DecodeError);
|
|
|
|
SET_ERROR_VAR_EX(DBG_SS, BadDigest, TRUST_E_BAD_DIGEST);
|
|
SET_ERROR_VAR_EX(DBG_SS, InvalidParameter, ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// protected:
|
|
//
|
|
|
|
BOOL SIPObjectPE_::PutMessageInFile(SIP_SUBJECTINFO *pSI,
|
|
WIN_CERTIFICATE *pWinCert,DWORD *pdwIndex)
|
|
{
|
|
if (fSizeFileOnly)
|
|
{
|
|
goto FileResizedError;
|
|
}
|
|
|
|
//
|
|
// check to see if we are going to align the file
|
|
//
|
|
DWORD cbFSize;
|
|
DWORD cbCheck;
|
|
BOOL fRet;
|
|
|
|
cbFSize = GetFileSize(this->hFile, NULL);
|
|
cbCheck = (cbFSize + 7) & ~7;
|
|
cbCheck -= cbFSize;
|
|
|
|
fRet = ImageAddCertificate(this->hFile, pWinCert, pdwIndex);
|
|
|
|
if ((fRet) && (cbCheck > 0))
|
|
{
|
|
//
|
|
// we aligned the file, make sure we null out the padding!
|
|
//
|
|
if (SetFilePointer(this->hFile, cbFSize, NULL, FILE_BEGIN) == 0xFFFFFFFF)
|
|
{
|
|
goto SetFileError;
|
|
}
|
|
|
|
BYTE buf[8];
|
|
DWORD cbWritten;
|
|
|
|
memset(&buf[0], 0x00, cbCheck);
|
|
|
|
if (!(WriteFile(this->hFile, &buf[0], cbCheck, &cbWritten, NULL)) || (cbWritten != cbCheck))
|
|
{
|
|
goto WriteFileError;
|
|
}
|
|
}
|
|
|
|
CommonReturn:
|
|
return(fRet);
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR_EX(DBG_SS, WriteFileError);
|
|
TRACE_ERROR_EX(DBG_SS, SetFileError);
|
|
|
|
SET_ERROR_VAR_EX(DBG_SS, FileResizedError, CRYPT_E_FILERESIZED);
|
|
}
|
|
|
|
|
|
BOOL SIPObjectPE_::GetDigestStream(DIGEST_DATA *pDigestData,
|
|
DIGEST_FUNCTION pfnCallBack, DWORD dwFlags)
|
|
{
|
|
//
|
|
// Check the version flag here. We will have set this based
|
|
// on which version of the image helper function we want to
|
|
// call.
|
|
//
|
|
if (uCertVersion < WIN_CERT_REVISION_2_0)
|
|
{
|
|
return(ImageGetDigestStream( this->hFile,
|
|
dwFlags,
|
|
pfnCallBack,
|
|
pDigestData));
|
|
}
|
|
|
|
BOOL fRet;
|
|
DWORD dwDiskLength;
|
|
|
|
fRet = imagehack_AuImageGetDigestStream( this->hFile,
|
|
dwFlags,
|
|
pfnCallBack,
|
|
pDigestData);
|
|
|
|
dwDiskLength = GetFileSize(this->hFile, NULL);
|
|
|
|
dwDiskLength = (dwDiskLength + 7) & ~7; // padding before the certs?
|
|
|
|
dwDiskLength -= GetFileSize(this->hFile, NULL);
|
|
|
|
if ((fRet) && (dwDiskLength > 0))
|
|
{
|
|
BYTE *pb;
|
|
|
|
if (!(pb = (BYTE *)this->SIPNew(dwDiskLength)))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
memset(pb, 0x00, dwDiskLength); // imagehlp put nulls before the signature!
|
|
|
|
fRet = (*pfnCallBack)(pDigestData, pb, dwDiskLength);
|
|
|
|
delete pb;
|
|
}
|
|
|
|
return(fRet);
|
|
}
|
|
|
|
DWORD SIPObjectPE_::ConvertSPCFlags(DWORD InFlags)
|
|
{
|
|
DWORD ret;
|
|
|
|
ret = 0;
|
|
|
|
if (InFlags & SPC_INC_PE_RESOURCES_FLAG)
|
|
{
|
|
ret |= CERT_PE_IMAGE_DIGEST_RESOURCES;
|
|
}
|
|
if (InFlags & SPC_INC_PE_DEBUG_INFO_FLAG)
|
|
{
|
|
ret |= CERT_PE_IMAGE_DIGEST_DEBUG_INFO;
|
|
}
|
|
if (InFlags & SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG)
|
|
{
|
|
ret |= CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO;
|
|
}
|
|
|
|
return(ret);
|
|
}
|