Skip to content

Commit 330f1f8

Browse files
committed
Windows: notify users after EFI bootloader CA refresh
Record EFI bootloader resource set changes during PostOOBE refreshes and mark a machine-wide rescue disk reminder. Show the reminder on VeraCrypt startup using the existing generic rescue disk prompt and Create Rescue Disk flow.
1 parent 43aa914 commit 330f1f8

3 files changed

Lines changed: 169 additions & 10 deletions

File tree

src/Common/BootEncryption.cpp

Lines changed: 113 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2640,7 +2640,7 @@ namespace VeraCrypt
26402640
IDR_EFI_DCSINFO_2023
26412641
};
26422642

2643-
static const wchar_t *EfiBootLoaderDiagnosticsRegistryKey = L"Software\\VeraCrypt\\Diagnostics\\EfiBootLoader";
2643+
static const wchar_t *EfiBootLoaderDiagnosticsRegistryKey = VC_EFI_BOOT_LOADER_DIAGNOSTICS_REGISTRY_KEY;
26442644

26452645
static bool ReadFirmwareEnvironmentVariableBuffer (const wchar_t* name, const wchar_t* guid, std::vector<uint8>& value, DWORD* pLastError = NULL)
26462646
{
@@ -2732,6 +2732,75 @@ namespace VeraCrypt
27322732
return selection;
27332733
}
27342734

2735+
static bool ReadRecordedEfiBootLoaderResourceSet (DWORD& resourceSet)
2736+
{
2737+
resourceSet = 0;
2738+
return ReadLocalMachineRegistryDword (
2739+
(wchar_t *) EfiBootLoaderDiagnosticsRegistryKey,
2740+
(wchar_t *) VC_EFI_BOOT_LOADER_RESOURCE_SET_VALUE_NAME,
2741+
&resourceSet) && resourceSet != 0;
2742+
}
2743+
2744+
static DWORD ReadEfiBootLoaderRescueDiskPromptId ()
2745+
{
2746+
DWORD promptId = 0;
2747+
ReadLocalMachineRegistryDword (
2748+
(wchar_t *) EfiBootLoaderDiagnosticsRegistryKey,
2749+
(wchar_t *) VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_ID_VALUE_NAME,
2750+
&promptId);
2751+
return promptId;
2752+
}
2753+
2754+
static bool WriteEfiBootLoaderDiagnosticsRegistryDword (const wchar_t *valueName, DWORD value)
2755+
{
2756+
#ifndef SETUP
2757+
if (!IsAdmin () && IsUacSupported ())
2758+
{
2759+
try
2760+
{
2761+
Elevator::WriteLocalMachineRegistryDwordValue ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, (wchar_t *) valueName, value);
2762+
return true;
2763+
}
2764+
catch (...) { }
2765+
2766+
return false;
2767+
}
2768+
#endif
2769+
return WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, (wchar_t *) valueName, value) ? true : false;
2770+
}
2771+
2772+
static void MarkEfiBootLoaderRescueDiskRecreationNeeded (const EfiBootLoaderImages& images)
2773+
{
2774+
if (!images.ResourceSet)
2775+
return;
2776+
2777+
DWORD previousLastError = GetLastError ();
2778+
DWORD promptId = ReadEfiBootLoaderRescueDiskPromptId () + 1;
2779+
if (promptId == 0)
2780+
promptId = 1;
2781+
2782+
WriteEfiBootLoaderDiagnosticsRegistryDword (VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_RESOURCE_SET_VALUE_NAME, images.ResourceSet);
2783+
WriteEfiBootLoaderDiagnosticsRegistryDword (VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_ID_VALUE_NAME, promptId);
2784+
SetLastError (previousLastError);
2785+
}
2786+
2787+
static void RecordEfiBootLoaderRescueDiskResourceSet (const EfiBootLoaderImages& images)
2788+
{
2789+
if (!images.ResourceSet)
2790+
return;
2791+
2792+
DWORD previousLastError = GetLastError ();
2793+
WriteEfiBootLoaderDiagnosticsRegistryDword (VC_EFI_BOOT_LOADER_RESCUE_DISK_RESOURCE_SET_VALUE_NAME, images.ResourceSet);
2794+
SetLastError (previousLastError);
2795+
}
2796+
2797+
static void ClearEfiBootLoaderDiagnosticsRegistry ()
2798+
{
2799+
DWORD previousLastError = GetLastError ();
2800+
::DeleteRegistryKey (HKEY_LOCAL_MACHINE, EfiBootLoaderDiagnosticsRegistryKey);
2801+
SetLastError (previousLastError);
2802+
}
2803+
27352804
static void RecordEfiBootLoaderResourceSetSelection (const EfiBootLoaderImages& images)
27362805
{
27372806
if (!images.ResourceSet || !images.SelectionReason)
@@ -2744,7 +2813,7 @@ namespace VeraCrypt
27442813
StringCchPrintfW (selectionTimeUtc, ARRAYSIZE (selectionTimeUtc), L"%04u-%02u-%02uT%02u:%02u:%02uZ",
27452814
systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
27462815

2747-
WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderResourceSet", images.ResourceSet);
2816+
WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, (wchar_t *) VC_EFI_BOOT_LOADER_RESOURCE_SET_VALUE_NAME, images.ResourceSet);
27482817
WriteLocalMachineRegistryDword ((wchar_t *) EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderFirmwareDbLastError", images.FirmwareDbError);
27492818
WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderSelectionReason", images.SelectionReason, FALSE);
27502819
WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderSelectionTimeUtc", selectionTimeUtc, FALSE);
@@ -3003,18 +3072,18 @@ namespace VeraCrypt
30033072
if (TryFirmwareDbContainsMicrosoft2023UefiCAs (bContainsMicrosoft2023UefiCAs))
30043073
{
30053074
if (bContainsMicrosoft2023UefiCAs)
3006-
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2023, 2023, L"firmware db contains Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023", ERROR_SUCCESS);
3075+
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2023, VC_EFI_BOOT_LOADER_RESOURCE_SET_2023, L"firmware db contains Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023", ERROR_SUCCESS);
30073076

3008-
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, 2011, L"firmware db does not contain both Microsoft 2023 UEFI CAs", ERROR_SUCCESS);
3077+
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, VC_EFI_BOOT_LOADER_RESOURCE_SET_2011, L"firmware db does not contain both Microsoft 2023 UEFI CAs", ERROR_SUCCESS);
30093078
}
30103079

