mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2026-07-05 20:48:00 -05:00
Windows: harden EFI Secure Boot CA fallback
Validate SecureBoot firmware data before trusting fallback selection and mark the unsupported-db helper as noreturn. Record unsupported Secure Boot db refusals in EFI loader diagnostics, and avoid stale rescue-disk prompts after a refusal. Reuse the central EFI loader selection policy for elevated signing-support checks instead of duplicating fallback/refusal logic. Translate unsupported Secure Boot db failures across elevation without duplicate generic dialogs, surface stored-PIM refresh failures, and log unattended loader update failures.
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
#include <atlcomcli.h>
|
#include <atlcomcli.h>
|
||||||
#include <atlconv.h>
|
#include <atlconv.h>
|
||||||
#include <comutil.h>
|
#include <comutil.h>
|
||||||
|
#include <string.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "BaseCom.h"
|
#include "BaseCom.h"
|
||||||
#include "BootEncryption.h"
|
#include "BootEncryption.h"
|
||||||
@@ -21,6 +22,11 @@
|
|||||||
|
|
||||||
using namespace VeraCrypt;
|
using namespace VeraCrypt;
|
||||||
|
|
||||||
|
static bool IsUnsupportedEfiSecureBootDbException (const ErrorException &e)
|
||||||
|
{
|
||||||
|
return e.ErrLangId && strcmp (e.ErrLangId, "SYSENC_EFI_UNSUPPORTED_SECUREBOOT_CA") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT CreateElevatedComObject (HWND hwnd, REFGUID guid, REFIID iid, void **ppv)
|
HRESULT CreateElevatedComObject (HWND hwnd, REFGUID guid, REFIID iid, void **ppv)
|
||||||
{
|
{
|
||||||
WCHAR monikerName[1024];
|
WCHAR monikerName[1024];
|
||||||
@@ -318,6 +324,14 @@ DWORD BaseCom::InstallEfiBootLoader (BOOL preserveUserConfig, BOOL hiddenOSCreat
|
|||||||
{
|
{
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
}
|
}
|
||||||
|
catch (ErrorException &e)
|
||||||
|
{
|
||||||
|
if (IsUnsupportedEfiSecureBootDbException (e))
|
||||||
|
return VC_ERROR_EFI_UNSUPPORTED_SECURE_BOOT_DB;
|
||||||
|
|
||||||
|
e.Show (NULL);
|
||||||
|
return ERROR_EXCEPTION_IN_SERVICE;
|
||||||
|
}
|
||||||
catch (Exception &e)
|
catch (Exception &e)
|
||||||
{
|
{
|
||||||
e.Show (NULL);
|
e.Show (NULL);
|
||||||
@@ -451,6 +465,14 @@ DWORD BaseCom::GetEfiBootLoaderSigningSupport (BOOL* pMicrosoft2023UefiCAsSuppor
|
|||||||
{
|
{
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
}
|
}
|
||||||
|
catch (ErrorException &e)
|
||||||
|
{
|
||||||
|
if (IsUnsupportedEfiSecureBootDbException (e))
|
||||||
|
return VC_ERROR_EFI_UNSUPPORTED_SECURE_BOOT_DB;
|
||||||
|
|
||||||
|
e.Show (NULL);
|
||||||
|
return ERROR_EXCEPTION_IN_SERVICE;
|
||||||
|
}
|
||||||
catch (Exception &e)
|
catch (Exception &e)
|
||||||
{
|
{
|
||||||
e.Show (NULL);
|
e.Show (NULL);
|
||||||
|
|||||||
@@ -585,6 +585,8 @@ namespace VeraCrypt
|
|||||||
DWORD result = ElevatedComInstance->InstallEfiBootLoader (preserveUserConfig ? TRUE : FALSE, hiddenOSCreation ? TRUE : FALSE, pim, hashAlg);
|
DWORD result = ElevatedComInstance->InstallEfiBootLoader (preserveUserConfig ? TRUE : FALSE, hiddenOSCreation ? TRUE : FALSE, pim, hashAlg);
|
||||||
if (result != ERROR_SUCCESS)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
if (result == VC_ERROR_EFI_UNSUPPORTED_SECURE_BOOT_DB)
|
||||||
|
throw ErrorException ("SYSENC_EFI_UNSUPPORTED_SECUREBOOT_CA", SRC_POS);
|
||||||
SetLastError (result);
|
SetLastError (result);
|
||||||
throw SystemException(SRC_POS);
|
throw SystemException(SRC_POS);
|
||||||
}
|
}
|
||||||
@@ -662,6 +664,8 @@ namespace VeraCrypt
|
|||||||
DWORD result = ElevatedComInstance->GetEfiBootLoaderSigningSupport (pMicrosoft2023UefiCAsSupported);
|
DWORD result = ElevatedComInstance->GetEfiBootLoaderSigningSupport (pMicrosoft2023UefiCAsSupported);
|
||||||
if (result != ERROR_SUCCESS)
|
if (result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
if (result == VC_ERROR_EFI_UNSUPPORTED_SECURE_BOOT_DB)
|
||||||
|
throw ErrorException ("SYSENC_EFI_UNSUPPORTED_SECUREBOOT_CA", SRC_POS);
|
||||||
SetLastError (result);
|
SetLastError (result);
|
||||||
throw SystemException(SRC_POS);
|
throw SystemException(SRC_POS);
|
||||||
}
|
}
|
||||||
@@ -2823,6 +2827,11 @@ namespace VeraCrypt
|
|||||||
systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
|
systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
|
||||||
|
|
||||||
WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, (wchar_t *) VC_EFI_BOOT_LOADER_RESOURCE_SET_VALUE_NAME, resourceSet);
|
WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, (wchar_t *) VC_EFI_BOOT_LOADER_RESOURCE_SET_VALUE_NAME, resourceSet);
|
||||||
|
if (!resourceSet)
|
||||||
|
{
|
||||||
|
WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, (wchar_t *) VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_ID_VALUE_NAME, 0);
|
||||||
|
WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, (wchar_t *) VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_RESOURCE_SET_VALUE_NAME, 0);
|
||||||
|
}
|
||||||
WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderFirmwareDbLastError", firmwareDbError);
|
WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderFirmwareDbLastError", firmwareDbError);
|
||||||
WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderSelectionReason", selectionReason, FALSE);
|
WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderSelectionReason", selectionReason, FALSE);
|
||||||
WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderSelectionTimeUtc", selectionTimeUtc, FALSE);
|
WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderSelectionTimeUtc", selectionTimeUtc, FALSE);
|
||||||
@@ -3096,49 +3105,6 @@ namespace VeraCrypt
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VC_EFI_BOOTLOADER_SELECTION_TEST
|
|
||||||
static bool FirmwareDbBufferContainsMicrosoft2023UefiCAs (const std::vector<uint8>& db)
|
|
||||||
{
|
|
||||||
FirmwareDbMicrosoftUefiCaSupport support;
|
|
||||||
return FirmwareDbBufferGetMicrosoftUefiCaSupport (db, support) && FirmwareDbMicrosoftUefiCaSupportContains2023Set (support);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool FirmwareDbBufferContainsMicrosoftCorporationUefiCa2011 (const std::vector<uint8>& db)
|
|
||||||
{
|
|
||||||
FirmwareDbMicrosoftUefiCaSupport support;
|
|
||||||
return FirmwareDbBufferGetMicrosoftUefiCaSupport (db, support) && support.ContainsMicrosoftCorporationUefiCa2011;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TestFirmwareDbBufferContainsMicrosoft2023UefiCAs (const uint8* db, size_t dbSize)
|
|
||||||
{
|
|
||||||
std::vector<uint8> firmwareDb;
|
|
||||||
if (dbSize != 0)
|
|
||||||
{
|
|
||||||
if (!db)
|
|
||||||
return false;
|
|
||||||
firmwareDb.assign (db, db + dbSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FirmwareDbBufferContainsMicrosoft2023UefiCAs (firmwareDb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Feed a db captured from a machine that trusts Microsoft Corporation UEFI CA 2011
|
|
||||||
// (for example the output of PowerShell Get-SecureBootUEFI db) to validate detection
|
|
||||||
// of the 2011 modulus against real firmware data.
|
|
||||||
bool TestFirmwareDbBufferContainsMicrosoftCorporationUefiCa2011 (const uint8* db, size_t dbSize)
|
|
||||||
{
|
|
||||||
std::vector<uint8> firmwareDb;
|
|
||||||
if (dbSize != 0)
|
|
||||||
{
|
|
||||||
if (!db)
|
|
||||||
return false;
|
|
||||||
firmwareDb.assign (db, db + dbSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FirmwareDbBufferContainsMicrosoftCorporationUefiCa2011 (firmwareDb);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool TryFirmwareDbGetMicrosoftUefiCaSupport (FirmwareDbMicrosoftUefiCaSupport& support)
|
static bool TryFirmwareDbGetMicrosoftUefiCaSupport (FirmwareDbMicrosoftUefiCaSupport& support)
|
||||||
{
|
{
|
||||||
std::vector<uint8> db;
|
std::vector<uint8> db;
|
||||||
@@ -3175,11 +3141,19 @@ namespace VeraCrypt
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bSecureBootEnabled = (secureBoot.size () >= 1) && (secureBoot[0] == 1);
|
if (secureBoot.size () != 1 || (secureBoot[0] != 0 && secureBoot[0] != 1))
|
||||||
|
{
|
||||||
|
if (pLastError)
|
||||||
|
*pLastError = ERROR_INVALID_DATA;
|
||||||
|
SetLastError (ERROR_INVALID_DATA);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bSecureBootEnabled = secureBoot[0] == 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ThrowUnsupportedEfiSecureBootDb (const wchar_t *reason, DWORD firmwareDbError)
|
static __declspec(noreturn) void ThrowUnsupportedEfiSecureBootDb (const wchar_t *reason, DWORD firmwareDbError)
|
||||||
{
|
{
|
||||||
RecordEfiBootLoaderResourceSetSelectionDiagnostics (0, reason, firmwareDbError);
|
RecordEfiBootLoaderResourceSetSelectionDiagnostics (0, reason, firmwareDbError);
|
||||||
throw ErrorException ("SYSENC_EFI_UNSUPPORTED_SECUREBOOT_CA", SRC_POS);
|
throw ErrorException ("SYSENC_EFI_UNSUPPORTED_SECUREBOOT_CA", SRC_POS);
|
||||||
@@ -3261,7 +3235,8 @@ namespace VeraCrypt
|
|||||||
if (!bSecureBootStateKnown && !IsFirmwareDbUnavailableError (secureBootLastError))
|
if (!bSecureBootStateKnown && !IsFirmwareDbUnavailableError (secureBootLastError))
|
||||||
ThrowUnsupportedEfiSecureBootDb (L"firmware db and Secure Boot state could not be read; refusing to select an unsupported EFI bootloader signing CA", dwError);
|
ThrowUnsupportedEfiSecureBootDb (L"firmware db and Secure Boot state could not be read; refusing to select an unsupported EFI bootloader signing CA", dwError);
|
||||||
|
|
||||||
ThrowUnsupportedEfiSecureBootDb (L"firmware db could not be read; refusing to select an unsupported EFI bootloader signing CA", dwError);
|
// All Secure Boot state cases are handled above.
|
||||||
|
TC_THROW_FATAL_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ThrowMissingEfiResource (const wchar_t* resourceName, bool rescueDisk)
|
static void ThrowMissingEfiResource (const wchar_t* resourceName, bool rescueDisk)
|
||||||
@@ -6133,54 +6108,7 @@ namespace VeraCrypt
|
|||||||
throw SystemException (SRC_POS);
|
throw SystemException (SRC_POS);
|
||||||
}
|
}
|
||||||
|
|
||||||
FirmwareDbMicrosoftUefiCaSupport support;
|
*pMicrosoft2023UefiCAsSupported = GetPreferredEfiBootLoaderResourceSet ().ResourceSet == VC_EFI_BOOT_LOADER_RESOURCE_SET_2023;
|
||||||
if (!TryFirmwareDbGetMicrosoftUefiCaSupport (support))
|
|
||||||
{
|
|
||||||
DWORD dwError = GetLastError ();
|
|
||||||
bool bSecureBootEnabled = false;
|
|
||||||
bool bSecureBootStateKnown = TryFirmwareSecureBootEnabled (bSecureBootEnabled);
|
|
||||||
DWORD secureBootLastError = bSecureBootStateKnown ? ERROR_SUCCESS : GetLastError ();
|
|
||||||
if (bSecureBootStateKnown && bSecureBootEnabled)
|
|
||||||
ThrowUnsupportedEfiSecureBootDb (L"Secure Boot is enabled but firmware db could not be read; refusing to select an unsupported EFI bootloader signing CA", dwError);
|
|
||||||
|
|
||||||
if (!bSecureBootStateKnown && !IsFirmwareDbUnavailableError (secureBootLastError))
|
|
||||||
ThrowUnsupportedEfiSecureBootDb (L"firmware db and Secure Boot state could not be read; refusing to select an unsupported EFI bootloader signing CA", dwError);
|
|
||||||
|
|
||||||
*pMicrosoft2023UefiCAsSupported = FALSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FirmwareDbMicrosoftUefiCaSupportContains2023Set (support))
|
|
||||||
{
|
|
||||||
*pMicrosoft2023UefiCAsSupported = TRUE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (support.ContainsMicrosoftCorporationUefiCa2011)
|
|
||||||
{
|
|
||||||
*pMicrosoft2023UefiCAsSupported = FALSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bSecureBootEnabled = false;
|
|
||||||
bool bSecureBootStateKnown = TryFirmwareSecureBootEnabled (bSecureBootEnabled);
|
|
||||||
DWORD secureBootLastError = bSecureBootStateKnown ? ERROR_SUCCESS : GetLastError ();
|
|
||||||
if (bSecureBootStateKnown && !bSecureBootEnabled)
|
|
||||||
{
|
|
||||||
*pMicrosoft2023UefiCAsSupported = FALSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bSecureBootStateKnown && IsFirmwareDbUnavailableError (secureBootLastError))
|
|
||||||
{
|
|
||||||
*pMicrosoft2023UefiCAsSupported = FALSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bSecureBootStateKnown)
|
|
||||||
ThrowUnsupportedEfiSecureBootDb (L"Secure Boot is enabled but firmware db does not contain Microsoft Corporation UEFI CA 2011 or the Microsoft 2023 UEFI CA pair required by VeraCrypt", ERROR_SUCCESS);
|
|
||||||
|
|
||||||
ThrowUnsupportedEfiSecureBootDb (L"firmware db does not contain a supported Microsoft UEFI CA and Secure Boot state could not be read; refusing to select an unsupported EFI bootloader signing CA", secureBootLastError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SETUP
|
#ifndef SETUP
|
||||||
@@ -6581,8 +6509,19 @@ namespace VeraCrypt
|
|||||||
if (storedPimUpdateNeeded || !CheckBootloaderFingerprint (true))
|
if (storedPimUpdateNeeded || !CheckBootloaderFingerprint (true))
|
||||||
InstallBootLoader (device, true, false, pim, cryptoInfo->pkcs5);
|
InstallBootLoader (device, true, false, pim, cryptoInfo->pkcs5);
|
||||||
}
|
}
|
||||||
|
catch (Exception &e)
|
||||||
|
{
|
||||||
|
if (storedPimUpdateNeeded)
|
||||||
|
{
|
||||||
|
e.Show (hwndDlg);
|
||||||
|
result = ERR_OS_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{}
|
{
|
||||||
|
if (storedPimUpdateNeeded)
|
||||||
|
result = ERR_OS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest));
|
CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,6 @@ using namespace std;
|
|||||||
|
|
||||||
namespace VeraCrypt
|
namespace VeraCrypt
|
||||||
{
|
{
|
||||||
#ifdef VC_EFI_BOOTLOADER_SELECTION_TEST
|
|
||||||
bool TestFirmwareDbBufferContainsMicrosoft2023UefiCAs (const uint8* db, size_t dbSize);
|
|
||||||
bool TestFirmwareDbBufferContainsMicrosoftCorporationUefiCa2011 (const uint8* db, size_t dbSize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class File
|
class File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ enum
|
|||||||
#define VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_ID_VALUE_NAME L"EfiBootLoaderRescueDiskPromptId"
|
#define VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_ID_VALUE_NAME L"EfiBootLoaderRescueDiskPromptId"
|
||||||
#define VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_RESOURCE_SET_VALUE_NAME L"EfiBootLoaderRescueDiskPromptResourceSet"
|
#define VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_RESOURCE_SET_VALUE_NAME L"EfiBootLoaderRescueDiskPromptResourceSet"
|
||||||
#define VC_EFI_BOOT_LOADER_RESCUE_DISK_RESOURCE_SET_VALUE_NAME L"EfiBootLoaderRescueDiskResourceSet"
|
#define VC_EFI_BOOT_LOADER_RESCUE_DISK_RESOURCE_SET_VALUE_NAME L"EfiBootLoaderRescueDiskResourceSet"
|
||||||
|
#define VC_ERROR_EFI_UNSUPPORTED_SECURE_BOOT_DB ((DWORD) 0xE0000201)
|
||||||
|
|
||||||
#define VC_FILENAME_RENAMED_SUFFIX L"_old"
|
#define VC_FILENAME_RENAMED_SUFFIX L"_old"
|
||||||
|
|
||||||
|
|||||||
@@ -10886,8 +10886,13 @@ static void SystemFavoritesServiceUpdateLoaderProcessing (BOOL bForce)
|
|||||||
SystemFavoritesServiceLogInfo (L"SystemFavoritesServiceUpdateLoaderProcessing: InstallBootLoader called");
|
SystemFavoritesServiceLogInfo (L"SystemFavoritesServiceUpdateLoaderProcessing: InstallBootLoader called");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception &)
|
||||||
|
{
|
||||||
|
SystemFavoritesServiceLogError (L"SystemFavoritesServiceUpdateLoaderProcessing failed while updating the boot loader.");
|
||||||
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
SystemFavoritesServiceLogError (L"SystemFavoritesServiceUpdateLoaderProcessing failed with an unexpected exception while updating the boot loader.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11197,8 +11202,13 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpsz
|
|||||||
bootEnc.InstallBootLoader (true);
|
bootEnc.InstallBootLoader (true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception &)
|
||||||
|
{
|
||||||
|
SystemFavoritesServiceLogError (L"PostOOBE boot loader update failed.");
|
||||||
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
SystemFavoritesServiceLogError (L"PostOOBE boot loader update failed with an unexpected exception.");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1807,6 +1807,12 @@ BOOL UpgradeBootLoader (HWND hwndDlg)
|
|||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
catch (ErrorException &e)
|
||||||
|
{
|
||||||
|
e.Show (hwndDlg);
|
||||||
|
if (e.ErrLangId && strcmp (e.ErrLangId, "SYSENC_EFI_UNSUPPORTED_SECUREBOOT_CA") == 0)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
catch (Exception &e)
|
catch (Exception &e)
|
||||||
{
|
{
|
||||||
e.Show (hwndDlg);
|
e.Show (hwndDlg);
|
||||||
|
|||||||
Reference in New Issue
Block a user