windows-nt/Source/XPSP1/NT/base/subsys/sm/sfc/dll/crypto.c
2020-09-26 16:20:57 +08:00

1001 lines
29 KiB
C

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
crypto.c
Abstract:
Implementation of crypto access.
Author:
Wesley Witt (wesw) 18-Dec-1998
Revision History:
Andrew Ritz (andrewr) 7-Jul-1999 : added comments
--*/
#include "sfcp.h"
#pragma hdrstop
typedef BOOL
(WINAPI *PCRYPTCATADMINRESOLVECATALOGPATH)(
IN HCATADMIN hCatAdmin,
IN WCHAR *pwszCatalogFile,
IN OUT CATALOG_INFO *psCatInfo,
IN DWORD dwFlags
);
BOOL
SfcRestoreSingleCatalog(
IN PCWSTR CatalogName,
IN PCWSTR CatalogFullPath
);
//
// pointers to the crypto functions we call
//
PCRYPTCATADMINRESOLVECATALOGPATH pCryptCATAdminResolveCatalogPath;
//
// global system catalog guid we pass into WinVerifyTrust
//
GUID DriverVerifyGuid = DRIVER_ACTION_VERIFY;
//
// Specifies if crypto API is initialized
//
BOOL g_bCryptoInitialized = FALSE;
NTSTATUS g_CryptoStatus = STATUS_SUCCESS;
//
// critical section to protect crypto initialization and exception packages file tree
//
RTL_CRITICAL_SECTION g_GeneralCS;
BOOL
MyCryptCATAdminResolveCatalogPath(
IN HCATADMIN hCatAdmin,
IN WCHAR *pwszCatalogFile,
IN OUT CATALOG_INFO *psCatInfo,
IN DWORD dwFlags
)
{
ExpandEnvironmentStrings(
L"%systemroot%\\system32\\catroot\\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\\",
psCatInfo->wszCatalogFile,
MAX_PATH);
wcscat(psCatInfo->wszCatalogFile,pwszCatalogFile);
return TRUE;
}
BOOL
SfcValidateSingleCatalog(
IN PCWSTR CatalogNameFullPath
)
/*++
Routine Description:
Routine to determine if the specified system catalog has a valid signature.
Arguments:
CatalogNameFullPath - null terminated string indicating full path to
catalog file to be validated
Return Value:
Win32 error code indicating outcome.
--*/
{
ULONG SigErr = ERROR_SUCCESS;
WINTRUST_DATA WintrustData;
WINTRUST_FILE_INFO WintrustFileInfo;
DRIVER_VER_INFO OsAttrVersionInfo;
OSVERSIONINFO OsVersionInfo;
ASSERT(CatalogNameFullPath != NULL);
//
// build up the structure to pass into winverifytrust
//
ZeroMemory( &WintrustData, sizeof(WINTRUST_DATA) );
WintrustData.cbStruct = sizeof(WINTRUST_DATA);
WintrustData.dwUIChoice = WTD_UI_NONE;
WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WintrustData.dwStateAction = WTD_STATEACTION_IGNORE;
WintrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
WintrustData.dwUnionChoice = WTD_CHOICE_FILE;
WintrustData.pFile = &WintrustFileInfo;
ZeroMemory( &WintrustFileInfo, sizeof(WINTRUST_FILE_INFO) );
WintrustFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
WintrustFileInfo.pcwszFilePath = CatalogNameFullPath;
//
// Initialize the DRIVER_VER_INFO structure to validate
// against 5.0 and 5.1 OSATTR
//
ZeroMemory( &OsVersionInfo, sizeof(OSVERSIONINFO));
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
ZeroMemory(&OsAttrVersionInfo, sizeof(DRIVER_VER_INFO));
OsAttrVersionInfo.cbStruct = sizeof(DRIVER_VER_INFO);
OsAttrVersionInfo.dwPlatform = VER_PLATFORM_WIN32_NT;
OsAttrVersionInfo.sOSVersionLow.dwMajor = 5;
OsAttrVersionInfo.sOSVersionLow.dwMinor = 0;
if (GetVersionEx(&OsVersionInfo)) {
OsAttrVersionInfo.sOSVersionHigh.dwMajor = OsVersionInfo.dwMajorVersion;
OsAttrVersionInfo.sOSVersionHigh.dwMinor = OsVersionInfo.dwMinorVersion;
//Set this only if all went well
WintrustData.pPolicyCallbackData = (LPVOID)(&OsAttrVersionInfo);
}else{
DebugPrint1( LVL_MINIMAL, L"Could not get OS Version while validating single catalog - GetVersionEx failed (%d)", GetLastError() );
}
//
// call winverfifytrust to check signature
//
SigErr = (DWORD)WinVerifyTrust(
NULL,
&DriverVerifyGuid,
&WintrustData
);
if(SigErr != ERROR_SUCCESS) {
DebugPrint2(
LVL_MINIMAL,
L"WinVerifyTrust of catalog %s failed, ec=0x%08x",
CatalogNameFullPath,
SigErr );
SetLastError(SigErr);
return FALSE;
}
//
// Free the pcSignerCertContext member of the DRIVER_VER_INFO struct
// that was allocated in our call to WinVerifyTrust.
//
if (OsAttrVersionInfo.pcSignerCertContext != NULL) {
CertFreeCertificateContext(OsAttrVersionInfo.pcSignerCertContext);
OsAttrVersionInfo.pcSignerCertContext = NULL;
}
return TRUE;
}
BOOL
SfcRestoreSingleCatalog(
IN PCWSTR CatalogName,
IN PCWSTR CatalogFullPath
)
/*++
Routine Description:
Routine to restore the specified catalog. The catalog must be reinstalled
by calling the CryptCATAdminAddCatalog API (pSetupInstallCatalog is a wrapper
for this API).
Note that this function may block if a user is not currently logged on.
Arguments:
CatalogName - name of catalog to be restored. This is just the filename
part of the catalog, not the complete path.
CatalogFullPath - name of catalog file to be restored. This is the full
path to the file so we can validate it when it is restored.
Return Value:
TRUE for success, FALSE for failure.
--*/
{
BOOL b = FALSE;
NTSTATUS Status;
WCHAR Buffer[MAX_PATH];
DWORD d;
PWSTR p;
UNICODE_STRING FileString;
//
// check if the catalog file is in the dllcache, and if so, try to restore
// it
//
if (SfcProtectedDllFileDirectory) {
MYASSERT(SfcProtectedDllPath.Buffer != NULL);
wcscpy(Buffer,SfcProtectedDllPath.Buffer);
pSetupConcatenatePaths(Buffer, CatalogName, MAX_PATH, NULL);
if (!SfcValidateSingleCatalog( Buffer )) {
//
// the catalog in the dll cache is invalid. Get rid of it.
//
DebugPrint1(
LVL_MINIMAL,
L"catalog %s in dllcache is invalid, deleting it.",
Buffer);
RtlInitUnicodeString(&FileString,CatalogName);
SfcDeleteFile(
SfcProtectedDllFileDirectory,
&FileString );
} else {
//
// the catalog in the dll cache is valid. Let's isntall it.
//
d = pSetupInstallCatalog(Buffer,CatalogName,NULL);
if (d == NO_ERROR) {
DebugPrint1(
LVL_MINIMAL,
L"catalog %s was successfully installed.",
CatalogName);
return(SfcValidateSingleCatalog(CatalogFullPath));
} else {
DebugPrint2(
LVL_MINIMAL,
L"catalog %s failed to install, ec = 0x%08x",
Buffer,
d);
//
// we could try to restore from media at this point, but if we
// failed to restore from the dllcache even though that copy is
// valid, I don't see how restoring from media will be any
// more successful.
//
return(FALSE);
}
}
}
//
// either the catalog file was invalid in the dllcache (and has since been
// deleted), or the dllcache isn't initialized to anything valid.
//
// We have to wait for someone to logon so that we can restore the catalog
// from installation media
// -- note that we just restore from media if we're in GUI
// Setup.
//
if (SFCDisable != SFC_DISABLE_SETUP) {
Status = NtWaitForSingleObject(hEventLogon,TRUE,NULL);
if (!NT_SUCCESS(Status)) {
DebugPrint1(
LVL_MINIMAL,
L"Failed waiting for the logon event, ec=0x%08x",
Status);
}
}
if (!SfcProtectedDllFileDirectory) {
ExpandEnvironmentStrings(L"%systemroot%\\system32", Buffer, sizeof(Buffer)/sizeof(WCHAR));
} else {
wcscpy(Buffer,SfcProtectedDllPath.Buffer);
}
p = Buffer;
b = SfcRestoreFileFromInstallMedia(
NULL,
CatalogName,
CatalogName,
p,
NULL,
NULL,
FALSE, // ###
FALSE, // target is NOT cache (it really could be, but
// pretend it isn't for the sake of this call)
(SFCDisable == SFC_DISABLE_SETUP) ? FALSE : TRUE,
NULL );
if (b) {
pSetupConcatenatePaths(Buffer, CatalogName, MAX_PATH, NULL);
d = pSetupInstallCatalog(Buffer,CatalogName,NULL);
b = (d == NO_ERROR);
//
// if we installed the catalog to somewhere besides the dllcache, then
// we need to cleanup the temporary file that we installed.
//
if (!SfcProtectedDllFileDirectory) {
HANDLE hDir;
p = wcsrchr(Buffer,L'\\');
if (*p) {
*p = L'\0';
}
hDir = SfcOpenDir( TRUE, TRUE, Buffer );
RtlInitUnicodeString(&FileString,CatalogName);
SfcDeleteFile( hDir , &FileString );
CloseHandle( hDir );
}
if (d == NO_ERROR) {
DebugPrint1(
LVL_MINIMAL,
L"catalog %s was successfully installed.",
CatalogName);
return(SfcValidateSingleCatalog(CatalogFullPath));
} else {
DebugPrint2(
LVL_MINIMAL,
L"catalog %s failed to install, ec = 0x%08x",
Buffer,
d);
}
}
return(b);
}
BOOL SfcRestoreASingleFile(
IN HCATADMIN hCatAdmin,
IN PUNICODE_STRING FileName,
IN HANDLE DirHandle,
IN PWSTR FilePathPartOnly
)
/*++
Routine Description:
Routine to restore the specified file. We first check for the file in the
dllcache, and if the copy in the dll cache is valid, we use it, otherwise
we restore from media.
Note that this function may block if a user is not currently logged on.
Arguments:
hCatAdmin - catalog context for restoring the file
FileName - unicode string to file to be restored
DirHandle - directory handle of file to be restored
FilePathPartOnly - string indicating the path to the file to be restored.
Return Value:
TRUE for success, FALSE for failure.
--*/
{
BOOL b = FALSE;
NTSTATUS Status;
WCHAR Buffer[MAX_PATH];
HANDLE FileHandle;
//
// check if the file is in the dllcache and signed, and if so, try to restore
// it
//
if (SfcProtectedDllFileDirectory) {
MYASSERT(SfcProtectedDllPath.Buffer != NULL);
wcscpy(Buffer,SfcProtectedDllPath.Buffer);
pSetupConcatenatePaths(Buffer, FileName->Buffer, MAX_PATH, NULL);
Status = SfcOpenFile(
FileName,
SfcProtectedDllFileDirectory,
SHARE_ALL,
&FileHandle );
if (NT_SUCCESS(Status)) {
if (!SfcValidateFileSignature(
hCatAdmin,
FileHandle,
FileName->Buffer,
Buffer)) {
//
// the file in the dll cache is invalid. Get rid of it.
//
DebugPrint1(
LVL_MINIMAL,
L"file %s in dllcache is invalid, deleting it.",
Buffer);
SfcDeleteFile(
SfcProtectedDllFileDirectory,
FileName );
CloseHandle(FileHandle);
FileHandle = NULL;
} else {
//
// the file in the dll cache is valid. copy it into place.
//
Status = SfcCopyFile( SfcProtectedDllFileDirectory,
SfcProtectedDllPath.Buffer,
DirHandle,
FilePathPartOnly,
FileName,
NULL);
if (NT_SUCCESS(Status)) {
DebugPrint1(
LVL_MINIMAL,
L"file %wZ was successfully installed, checking it's signature",
FileName);
CloseHandle(FileHandle);
FileHandle = NULL;
Status = SfcOpenFile(
FileName,
DirHandle,
SHARE_ALL,
&FileHandle);
wcscpy(Buffer,FilePathPartOnly);
pSetupConcatenatePaths(Buffer, FileName->Buffer, MAX_PATH, NULL);
if (NT_SUCCESS(Status)
&& SfcValidateFileSignature(
hCatAdmin,
FileHandle,
FileName->Buffer,
Buffer)) {
DebugPrint1(
LVL_MINIMAL,
L"file %wZ was successfully installed and validated",
FileName);
CloseHandle(FileHandle);
return(TRUE);
} else {
DebugPrint1(
LVL_MINIMAL,
L"file %s failed to validate",
Buffer);
if (FileHandle) {
CloseHandle(FileHandle);
FileHandle = NULL;
}
//
// we could try to restore from media at this point, but if we
// failed to restore from the dllcache even though that copy is
// valid, I don't see how restoring from media will be any
// more successful.
//
return(FALSE);
}
}
}
}
}
//
// either the file file was invalid in the dllcache (and has since been
// deleted), or the dllcache isn't initialized to anything valid.
//
// We have to wait for someone to logon so that we can restore the file
// from installation media
// -- note that we just restore from media if we're in GUI
// Setup.
//
if (SFCDisable != SFC_DISABLE_SETUP) {
MYASSERT( hEventLogon != NULL );
Status = NtWaitForSingleObject(hEventLogon,TRUE,NULL);
if (!NT_SUCCESS(Status)) {
DebugPrint1(
LVL_MINIMAL,
L"Failed waiting for the logon event, ec=0x%08x",
Status);
}
}
b = SfcRestoreFileFromInstallMedia(
NULL,
FileName->Buffer,
FileName->Buffer,
FilePathPartOnly,
NULL,
NULL,
FALSE, // ###
FALSE, // target is NOT cache
(SFCDisable == SFC_DISABLE_SETUP) ? FALSE : TRUE,
NULL );
if (b) {
Status = SfcOpenFile(
FileName,
DirHandle,
SHARE_ALL,
&FileHandle);
wcscpy(Buffer,FilePathPartOnly);
pSetupConcatenatePaths(Buffer, FileName->Buffer, MAX_PATH, NULL);
if (NT_SUCCESS(Status)) {
b = SfcValidateFileSignature(
hCatAdmin,
FileHandle,
FileName->Buffer,
Buffer);
CloseHandle(FileHandle);
DebugPrint2(
LVL_MINIMAL,
L"file %wZ was%s successfully installed and validated",
FileName,
b ? L" " : L" not");
} else {
b = FALSE;
}
} else {
DebugPrint2(
LVL_MINIMAL,
L"file %s failed to install, ec = 0x%08x",
Buffer,
GetLastError());
}
return(b);
}
BOOL
SfcValidateCatalogs(
VOID
)
/*++
Routine Description:
Validates that all system catalogs have a valid signature. If
a system catalog is not signed, then WFP will try to restore the files.
Note that simply copying the file into place is NOT sufficient. Instead,
we must re-register the catalog with the crypto subsystem.
This function runs very early on during WFP initialization, and may rely on
the following:
1) crypto subsystem being initialized so we can check file signatures.
2) syssetup.inf being present on the system and signed. Syssetup.inf
contains the list of system catalogs. If syssetup.inf isn't signed,
we'll have to restore it, and this may require network access or
prompting a user, when one finally logs on.
Arguments:
NONE.
Return Value:
TRUE if all critical system catalogs were validated as OK , FALSE on failure.
If some "non-critical" catalogs fail to validate and restore, we still
return TRUE. We will log an error about the non-critical catalogs failing
to install, however.
--*/
{
NTSTATUS Status;
PWSTR pInfPathOnly, pInfFullPath;
BOOL RetVal = FALSE, CriticalCatalogFailedToValidateOrRestore = FALSE;
HCATADMIN hCatAdmin = NULL;
HANDLE InfDirHandle,InfFileHandle;
UNICODE_STRING FileString;
CATALOG_INFO CatInfo;
PCWSTR CriticalCatalogList[] = {
L"nt5inf.cat",
L"nt5.cat" };
#define CriticalCatalogCount (sizeof(CriticalCatalogList)/sizeof(PCWSTR))
BOOL CriticalCatalogVector[CriticalCatalogCount] = {FALSE};
DWORD i,Count;
HINF hInf;
pInfPathOnly = MemAlloc(sizeof(WCHAR)*MAX_PATH);
if (!pInfPathOnly) {
goto e0;
}
pInfFullPath = MemAlloc(sizeof(WCHAR)*MAX_PATH);
if (!pInfFullPath) {
goto e1;
}
ExpandEnvironmentStrings(L"%systemroot%\\inf", pInfPathOnly, MAX_PATH);
wcscpy(pInfFullPath, pInfPathOnly);
pSetupConcatenatePaths(pInfFullPath, L"syssetup.inf", MAX_PATH, NULL);
InfDirHandle = SfcOpenDir( TRUE, TRUE, pInfPathOnly );
if (!InfDirHandle) {
DebugPrint1( LVL_MINIMAL, L"failed to open inf directory, ec=%d", GetLastError() );
goto e2;
}
RtlInitUnicodeString(&FileString,L"syssetup.inf");
Status = SfcOpenFile( &FileString, InfDirHandle, SHARE_ALL, &InfFileHandle );
if (!NT_SUCCESS(Status)) {
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
DebugPrint( LVL_MINIMAL, L"syssetup.inf is missing. Trying to restore it" );
goto restore_inf;
}
DebugPrint1( LVL_MINIMAL, L"failed to open syssetup.inf, ec=0x%08x", Status );
goto e2;
}
//
// aquire an HCATADMIN so we can check the signature of syssetup.inf.
//
if(!CryptCATAdminAcquireContext(&hCatAdmin, &DriverVerifyGuid, 0)) {
DebugPrint1( LVL_MINIMAL, L"CCAAC() failed, ec=%x", GetLastError() );
return(FALSE);
}
//
// Flush the Cache once before we start any Crypto operations
//
SfcFlushCryptoCache();
if (!SfcValidateFileSignature(
hCatAdmin,
InfFileHandle,
L"syssetup.inf",
pInfFullPath )) {
CloseHandle(InfFileHandle);
DebugPrint1( LVL_MINIMAL, L"syssetup.inf isn't signed, attempting to restore. ec=%x", GetLastError() );
goto restore_inf;
}
CloseHandle(InfFileHandle);
goto full_catalog_validation;
restore_inf:
if (!SfcRestoreASingleFile(
hCatAdmin,
&FileString,
InfDirHandle,
pInfPathOnly
)) {
DebugPrint1( LVL_MINIMAL, L"couldn't restore syssetup.inf, ec=%d", GetLastError() );
goto minimal_catalog_validation;
}
full_catalog_validation:
//
// 2. validate syssetup.inf against that catalog. If syssetup.inf is
// unsigned, then default to checking if nt5inf.cat is signed. If it
// is signed, then restore syssetup.inf and start over, but bail out if
// we've been here before.
//
hInf = SetupOpenInfFile(pInfFullPath, NULL, INF_STYLE_WIN4, NULL);
if (hInf == INVALID_HANDLE_VALUE) {
DebugPrint1(
LVL_MINIMAL,
L"couldn't open syssetup.inf, doing minimal catalog validation, ec=%d",
GetLastError() );
goto minimal_catalog_validation;
}
Count = SetupGetLineCount( hInf, L"ProductCatalogsToInstall");
if (Count == 0) {
DebugPrint(
LVL_MINIMAL,
L"failed to retreive catalogs via syssetup.inf, validate using critical catalog list");
goto minimal_catalog_validation;
}
for (i = 0; i < Count; i++) {
INFCONTEXT InfContext;
WCHAR CatalogName[MAX_PATH];
BOOL SuccessfullyValidatedOrRestoredACatalog = FALSE;
if(SetupGetLineByIndex(
hInf,
L"ProductCatalogsToInstall",
i,
&InfContext) &&
(SetupGetStringField(
&InfContext,
1,
CatalogName,
sizeof(CatalogName)/sizeof(WCHAR),
NULL))) {
CatInfo.cbStruct = sizeof(CATALOG_INFO);
pCryptCATAdminResolveCatalogPath(
hCatAdmin,
CatalogName,
&CatInfo,
0 );
if (!SfcValidateSingleCatalog( CatInfo.wszCatalogFile )) {
if (!SfcRestoreSingleCatalog(
CatalogName,
CatInfo.wszCatalogFile )) {
DWORD j;
DebugPrint2(
LVL_MINIMAL,
L"couldn't restore catalog %s, ec=%d",
CatInfo.wszCatalogFile,
GetLastError() );
for (j = 0; j < CriticalCatalogCount; j++) {
if (0 == _wcsicmp(CatalogName,CriticalCatalogList[j])) {
CriticalCatalogFailedToValidateOrRestore = TRUE;
break;
}
}
} else {
SuccessfullyValidatedOrRestoredACatalog = TRUE;
}
} else {
SuccessfullyValidatedOrRestoredACatalog = TRUE;
}
if (SuccessfullyValidatedOrRestoredACatalog) {
DWORD j;
for (j = 0; j < CriticalCatalogCount; j++) {
if (0 == _wcsicmp(CatalogName,CriticalCatalogList[j])) {
CriticalCatalogVector[j] = TRUE;
break;
}
}
} else {
DWORD LastError = GetLastError();
//
// log an error
//
DebugPrint2(
LVL_MINIMAL,
L"couldn't restore or validate catalog %s, ec=%d",
CatInfo.wszCatalogFile,
LastError );
SfcReportEvent(
MSG_CATALOG_RESTORE_FAILURE,
CatInfo.wszCatalogFile,
NULL,
LastError);
}
} else {
DebugPrint(
LVL_MINIMAL,
L"failed to retreive catalogs via syssetup.inf, validate using critical catalog list");
goto minimal_catalog_validation;
}
}
if (CriticalCatalogFailedToValidateOrRestore) {
RetVal = FALSE;
goto e3;
} else {
CriticalCatalogFailedToValidateOrRestore = FALSE;
for (i = 0; i< CriticalCatalogCount; i++) {
if (!CriticalCatalogVector[i]) {
CriticalCatalogFailedToValidateOrRestore = TRUE;
}
}
RetVal = !CriticalCatalogFailedToValidateOrRestore;
goto e3;
}
MYASSERT(FALSE && "Should never get here");
//
// 3. validate all remaining catalogs in [ProductCatalogsToInstall] section.
// Keep an internal list of critical catalogs, and if any of these fail to
// be signed (and restored), then we should fail this function, and thus
// fail to initialize WFP. Otherwise, we'll treat the other catalogs being
// invalid as a non-fatal error.
minimal_catalog_validation:
CriticalCatalogFailedToValidateOrRestore = FALSE;
for (i = 0; i < CriticalCatalogCount; i++) {
CatInfo.cbStruct = sizeof(CATALOG_INFO);
pCryptCATAdminResolveCatalogPath(
hCatAdmin,
(PWSTR) CriticalCatalogList[i],
&CatInfo,
0 );
if (!SfcValidateSingleCatalog( CatInfo.wszCatalogFile )) {
if (!SfcRestoreSingleCatalog(
CriticalCatalogList[i],
CatInfo.wszCatalogFile )) {
DebugPrint2(
LVL_MINIMAL,
L"couldn't restore critical catalog %s, ec=%d",
CatInfo.wszCatalogFile,
GetLastError() );
CriticalCatalogFailedToValidateOrRestore = TRUE;
}
}
}
RetVal = !CriticalCatalogFailedToValidateOrRestore;
e3:
CryptCATAdminReleaseContext( hCatAdmin, 0 );
e2:
MemFree(pInfFullPath);
e1:
MemFree(pInfPathOnly);
e0:
return(RetVal);
}
NTSTATUS
LoadCrypto(
VOID
)
/*++
Routine Description:
Loads all of the required DLLs that are necessary for
doing driver signing and cataloge verification.
This dynamic calling mechanism is necessary because this
code is actually NOT used by session manager at this time.
It is build here and is used conditionaly at runtime. This
code is linked into SMSS and WINLOGON, but only used by
WINLOGON right now. When the crypto functions are available
as NT functions then the dynamic code here can be removed.
Arguments:
None.
Return Value:
NT status code.
--*/
{
HMODULE hModuleWinTrust;
RtlEnterCriticalSection(&g_GeneralCS);
if(g_bCryptoInitialized)
{
RtlLeaveCriticalSection(&g_GeneralCS);
return g_CryptoStatus; // exit here to avoid cleanup
}
g_bCryptoInitialized = TRUE; // set this anyway so no other thread will enter again
hModuleWinTrust = GetModuleHandleW(L"wintrust.dll");
ASSERT(hModuleWinTrust != NULL);
pCryptCATAdminResolveCatalogPath = SfcGetProcAddress( hModuleWinTrust, "CryptCATAdminResolveCatalogPath" );
if (pCryptCATAdminResolveCatalogPath == NULL) {
pCryptCATAdminResolveCatalogPath = MyCryptCATAdminResolveCatalogPath;
}
if (!SfcValidateCatalogs()) {
DebugPrint1( LVL_MINIMAL, L"LoadCrypto: failed SfcValidateCatalogs, ec=%d", GetLastError() );
g_CryptoStatus = STATUS_NO_SUCH_FILE;
}
RtlLeaveCriticalSection(&g_GeneralCS);
if (!(NT_SUCCESS(g_CryptoStatus))) {
DebugPrint1( LVL_MINIMAL, L"LoadCrypto failed, ec=0x%08x", g_CryptoStatus );
//
// Terminate WFP
//
SfcTerminateWatcherThread();
}
return g_CryptoStatus;
}
void
SfcFlushCryptoCache(
void
)
/*++
Routine Description:
Flushes the crypto catalog cache. Crypto by default maintains a per process based
cache that it uses for fast signature verification. The bad part is that the cache
is not updated if somebody updates (remove/add) a catalog file outside of this process.
This can be a problem with install/uninstall/install of service packs etc. To workaround this
we will need to flush the cache before we do any set of verifications. We want to do this at
the beginning of such a set of operations as we don't want to affect performance by tearing
down the cache before every file verification as we do today.
Arguments:
None.
Return Value:
None.
--*/
{
WINTRUST_DATA WintrustData;
ULONG SigErr = ERROR_SUCCESS;
ZeroMemory(&WintrustData, sizeof(WINTRUST_DATA));
WintrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
WintrustData.cbStruct = sizeof(WINTRUST_DATA);
WintrustData.dwUIChoice = WTD_UI_NONE;
WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WintrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE_FLUSH;
WintrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
//Call WinVerifyTrust to flush the cache
SigErr = (DWORD)WinVerifyTrust(
NULL,
&DriverVerifyGuid,
&WintrustData
);
if(SigErr != ERROR_SUCCESS)
DebugPrint1( LVL_MINIMAL, L"SFCC failed : WinVerifyTrust(1) failed, ec=0x%08x", SigErr );
return;
}