30113080
DWORD dwError = GetLastError ();
30123081
if (IsFirmwareDbUnavailableError (dwError))
3013-
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, 2011, L"firmware db is unavailable; using 2011 compatibility fallback", dwError);
3082+
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, VC_EFI_BOOT_LOADER_RESOURCE_SET_2011, L"firmware db is unavailable; using 2011 compatibility fallback", dwError);
30143083

30153084
bool bSecureBootEnabled = false;
30163085
if (TryFirmwareSecureBootEnabled (bSecureBootEnabled) && !bSecureBootEnabled)
3017-
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, 2011, L"Secure Boot is disabled and firmware db could not be read; using 2011 compatibility fallback", dwError);
3086+
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, VC_EFI_BOOT_LOADER_RESOURCE_SET_2011, L"Secure Boot is disabled and firmware db could not be read; using 2011 compatibility fallback", dwError);
30183087
#ifndef SETUP
30193088
if (!IsAdmin () && IsUacSupported ())
30203089
{
@@ -3024,13 +3093,13 @@ namespace VeraCrypt
30243093
BOOL bElevatedContainsMicrosoft2023UefiCAs = FALSE;
30253094
Elevator::GetEfiBootLoaderSigningSupport (&bElevatedContainsMicrosoft2023UefiCAs);
30263095
if (bElevatedContainsMicrosoft2023UefiCAs)
3027-
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2023, 2023, L"elevated helper reported Microsoft 2023 UEFI CA support", dwError);
3096+
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2023, VC_EFI_BOOT_LOADER_RESOURCE_SET_2023, L"elevated helper reported Microsoft 2023 UEFI CA support", dwError);
30283097

3029-
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, 2011, L"elevated helper did not report Microsoft 2023 UEFI CA support", dwError);
3098+
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, VC_EFI_BOOT_LOADER_RESOURCE_SET_2011, L"elevated helper did not report Microsoft 2023 UEFI CA support", dwError);
30303099
}
30313100
#endif
30323101

3033-
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, 2011, L"firmware db could not be read; using 2011 compatibility fallback", dwError);
3102+
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, VC_EFI_BOOT_LOADER_RESOURCE_SET_2011, L"firmware db could not be read; using 2011 compatibility fallback", dwError);
30343103
}
30353104

30363105
static void ThrowMissingEfiResource (const wchar_t* resourceName, bool rescueDisk)
@@ -3093,6 +3162,35 @@ namespace VeraCrypt
30933162
BackupEfiBootLoaderImageIfDifferent (efiBoot, L"\\EFI\\VeraCrypt\\DcsInfo.dcs", L"\\EFI\\VeraCrypt\\DcsInfo.dcs.vc_backup", images.DcsInfo, images.SizeDcsInfo);
30943163
}
30953164

