diff --git a/doc/html/en/VeraCrypt RAM Encryption.html b/doc/html/en/VeraCrypt RAM Encryption.html
index 26a92816ec..7fe55a46f8 100644
--- a/doc/html/en/VeraCrypt RAM Encryption.html
+++ b/doc/html/en/VeraCrypt RAM Encryption.html
@@ -144,7 +144,8 @@ Additional Security Measures
Starting from version 1.24, VeraCrypt has integrated a mechanism that detects the insertion of new devices into the system when System Encryption is active. If a new device is inserted, master keys are immediately purged from memory, resulting in a Windows BSOD. This protects against attacks using specialized devices to extract memory from running systems. However, for maximum efficiency, this feature should be paired with RAM encryption.
- To enable this feature, navigate to the menu System -> Settings and check the "Clear encryption keys from memory if a new device is inserted" option.
+ To enable this feature, navigate to the menu System -> Settings and check the "Clear encryption keys from memory if a new device is inserted" option.
+ When enabling it, you can also choose to prevent the option from being disabled until Windows restarts (if the option is already enabled, uncheck it and check it again to be offered this choice). VeraCrypt then keeps clearing the keys when a new device is inserted, even if the registry value of the option is changed, and its system service cannot be stopped until Windows restarts. This does not protect against someone with administrator privileges, who can for example terminate the VeraCrypt system service.
Technical Limitations with Hibernation and Fast Startup
diff --git a/src/Common/Apidrvr.h b/src/Common/Apidrvr.h
index bf9f56a707..358c568acc 100644
--- a/src/Common/Apidrvr.h
+++ b/src/Common/Apidrvr.h
@@ -130,6 +130,12 @@
#define TC_IOCTL_ABORT_MOUNT_VOLUME TC_IOCTL (44)
+// Keeps "clear encryption keys from memory if a new device is inserted" enabled until Windows restarts (cannot be undone)
+#define VC_IOCTL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION TC_IOCTL (45)
+
+// OUT - int (non-zero if VC_IOCTL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION was used since Windows started)
+#define VC_IOCTL_IS_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION_LOCKED TC_IOCTL (46)
+
// Undocumented IOCTL sent by Windows 10 when handling EFS data on volumes
#define IOCTL_UNKNOWN_WINDOWS10_EFS_ACCESS 0x455610D8
@@ -448,5 +454,6 @@ typedef struct
#define VC_DRIVER_CONFIG_ENABLE_CPU_RNG 0x800
#define VC_DRIVER_CONFIG_ENABLE_RAM_ENCRYPTION 0x1000
#define VC_DRIVER_CONFIG_ENABLE_ORDERED_FLUSH_BARRIERS 0x2000
+#define VC_DRIVER_CONFIG_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION 0x4000
#endif /* _WIN32 */
diff --git a/src/Common/BootEncryption.h b/src/Common/BootEncryption.h
index 4ce5309db6..0c6096970f 100644
--- a/src/Common/BootEncryption.h
+++ b/src/Common/BootEncryption.h
@@ -444,6 +444,7 @@ namespace VeraCrypt
#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_FORCE_SET_BOOTNEXT 0x2
#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_SET_BOOTENTRY 0x4
#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_FORCE_FIRST_BOOTENTRY 0x8
+#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_SUPERSEDED 0x10
#define VC_WINDOWS_UPGRADE_POSTOOBE_CMDLINE_OPTION L"/PostOOBE"
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index f245d693dc..43e6a21413 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -16735,10 +16735,15 @@ bool OneOfKBsInstalled (const wchar_t* szKBs[], int count)
DWORD SendServiceNotification (DWORD dwNotificationCmd)
{
DWORD dwRet = ERROR_INVALID_PARAMETER;
+ DWORD dwServiceControlCode = 0;
// We only support clearing keys on new device insertion
if (VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION == dwNotificationCmd)
+ dwServiceControlCode = VC_SERVICE_CONTROL_BUILD_DEVICE_LIST;
+ else if (VC_SERVICE_CONTROL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION == dwNotificationCmd)
+ dwServiceControlCode = VC_SERVICE_CONTROL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION;
+
+ if (dwServiceControlCode)
{
- DWORD dwServiceControlCode = VC_SERVICE_CONTROL_BUILD_DEVICE_LIST;
// send this control code to VeraCrypt SystemFavorites service
SC_HANDLE hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT);
if (hSCManager != NULL)
@@ -16764,6 +16769,17 @@ DWORD SendServiceNotification (DWORD dwNotificationCmd)
return dwRet;
}
+BOOL IsClearKeysOnNewDeviceInsertionLocked ()
+{
+ int locked = 0;
+ DWORD dwResult;
+
+ if (!DeviceIoControl (hDriver, VC_IOCTL_IS_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION_LOCKED, NULL, 0, &locked, sizeof (locked), &dwResult, NULL))
+ return FALSE;
+
+ return locked ? TRUE : FALSE;
+}
+
DWORD FastResizeFile (const wchar_t* filePath, __int64 fileSize)
{
DWORD dwRet = ERROR_INVALID_PARAMETER;
diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h
index 82e99287cd..a7686fb3eb 100644
--- a/src/Common/Dlgcode.h
+++ b/src/Common/Dlgcode.h
@@ -116,6 +116,9 @@ enum
/* customer service control code to build device list */
#define VC_SERVICE_CONTROL_BUILD_DEVICE_LIST 128
+/* customer service control code to apply VC_DRIVER_CONFIG_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION. Every local user can send
+ custom controls to the service: the action is authorized by the flag, which only an administrator can set */
+#define VC_SERVICE_CONTROL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION 129
#ifndef USER_DEFAULT_SCREEN_DPI
#define USER_DEFAULT_SCREEN_DPI 96
@@ -645,6 +648,7 @@ void SafeOpenURL (LPCWSTR szUrl);
BitLockerEncryptionStatus GetBitLockerEncryptionStatus(WCHAR driveLetter);
BOOL IsTestSigningModeEnabled ();
DWORD SendServiceNotification (DWORD dwNotificationCmd);
+BOOL IsClearKeysOnNewDeviceInsertionLocked ();
DWORD FastResizeFile (const wchar_t* filePath, __int64 fileSize);
#if !defined(SETUP) && !defined(VCSDK_DLL)
void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed);
diff --git a/src/Common/Language.xml b/src/Common/Language.xml
index a7e7839747..65c3c37843 100644
--- a/src/Common/Language.xml
+++ b/src/Common/Language.xml
@@ -1740,6 +1740,8 @@
This check covers only the active Windows boot manager. Before revocation, also verify that decryption fallback and rescue backups are compatible. Creating a new VeraCrypt Rescue Disk can reuse an older stored boot-manager backup; creating the disk alone does not establish that backup's compatibility with the revocation.
The Windows Boot Manager backup included in this Rescue Disk is signed by Microsoft Windows Production PCA 2011. Your firmware already contains Windows UEFI CA 2023.\n\nAfter PCA 2011 revocation (AvailableUpdates bit 0x80, including combined value 0x280), restoring this backup can leave Windows unable to start with Secure Boot enabled. Creating a new Rescue Disk reuses this stored backup; it does not update its signature.\n\nBefore applying the revocation, prepare compatible, updated Windows recovery media and verify the decryption fallback. Do not rely on this Rescue Disk to restore a compatible Windows Boot Manager. It remains useful for other VeraCrypt recovery tasks.
VeraCrypt could not check the Windows Boot Manager backup in this Rescue Disk against the firmware Secure Boot policy.\n\nCreating or verifying this disk does not establish that its stored Windows Boot Manager is compatible with PCA 2011 revocation (AvailableUpdates bit 0x80, including combined value 0x280). Before applying the revocation, verify your recovery backups and prepare compatible, updated Windows recovery media.
+ Do you also want to prevent this option from being disabled until Windows restarts?\n\nIf you answer Yes, the option cannot be turned off in VeraCrypt or in the registry, and the VeraCrypt system service cannot be stopped, until Windows restarts. If you need to connect a new device before then, you will have to restart Windows first.\n\nNote: this does not protect against someone who has administrator privileges on this computer, who can, for example, terminate the VeraCrypt system service.
+ VeraCrypt could not prevent the option "Clear encryption keys from memory if a new device is inserted" from being disabled until Windows restarts.\n\nThe option is enabled, but it can still be disabled.
diff --git a/src/Driver/Ntdriver.c b/src/Driver/Ntdriver.c
index 5b32992ec1..facea16ad5 100644
--- a/src/Driver/Ntdriver.c
+++ b/src/Driver/Ntdriver.c
@@ -136,6 +136,7 @@ BOOL CacheBootPassword = FALSE;
BOOL CacheBootPim = FALSE;
BOOL NonAdminSystemFavoritesAccessDisabled = FALSE;
BOOL BlockSystemTrimCommand = FALSE;
+static BOOL ClearKeysOnNewDeviceInsertionLocked = FALSE; // set once, cleared only by a restart
BOOL AllowWindowsDefrag = FALSE;
BOOL EraseKeysOnShutdown = TRUE; // by default, we erase encryption keys on system shutdown
static size_t EncryptionThreadPoolFreeCpuCountLimit = 0;
@@ -3146,6 +3147,27 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
}
break;
+ case VC_IOCTL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION:
+ if (UserCanAccessDriveDevice())
+ {
+ ClearKeysOnNewDeviceInsertionLocked = TRUE;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ }
+ else
+ Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
+
+ Irp->IoStatus.Information = 0;
+ break;
+
+ case VC_IOCTL_IS_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION_LOCKED:
+ if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput))
+ {
+ *(int *) Irp->AssociatedIrp.SystemBuffer = ClearKeysOnNewDeviceInsertionLocked ? 1 : 0;
+ Irp->IoStatus.Information = sizeof (int);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ }
+ break;
+
case VC_IOCTL_ENCRYPTION_QUEUE_PARAMS:
if (ValidateIOBufferSize (Irp, sizeof (EncryptionQueueParameters), ValidateOutput))
{
@@ -3581,6 +3603,8 @@ LPWSTR TCTranslateCode (ULONG ulCode)
TC_CASE_RET_NAME (VC_IOCTL_EMERGENCY_CLEAR_ALL_KEYS);
TC_CASE_RET_NAME (VC_IOCTL_IS_RAM_ENCRYPTION_ENABLED);
TC_CASE_RET_NAME (VC_IOCTL_ENCRYPTION_QUEUE_PARAMS);
+ TC_CASE_RET_NAME (VC_IOCTL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION);
+ TC_CASE_RET_NAME (VC_IOCTL_IS_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION_LOCKED);
TC_CASE_RET_NAME (IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS);
@@ -4963,10 +4987,10 @@ NTSTATUS ReadRegistryConfigFlags (BOOL driverEntry)
if (flags & VC_DRIVER_CONFIG_BLOCK_SYS_TRIM)
BlockSystemTrimCommand = TRUE;
- /* clear VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION if it is set */
- if (flags & VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION)
+ /* clear VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION and its lock request if they are set */
+ if (flags & (VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION | VC_DRIVER_CONFIG_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION))
{
- flags ^= VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION;
+ flags &= ~(VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION | VC_DRIVER_CONFIG_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION);
WriteRegistryConfigFlags (flags);
}
diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c
index 400b4e164f..fbc2d4dc25 100644
--- a/src/Mount/Mount.c
+++ b/src/Mount/Mount.c
@@ -11172,6 +11172,13 @@ static void SystemFavoritesServiceUpdateSetupConfigFile ()
static void SystemFavoritesServiceUpdateLoaderProcessing (BOOL bForce, const GUID *requestId = NULL)
{
SystemFavoritesServiceLogInfo (L"SystemFavoritesServiceUpdateLoaderProcessing called");
+ // Set by Setup if it could not stop the service (for example while clearing keys on new device insertion is locked):
+ // this executable is replaced when Windows restarts and must not reinstall its own, older boot loader until then.
+ if (BootEncObj->ReadServiceConfigurationFlags () & VC_SYSTEM_FAVORITES_SERVICE_CONFIG_SUPERSEDED)
+ {
+ SystemFavoritesServiceLogInfo (L"SystemFavoritesServiceUpdateLoaderProcessing skipped: a new version is installed and replaces this executable when Windows restarts");
+ return;
+ }
GUID notificationGeneration = {};
DWORD notifications = ReadSetupNotifications (¬ificationGeneration);
BootLoaderUpdateResult result = {};
@@ -11307,6 +11314,13 @@ static void SystemFavoritesServiceUpdateLoaderProcessing (BOOL bForce, const GUI
// Global vector containing all devices previsouly knwon to the system
std::vector g_Devices;
+// Once locked, the option stays enabled until Windows restarts, whatever the registry says
+static BOOL IsClearKeysOnNewDeviceInsertionEnabled ()
+{
+ return (ReadDriverConfigurationFlags() & VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION)
+ || IsClearKeysOnNewDeviceInsertionLocked ();
+}
+
static DWORD WINAPI SystemFavoritesServiceCtrlHandler ( DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
@@ -11314,8 +11328,16 @@ static DWORD WINAPI SystemFavoritesServiceCtrlHandler ( DWORD dwControl,
{
switch (dwControl)
{
- case SERVICE_CONTROL_PRESHUTDOWN:
case SERVICE_CONTROL_STOP:
+ if (IsClearKeysOnNewDeviceInsertionLocked ())
+ {
+ /* the service clears the keys when a new device is inserted: it is stopped only when Windows shuts down */
+ SystemFavoritesServiceLogInfo (L"SERVICE_CONTROL_STOP ignored: clearing keys on new device insertion is locked until Windows restarts");
+ SystemFavoritesServiceSetStatus (SystemFavoritesServiceStatus.dwCurrentState);
+ break;
+ }
+ // fall through
+ case SERVICE_CONTROL_PRESHUTDOWN:
SystemFavoritesServiceSetStatus (SERVICE_STOP_PENDING);
SystemFavoritesServiceUpdateLoaderProcessing (FALSE);
@@ -11348,7 +11370,7 @@ static DWORD WINAPI SystemFavoritesServiceCtrlHandler ( DWORD dwControl,
{
/* build a list of all devices currently connected to the system */
/* ignore if clear keys configuration is already set */
- if (!(ReadDriverConfigurationFlags() & VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION))
+ if (!IsClearKeysOnNewDeviceInsertionEnabled ())
{
SystemFavoritesServiceLogInfo (L"VC_SERVICE_CONTROL_BUILD_DEVICE_LIST received");
g_Devices.clear ();
@@ -11356,13 +11378,40 @@ static DWORD WINAPI SystemFavoritesServiceCtrlHandler ( DWORD dwControl,
}
}
break;
+ case VC_SERVICE_CONTROL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION:
+ {
+ /* keep clearing keys on new device insertion enabled, and the service running, until Windows restarts.
+ Every local user can send this control: an administrator must have requested it in the registry */
+ const uint32 required = VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION | VC_DRIVER_CONFIG_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION;
+ uint32 flags = ReadDriverConfigurationFlags();
+ if ((flags & required) == required)
+ {
+ DWORD cbBytesReturned = 0;
+ if (DeviceIoControl (hDriver, VC_IOCTL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION, NULL, 0, NULL, 0, &cbBytesReturned, NULL))
+ {
+ SystemFavoritesServiceLogInfo (L"Clearing keys on new device insertion is locked until Windows restarts");
+ SystemFavoritesServiceStatus.dwControlsAccepted &= ~SERVICE_ACCEPT_STOP;
+ }
+ else
+ SystemFavoritesServiceLogError (L"VC_SERVICE_CONTROL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION failed");
+
+ try
+ {
+ SetDriverConfigurationFlag (VC_DRIVER_CONFIG_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION, FALSE);
+ }
+ catch (...) { }
+ }
+
+ SystemFavoritesServiceSetStatus (SystemFavoritesServiceStatus.dwCurrentState);
+ }
+ break;
case SERVICE_CONTROL_DEVICEEVENT:
if (DBT_DEVICEARRIVAL == dwEventType)
{
DEV_BROADCAST_HDR* pHdr = (DEV_BROADCAST_HDR *) lpEventData;
- if (pHdr->dbch_devicetype != DBT_DEVTYP_VOLUME && pHdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
+ if (pHdr->dbch_devicetype != DBT_DEVTYP_VOLUME && pHdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
{
- if (ReadDriverConfigurationFlags() & VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION)
+ if (IsClearKeysOnNewDeviceInsertionEnabled ())
{
BOOL bClearKeys = TRUE;
SystemFavoritesServiceLogInfo (L"SERVICE_CONTROL_DEVICEEVENT - DBT_DEVICEARRIVAL received");
@@ -11469,6 +11518,8 @@ static VOID WINAPI SystemFavoritesServiceMain (DWORD argc, LPTSTR *argv)
SystemFavoritesServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
SystemFavoritesServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
SystemFavoritesServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_PRESHUTDOWN | SERVICE_ACCEPT_SESSIONCHANGE | SERVICE_ACCEPT_POWEREVENT;
+ if (IsClearKeysOnNewDeviceInsertionLocked ())
+ SystemFavoritesServiceStatus.dwControlsAccepted &= ~SERVICE_ACCEPT_STOP;
for (i = 1; i < argc; i++)
{
@@ -11497,6 +11548,14 @@ static VOID WINAPI SystemFavoritesServiceMain (DWORD argc, LPTSTR *argv)
SetUnhandledExceptionFilter (SystemFavoritesServiceExceptionHandler);
_set_invalid_parameter_handler (SystemFavoritesServiceInvalidParameterHandler);
+ // The flag concerned the executable that was running when Setup could not stop it
+ try
+ {
+ if (BootEncObj && (BootEncObj->ReadServiceConfigurationFlags () & VC_SYSTEM_FAVORITES_SERVICE_CONFIG_SUPERSEDED))
+ BootEncObj->SetServiceConfigurationFlag (VC_SYSTEM_FAVORITES_SERVICE_CONFIG_SUPERSEDED, false);
+ }
+ catch (...) { }
+
if (bUpdateLoader)
{
SystemFavoritesServiceSetStatus (SERVICE_START_PENDING, 120000);
@@ -13954,10 +14013,12 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA
static std::string platforminfo;
static uint8 currentUserConfig;
static string currentCustomUserMessage;
+ static BOOL bLockClearKeys;
switch (msg)
{
case WM_INITDIALOG:
+ bLockClearKeys = FALSE;
{
BootEncryptionStatus bootEncStatus = BootEncObj->GetStatus();
if (!bootEncStatus.DriveMounted)
@@ -14045,6 +14106,12 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA
EnableWindow (GetDlgItem (hwndDlg, IDC_BOOT_LOADER_CACHE_PIM), bPasswordCacheEnabled);
CheckDlgButton (hwndDlg, IDC_BOOT_LOADER_CACHE_PIM, (bPasswordCacheEnabled && bPimCacheEnabled)? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton (hwndDlg, IDC_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION, bClearKeysEnabled? BST_CHECKED : BST_UNCHECKED);
+ if (IsClearKeysOnNewDeviceInsertionLocked ())
+ {
+ // locked until Windows restarts: the option cannot be disabled
+ CheckDlgButton (hwndDlg, IDC_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION, BST_CHECKED);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION), FALSE);
+ }
if (bIsHiddenOS)
{
@@ -14186,6 +14253,8 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA
BOOL bPimCacheEnabled = IsDlgButtonChecked (hwndDlg, IDC_BOOT_LOADER_CACHE_PIM);
BOOL bBlockSysEncTrimEnabled = IsDlgButtonChecked (hwndDlg, IDC_BLOCK_SYSENC_TRIM);
BOOL bClearKeysEnabled = IsDlgButtonChecked (hwndDlg, IDC_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION);
+ // when locked, the option cannot be changed and the service needs no notification
+ BOOL bClearKeysLocked = IsClearKeysOnNewDeviceInsertionLocked ();
BOOL bAutoFixBootloader = IsDlgButtonChecked (hwndDlg, IDC_UPDATE_BOOTLOADER_ON_SHUTDOWN);
BOOL bForceVeraCryptNextBoot = FALSE;
@@ -14205,7 +14274,8 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA
std::string techInfo = SRC_POS;
techInfo += "\nIsSystemFavoritesServiceRunning = False.";
ReportUnexpectedState (techInfo.c_str());
- return 1;
+ if (!bClearKeysLocked)
+ return 1;
}
// only write boot configuration if something changed
@@ -14215,7 +14285,7 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA
SetDriverConfigurationFlag (TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD, bPasswordCacheEnabled);
SetDriverConfigurationFlag (TC_DRIVER_CONFIG_CACHE_BOOT_PIM, (bPasswordCacheEnabled && bPimCacheEnabled)? TRUE : FALSE);
SetDriverConfigurationFlag (TC_DRIVER_CONFIG_DISABLE_EVIL_MAID_ATTACK_DETECTION, IsDlgButtonChecked (hwndDlg, IDC_DISABLE_EVIL_MAID_ATTACK_DETECTION));
- if (bClearKeysEnabled)
+ if (bClearKeysEnabled && !bClearKeysLocked)
NotifyService (VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION);
SetDriverConfigurationFlag (VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION, bClearKeysEnabled);
SetServiceConfigurationFlag (VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_UPDATE_LOADER, bAutoFixBootloader? FALSE : TRUE);
@@ -14242,6 +14312,30 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA
return 1;
}
+ // last, so that a failure does not prevent the other settings from being saved
+ if (bLockClearKeys && IsDlgButtonChecked (hwndDlg, IDC_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION)
+ && !IsClearKeysOnNewDeviceInsertionLocked ())
+ {
+ try
+ {
+ SetDriverConfigurationFlag (VC_DRIVER_CONFIG_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION, TRUE);
+ NotifyService (VC_SERVICE_CONTROL_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION);
+ }
+ catch (Exception &) { }
+
+ if (!IsClearKeysOnNewDeviceInsertionLocked ())
+ {
+ // The request must not stay for a later control to the service
+ try
+ {
+ SetDriverConfigurationFlag (VC_DRIVER_CONFIG_LOCK_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION, FALSE);
+ }
+ catch (Exception &) { }
+
+ Error ("CLEAR_KEYS_ON_DEVICE_INSERTION_LOCK_FAILED", hwndDlg);
+ }
+ }
+
EndDialog (hwndDlg, lw);
return 1;
}
@@ -14291,8 +14385,13 @@ static BOOL CALLBACK BootLoaderPreferencesDlgProc (HWND hwndDlg, UINT msg, WPARA
CheckDlgButton (hwndDlg, IDC_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION, BST_UNCHECKED);
}
else
+ {
Warning ("CLEAR_KEYS_ON_DEVICE_INSERTION_WARNING", hwndDlg);
+ bLockClearKeys = (AskWarnNoYes ("CLEAR_KEYS_ON_DEVICE_INSERTION_LOCK_PROMPT", hwndDlg) == IDYES);
+ }
}
+ else
+ bLockClearKeys = FALSE;
break;
diff --git a/src/Setup/Setup.c b/src/Setup/Setup.c
index 23ed2b40b2..0785aa2a23 100644
--- a/src/Setup/Setup.c
+++ b/src/Setup/Setup.c
@@ -993,7 +993,11 @@ BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir)
#endif
// The executable of a service that cannot be stopped is replaced when Windows restarts.
if (!StartStopService (hwndDlg, TC_SYSTEM_FAVORITES_SERVICE_NAME, FALSE, 0, NULL))
+ {
bRestartRequired = TRUE; // The previous executable runs until then
+ // and must not reinstall its own, older boot loader
+ try { BootEncObj.SetServiceConfigurationFlag (VC_SYSTEM_FAVORITES_SERVICE_CONFIG_SUPERSEDED, true); } catch (...) { }
+ }
DWORD copyError = SetupService::UpdateExecutable (szTmp, servicePath);
if (copyError == ERROR_SUCCESS)
{
diff --git a/src/SetupDLL/Setup.c b/src/SetupDLL/Setup.c
index 2e65bef3ce..a5d48fbb67 100644
--- a/src/SetupDLL/Setup.c
+++ b/src/SetupDLL/Setup.c
@@ -2924,6 +2924,9 @@ EXTERN_C UINT STDAPICALLTYPE VC_CustomAction_PostInstall(MSIHANDLE hInstaller)
bootLoaderServiceError = GetLastError () ? GetLastError () : ERROR_GEN_FAILURE;
MSILog (hInstaller, MSI_WARNING_LEVEL, L"VC_CustomAction_PostInstall: failed to stop %s. Error 0x%.8X", TC_SYSTEM_FAVORITES_SERVICE_NAME, bootLoaderServiceError);
bRestartRequired = TRUE; // The previous executable runs until then
+ // and must not reinstall its own, older boot loader
+ try { BootEncObj.SetServiceConfigurationFlag (VC_SYSTEM_FAVORITES_SERVICE_CONFIG_SUPERSEDED, true); }
+ catch (...) { MSILog (hInstaller, MSI_WARNING_LEVEL, L"VC_CustomAction_PostInstall: failed to mark the previous service executable as superseded"); }
}
DWORD copyError = SetupService::UpdateExecutable (szTmp, servicePath);
bootLoaderResultError = copyError;