3165+
static bool EfiBootLoaderImageDiffers (EfiBoot& efiBoot, const wchar_t* imageName, uint8* replacementData, DWORD replacementSize)
3166+
{
3167+
std::vector<uint8> currentImage;
3168+
if (!efiBoot.ReadFileToBuffer (imageName, currentImage))
3169+
return false;
3170+
3171+
return (currentImage.size () != replacementSize)
3172+
|| ((replacementSize != 0) && (memcmp (currentImage.data (), replacementData, replacementSize) != 0));
3173+
}
3174+
3175+
static bool EfiBootLoaderImagesDiffer (EfiBoot& efiBoot, const EfiBootLoaderImages& images)
3176+
{
3177+
return EfiBootLoaderImageDiffers (efiBoot, L"\\EFI\\VeraCrypt\\DcsBoot.efi", images.DcsBoot, images.SizeDcsBoot)
3178+
|| EfiBootLoaderImageDiffers (efiBoot, L"\\EFI\\VeraCrypt\\DcsInt.dcs", images.DcsInt, images.SizeDcsInt)
3179+
|| EfiBootLoaderImageDiffers (efiBoot, L"\\EFI\\VeraCrypt\\DcsCfg.dcs", images.DcsCfg, images.SizeDcsCfg)
3180+
|| EfiBootLoaderImageDiffers (efiBoot, L"\\EFI\\VeraCrypt\\LegacySpeaker.dcs", images.LegacySpeaker, images.SizeLegacySpeaker)
3181+
|| EfiBootLoaderImageDiffers (efiBoot, L"\\EFI\\VeraCrypt\\DcsInfo.dcs", images.DcsInfo, images.SizeDcsInfo);
3182+
}
3183+
3184+
static bool EfiBootLoaderRefreshRequiresRescueDiskPrompt (EfiBoot& efiBoot, const EfiBootLoaderImages& images)
3185+
{
3186+
DWORD recordedResourceSet = 0;
3187+
bool bRecordedResourceSetKnown = ReadRecordedEfiBootLoaderResourceSet (recordedResourceSet);
3188+
if (bRecordedResourceSetKnown && recordedResourceSet == images.ResourceSet)
3189+
return false;
3190+
3191+
return EfiBootLoaderImagesDiffer (efiBoot, images);
3192+
}
3193+
30963194
static void SaveEfiBootLoaderImages (EfiBoot& efiBoot, const EfiBootLoaderImages& images, bool backupExistingImages = false)
30973195
{
30983196
if (backupExistingImages)
@@ -4158,6 +4256,7 @@ namespace VeraCrypt
41584256
const bool bRefreshMsBootloader = !bModifiedMsBoot
41594257
|| bMissingMsBoot
41604258
|| (EfiBootInst.FileExists (szStdMsBootloader) && EfiBootInst.IsVeraCryptBootLoader (szStdMsBootloader));
4259+
const bool bRescueDiskPromptRequired = EfiBootLoaderRefreshRequiresRescueDiskPrompt (EfiBootInst, efiImages);
41614260

41624261
// Keep the firmware-visible loader path valid before the larger module refresh.
41634262
if (bRefreshMsBootloader && !EfiBootInst.FileExists (szStdMsBootloader))
@@ -4215,6 +4314,8 @@ namespace VeraCrypt
42154314
EfiBootInst.CopyFile (L"\\EFI\\VeraCrypt\\DcsBoot.efi", szStdEfiBootloader);
42164315
}
42174316
}
4317+
if (bRescueDiskPromptRequired)
4318+
MarkEfiBootLoaderRescueDiskRecreationNeeded (efiImages);
42184319
return;
42194320
}
42204321
}
@@ -4575,6 +4676,7 @@ namespace VeraCrypt
45754676
{
45764677
File isoFile (isoImagePath, false, true);
45774678
isoFile.Write (RescueZipData, RescueZipSize);
4679+
RecordEfiBootLoaderRescueDiskResourceSet (efiImages);
45784680
}
45794681
}
45804682
else
@@ -5324,6 +5426,8 @@ namespace VeraCrypt
53245426
device.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
53255427
}
53265428

5429+
ClearEfiBootLoaderDiagnosticsRegistry ();
5430+
53275431
if (!IsAdmin() && IsUacSupported())
53285432
{
53295433
Elevator::UpdateSetupConfigFile (false);

src/Common/Dlgcode.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3739,9 +3739,56 @@ void SavePostInstallTasksSettings (int command)
37393739
}
37403740

37413741

3742+
static BOOL ReadEfiBootLoaderDiagnosticsDword (const wchar_t *valueName, DWORD *value)
3743+
{
3744+
return ReadLocalMachineRegistryDword (
3745+
(wchar_t *) VC_EFI_BOOT_LOADER_DIAGNOSTICS_REGISTRY_KEY,
3746+
(wchar_t *) valueName,
3747+
value);
3748+
}
3749+
3750+
3751+
static BOOL EfiBootLoaderRescueDiskResourceSetMatches (DWORD resourceSet)
3752+
{
3753+
DWORD rescueDiskResourceSet = 0;
3754+
3755+
return resourceSet != 0
3756+
&& ReadEfiBootLoaderDiagnosticsDword (VC_EFI_BOOT_LOADER_RESCUE_DISK_RESOURCE_SET_VALUE_NAME, &rescueDiskResourceSet)
3757+
&& rescueDiskResourceSet == resourceSet;
3758+
}
3759+
3760+
3761+
static BOOL IsEfiBootLoaderRescueDiskPromptPending (void)
3762+
{
3763+
DWORD promptId = 0;
3764+
DWORD recordedResourceSet = 0;
3765+
DWORD promptResourceSet = 0;
3766+
3767+
if (ReadEfiBootLoaderDiagnosticsDword (VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_ID_VALUE_NAME, &promptId) && promptId != 0)
3768+
{
3769+
if (!ReadEfiBootLoaderDiagnosticsDword (VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_RESOURCE_SET_VALUE_NAME, &promptResourceSet))
3770+
{
3771+
if (!ReadEfiBootLoaderDiagnosticsDword (VC_EFI_BOOT_LOADER_RESOURCE_SET_VALUE_NAME, &promptResourceSet))
3772+
return FALSE;
3773+
}
3774+
3775+
return !EfiBootLoaderRescueDiskResourceSetMatches (promptResourceSet);
3776+
}
3777+
3778+
if (ReadEfiBootLoaderDiagnosticsDword (VC_EFI_BOOT_LOADER_RESOURCE_SET_VALUE_NAME, &recordedResourceSet)
3779+
&& recordedResourceSet == VC_EFI_BOOT_LOADER_RESOURCE_SET_2023)
3780+
{
3781+
return !EfiBootLoaderRescueDiskResourceSetMatches (recordedResourceSet);
3782+
}
3783+
3784+
return FALSE;
3785+
}
3786+
3787+
37423788
void DoPostInstallTasks (HWND hwndDlg)
37433789
{
37443790
BOOL bDone = FALSE;
3791+
BOOL bEfiBootLoaderRescueDiskPromptPending = IsEfiBootLoaderRescueDiskPromptPending ();
37453792

37463793
if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL)))
37473794
{
@@ -3759,7 +3806,7 @@ void DoPostInstallTasks (HWND hwndDlg)
37593806
bDone = TRUE;
37603807
}
37613808

3762-
if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK)))
3809+
if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK)) || bEfiBootLoaderRescueDiskPromptPending)
37633810
{
37643811
if (AskYesNo ("AFTER_UPGRADE_RESCUE_DISK", hwndDlg) == IDYES)
37653812
PostMessage (hwndDlg, VC_APPMSG_CREATE_RESCUE_DISK, 0, 0);

src/Common/Dlgcode.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ enum
8282
#define TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES L"Post-Install Task - Release Notes"
8383
#define TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK L"Post-Install Task - Rescue Disk"
8484

85+
#define VC_EFI_BOOT_LOADER_DIAGNOSTICS_REGISTRY_KEY L"Software\\VeraCrypt\\Diagnostics\\EfiBootLoader"
86+
#define VC_EFI_BOOT_LOADER_RESOURCE_SET_2011 2011
87+
#define VC_EFI_BOOT_LOADER_RESOURCE_SET_2023 2023
88+
#define VC_EFI_BOOT_LOADER_RESOURCE_SET_VALUE_NAME L"EfiBootLoaderResourceSet"
89+
#define VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_ID_VALUE_NAME L"EfiBootLoaderRescueDiskPromptId"
90+
#define VC_EFI_BOOT_LOADER_RESCUE_DISK_PROMPT_RESOURCE_SET_VALUE_NAME L"EfiBootLoaderRescueDiskPromptResourceSet"
91+
#define VC_EFI_BOOT_LOADER_RESCUE_DISK_RESOURCE_SET_VALUE_NAME L"EfiBootLoaderRescueDiskResourceSet"
92+
8593
#define VC_FILENAME_RENAMED_SUFFIX L"_old"
8694

8795
/* customer service control code to build device list */

0 commit comments

Comments
 (0)