-At installation, upgrade, repair and system encryption time, VeraCrypt reads the firmware db and selects the loader set whose signing CAs are trusted. If the 2023 CA pair is present, the 2023 set is preferred; otherwise the 2011 set is used when Microsoft Corporation UEFI CA 2011 is trusted. If Secure Boot is enabled and neither set is trusted by the firmware, VeraCrypt refuses to install its bootloader and displays an error instead of installing a loader that the firmware would reject at the next reboot.
+At installation, upgrade, repair and system encryption time, VeraCrypt reads the firmware db and dbx and selects a loader set whose known signing CAs are present in db and not listed in dbx. The optional dbx variable may legitimately be absent (especially on custom-key systems); VeraCrypt treats that state as an empty forbidden database, while a genuine read or parse failure remains an error when Secure Boot is enabled. If the 2023 CA pair is available, the 2023 set is preferred; otherwise the 2011 set is used when Microsoft Corporation UEFI CA 2011 is available. If Secure Boot is enabled and neither set is compatible with the known CA policy, VeraCrypt refuses to install its bootloader rather than knowingly installing a loader whose CA the firmware will reject.
Changing the firmware Secure Boot configuration (for example enabling additional certificates in the BIOS setup) does not by itself rewrite the files already installed on the EFI System Partition. Run VeraCrypt Setup in
Repair/Reinstall mode after changing the firmware Secure Boot database, or let the VeraCrypt System Favorites service refresh the loader automatically (it re-evaluates the selection at Windows startup, session logon/unlock, resume from sleep, and shutdown).
@@ -68,10 +68,27 @@ HKEY_LOCAL_MACHINE\SOFTWARE\VeraCrypt\Diagnostics\EfiBootLoader
EfiBootLoaderResourceSet REG_DWORD 2011 (0x7db) or 2023 (0x7e7)
EfiBootLoaderSelectionReason REG_SZ human readable selection reason
EfiBootLoaderFirmwareDbLastError REG_DWORD last firmware db read/parse error (0 = none)
+ EfiBootLoaderFirmwareDbxLastError REG_DWORD last firmware dbx read/parse error (0 = none)
EfiBootLoaderSelectionTimeUtc REG_SZ time of the last selection
+ EfiBootChainStatusKnown REG_DWORD db/dbx known-CA assessment is available
+ EfiBootChainLastError REG_DWORD last incomplete-assessment error (0 = none)
+ SecureBootEnabled REG_DWORD Secure Boot state at the last assessment
+ FirmwareDbxPresent REG_DWORD dbx exists (0 is valid: optional variable absent)
+ VeraCryptLoaderFilesValid REG_DWORD installed DCS files match one embedded set
+ VeraCryptLoaderKnownCaAllowed REG_DWORD known required CAs are in db and not in dbx
+ VeraCryptLoaderKnownCaRevoked REG_DWORD a known required VeraCrypt CA is in dbx
+ EfiBootLoaderInstalledResourceSet REG_DWORD set identified from the actual ESP files
+ EfiBootLoaderRecordedResourceSet REG_DWORD set recorded at the last successful refresh
+ WindowsLoaderInspectionSucceeded REG_DWORD embedded PE signature was parsed
+ WindowsLoaderPresent REG_DWORD bootmgfw_ms.vc was found
+ WindowsLoaderSigner REG_DWORD 0 (unknown), 2011, or 2023
+ WindowsLoaderKnownCaAllowed REG_DWORD known signing CA is in db and not in dbx
+ WindowsLoaderKnownCaRevoked REG_DWORD known Windows loader signing CA is in dbx
+ WindowsLoaderMigrationRecommended REG_DWORD PCA 2011 copy remains while CA 2023 is available
+ EfiBootChainCheckTimeUtc REG_SZ time of the last attempted chain check
-The following commands, run from an elevated PowerShell prompt, show which Microsoft certificates are present in the firmware db (note that on some firmware the names may not be visible in this simple text search even when the certificates are present):
+The following commands, run from an elevated PowerShell prompt, provide additional evidence. The text search is only a convenience and may not expose certificate names on every firmware. An absent dbx is valid; any other exception needs investigation.
reg query HKLM\SOFTWARE\VeraCrypt\Diagnostics\EfiBootLoader /s
@@ -83,9 +100,33 @@ $t = [Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).Bytes)
'Microsoft UEFI CA 2023',
'Microsoft Option ROM UEFI CA 2023' |
ForEach-Object { "$_ : $($t -match [regex]::Escape($_))" }
+
+try {
+ $dbx = (Get-SecureBootUEFI dbx).Bytes
+ 'Windows PCA 2011 in dbx: ' +
+ ([Text.Encoding]::ASCII.GetString($dbx) -match
+ 'Microsoft Windows Production PCA 2011')
+} catch {
+ 'dbx is absent or could not be read; check FirmwareDbxPresent and EfiBootLoaderFirmwareDbxLastError'
+}
+
+# After mounting the EFI System Partition as S:, inspect the embedded signer.
+# Do not use Get-AuthenticodeSignature here: it may report a catalog signer.
+Get-PfxCertificate -FilePath S:\EFI\Microsoft\Boot\bootmgfw_ms.vc |
+ Select-Object Subject,Issuer,Thumbprint
+
+Get-WinEvent -FilterHashtable @{
+ LogName='System'
+ ProviderName='Microsoft-Windows-TPM-WMI'
+ Id=@(1036,1037,1043,1044,1045,1797,1798,1799,1800,1801,1802,1803)
+ StartTime=(Get-Date).AddDays(-30)
+} | Select-Object TimeCreated,Id,LevelDisplayName,Message
-In addition, the VeraCrypt System Favorites service writes a warning to the Windows Application event log (source VeraCryptSystemFavorites) when it detects that the active Secure Boot db no longer trusts a component of the installed boot chain.
+In addition, the VeraCrypt System Favorites service writes a warning to the Windows Application event log (source VeraCryptSystemFavorites) when installed DCS files do not match an embedded set, the chainloaded Windows Boot Manager is missing or its embedded signer cannot be identified, a known required CA is absent from db or listed in dbx, or a PCA 2011-signed Windows Boot Manager should be migrated before revocation.
+
+
+These values are deliberately described as a known-CA compatibility assessment, not proof that firmware will accept an image. UEFI dbx can also contain individual image hashes, certificate TBS hashes and security-version revocations that this diagnostic does not fully evaluate. A successful controlled reboot with Secure Boot enabled remains the final validation.
The Microsoft 2023 certificate transition
@@ -97,10 +138,10 @@ Two important points for VeraCrypt users:
-Windows deploys the 2023 certificates through a staged, telemetry-driven rollout. Devices are updated automatically only once Microsoft has high confidence in their hardware/firmware combination. Because a system-encrypted VeraCrypt machine boots through a non-standard boot chain (the VeraCrypt loader occupies the Windows Boot Manager location), such machines are typically not classified for automatic update and the rollout does not trigger on its own. The Windows Security app may report that there is "not yet enough data to classify your device". For the same reason, opting into the Microsoft-managed rollout (the MicrosoftUpdateManagedOptIn registry value) may not be sufficient on these machines.
+Windows deploys the 2023 certificates through a staged, telemetry-driven rollout. Devices are updated automatically only once Microsoft has sufficient confidence in their hardware/firmware combination. A VeraCrypt system-encrypted machine has a non-standard boot chain because the VeraCrypt loader occupies the standard Windows Boot Manager location; this may affect servicing checks, but Microsoft does not document VeraCrypt as a categorical exclusion from the rollout. A Windows Security report that there is "not yet enough data to classify your device" describes the current rollout state, not proof that VeraCrypt caused it.
-Microsoft documents a registry value that triggers the update explicitly (see Microsoft KB5068202, "Registry key updates for Secure Boot"). From an elevated command prompt:
+The MicrosoftUpdateManagedOptIn value is a separate opt-in to Microsoft's asynchronous managed rollout. It requires the applicable Windows diagnostic-data configuration and does not guarantee immediate deployment. Do not mix that method with a manual AvailableUpdates deployment; choose one method and monitor it to completion.
+
+
Before triggering the update on a VeraCrypt system-encrypted machine, take the following precautions:
@@ -139,7 +183,10 @@ Before triggering the update on a VeraCrypt system-encrypted machine, take the f
Create or update your VeraCrypt Rescue Disk first, and verify that it boots.
-Do not disable the VeraCrypt System Favorites service or its bootloader update function. When the Windows servicing task installs the 2023-signed Windows Boot Manager at the standard location, this service is what preserves the VeraCrypt boot chain: it saves the new boot manager as bootmgfw_ms.vc (the copy VeraCrypt chainloads after pre-boot authentication) and restores the VeraCrypt loader.
+Record the existing AvailableUpdates value and make sure the device is not already managed by another Secure Boot deployment policy. Setting 0x5944 requests authenticated firmware db/KEK writes and a boot-file replacement. Firmware defects, a missing OEM-authorized KEK, interruption during servicing, or overwriting another pending deployment value can leave the transition incomplete. Use the computer manufacturer's recovery procedure if a firmware variable update fails.
+
+
+Do not disable the VeraCrypt System Favorites service or its bootloader update function. When Windows installs a new Boot Manager at the standard ESP location, the service saves it as bootmgfw_ms.vc and restores the VeraCrypt loader. If Windows leaves the standard path unchanged, current VeraCrypt versions also inspect Windows' serviced copies under %SystemRoot%\Boot\EFI_EX and %SystemRoot%\Boot\EFI, verify the embedded signer, and atomically refresh bootmgfw_ms.vc with the best copy permitted by the known firmware CA policy.
Hidden operating system users should not trigger the update from the hidden OS. The automatic boot-chain preservation is disabled when a hidden OS is running.
@@ -148,23 +195,26 @@ Do not disable the VeraCrypt System Favorites service or its bootloader
Avoid forced power-off between the moment Windows replaces the boot manager and the next normal restart or shutdown. On most systems the VeraCrypt boot entry keeps the machine bootable during this window, but firmware that ignores the boot order could boot the plain Windows Boot Manager, which cannot start an encrypted Windows (recoverable with the Rescue Disk).
-Expect Windows to keep reporting the Secure Boot certificate servicing as not fully completed even after everything works. Windows checks whether the file at the standard boot manager location is the 2023-signed Microsoft Boot Manager; on a VeraCrypt system that location holds the VeraCrypt loader by design. This status is cosmetic and does not affect the security or operation of the system.
+Windows may continue reporting the transition as incomplete because the standard Windows Boot Manager location contains the VeraCrypt loader by design. Treat this as a possible servicing false negative only after the firmware db contains the required 2023 CAs, EfiBootLoaderInstalledResourceSet identifies the actual 2023 DCS files, the embedded issuer of bootmgfw_ms.vc is Windows UEFI CA 2023, and the event log contains no unresolved Secure Boot servicing failure.
-After the db update has been applied, VeraCrypt automatically switches to the 2023 loader set the next time the bootloader is refreshed (Repair/Reinstall, upgrade, or one of the automatic refresh points of the System Favorites service). You can verify the result in the diagnostics registry key described above and recreate the Rescue Disk when prompted.
+After the db update has been applied, VeraCrypt automatically switches to the 2023 DCS set and attempts to import the current 2023-signed Windows Boot Manager the next time the bootloader is refreshed (Repair/Reinstall, upgrade, or one of the automatic refresh points of the System Favorites service). Verify the actual result in the diagnostics registry key and recreate the Rescue Disk when prompted.
+
+
+The Windows PCA 2011 dbx revocation is a later, separate operation documented in
Microsoft KB5025885. Do not request its
0x80 bit (or the combined
0x280 value, which also requests the SVN update) until
bootmgfw_ms.vc is confirmed to be signed by
Windows UEFI CA 2023, recovery media are current, and a controlled reboot with Secure Boot enabled has succeeded. VeraCrypt never enables this revocation automatically.
Recovering from a Secure Boot boot failure
-Two distinct failures can occur when the firmware Secure Boot configuration no longer trusts a component of the boot chain:
+Two distinct failures can occur when the firmware Secure Boot policy rejects a component of the boot chain (because of a missing CA, a CA or image revocation, or another policy restriction):
-
-Before the password prompt (message such as "Secure Boot Violation" or an immediate return to the firmware): the firmware does not trust the CA that signs the installed VeraCrypt loader.
+Before the password prompt (message such as "Secure Boot Violation" or an immediate return to the firmware): the firmware policy rejects the installed VeraCrypt loader.
-
-After successful password entry (an explicit Secure Boot error message from the VeraCrypt loader, or on older loader versions a return to the password prompt): the firmware does not trust the CA that signs the Windows Boot Manager copy (
bootmgfw_ms.vc) that VeraCrypt chainloads.
+After successful password entry (an explicit Secure Boot error message from the VeraCrypt loader, or on older loader versions a return to the password prompt): the firmware policy rejects the Windows Boot Manager copy (bootmgfw_ms.vc) that VeraCrypt chainloads.
@@ -172,19 +222,19 @@ In both cases, the recovery procedure is:
-
-Temporarily disable Secure Boot in the firmware setup and start Windows normally (VeraCrypt pre-boot authentication works with Secure Boot disabled), or boot the VeraCrypt Rescue Disk and use "Restore VeraCrypt loader binaries to system disk".
+Temporarily disable Secure Boot in the firmware setup and start Windows normally (VeraCrypt pre-boot authentication works with Secure Boot disabled). The VeraCrypt Rescue Disk can restore VeraCrypt loader components when they are missing or damaged, but it cannot manufacture a current Windows Boot Manager or make a PCA 2011-signed
bootmgfw_ms.vc acceptable after that CA has been added to dbx; it is not a substitute for completing the Windows migration.
-
-In Windows, adjust the firmware/Windows Secure Boot certificates as needed (enable the third-party CAs in the firmware setup, or apply the Windows Secure Boot certificate updates as described above), then run VeraCrypt Setup in Repair/Reinstall mode.
+In Windows, adjust the firmware/Windows Secure Boot policy as needed (enable the third-party CAs in firmware setup, restore a valid dbx if a custom-key workflow removed it, or apply the Windows Secure Boot certificate updates as described above), then run VeraCrypt Setup in Repair/Reinstall mode. Repair now checks Windows' serviced
EFI_EX/EFI copies and can install a compatible current Windows Boot Manager even while the standard ESP path contains VeraCrypt.
-
-Re-enable Secure Boot.
+Review the VeraCrypt diagnostics and embedded signer as described above, then re-enable Secure Boot and perform a controlled reboot. Do not re-enable it while VeraCrypt reports an incomplete policy assessment or incompatible loader files.
Legacy custom-key procedure (deprecated)
-Older VeraCrypt versions documented a custom-key procedure (the VeraCrypt-DCS SecureBoot script, sb_set_siglists.ps1) that replaced the firmware Secure Boot databases with a custom platform key and the 2011-era Microsoft certificates. This procedure is deprecated and must not be used on systems using the 2023 certificate chain: it removes trust for the 2023-signed Windows Boot Manager and breaks the Windows boot process after VeraCrypt pre-boot authentication. Systems where it was applied should restore the manufacturer Secure Boot keys, then follow the normal procedure described on this page.
+Older VeraCrypt versions documented a custom-key procedure (the VeraCrypt-DCS SecureBoot script, sb_set_siglists.ps1) that replaced PK, KEK, db and dbx with a custom platform key, 2011-era Microsoft certificates and an obsolete bundled dbx. This procedure is deprecated and must not be used on systems using the 2023 certificate chain: it removes trust for the 2023-signed Windows Boot Manager, discards current revocations and can break the Windows handoff after VeraCrypt pre-boot authentication. Systems where it was applied should restore the manufacturer Secure Boot keys and current dbx, then follow the normal procedure described on this page.
diff --git a/doc/html/en/System Encryption.html b/doc/html/en/System Encryption.html
index 48653304..511f3eb9 100644
--- a/doc/html/en/System Encryption.html
+++ b/doc/html/en/System Encryption.html
@@ -73,7 +73,7 @@ Thus, when setting or entering your password, it's crucial to type it manually u
Note: By default, Windows 7 and later boot from a special small partition. The partition contains files that are required to boot the system. Windows allows only applications that have administrator privileges to write to the partition (when the system is
running). In EFI boot mode, which is the default on modern PCs, VeraCrypt can not encrypt this partition since it must remain unencrypted so that the BIOS can load the EFI bootloader from it. This in turn implies that in EFI boot mode, VeraCrypt offers only to encrypt the system partition where Windows is installed (the user can later manually encrypt other data partitions using VeraCrypt).
In MBR legacy boot mode, VeraCrypt encrypts the partition only if you choose to encrypt the whole system drive (as opposed to choosing to encrypt only the partition where Windows is installed).
-
In EFI boot mode with Secure Boot enabled, VeraCrypt selects a Microsoft UEFI CA-signed bootloader set trusted by the active firmware Secure Boot db during install, repair, upgrade, or Windows PostOOBE repair. The 2023 VeraCrypt loader set requires both Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023, while the 2011 loader set requires Microsoft Corporation UEFI CA 2011. If the active db trusts neither supported set, VeraCrypt aborts instead of installing a loader that firmware will reject. If you manually change firmware Secure Boot db entries, run VeraCrypt repair or reinstall to refresh the installed bootloader set. For details, including the Microsoft 2023 certificate transition and recovery procedures, see EFI Secure Boot.
+
In EFI boot mode with Secure Boot enabled, VeraCrypt selects a Microsoft UEFI CA-signed bootloader set allowed by the active firmware Secure Boot policy during install, repair, upgrade, or Windows PostOOBE repair: every required CA must be present in the allowed database (db) and absent from the forbidden database (dbx). The 2023 VeraCrypt loader set requires both Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023, while the 2011 loader set requires Microsoft Corporation UEFI CA 2011. If the active db/dbx policy permits neither supported set, VeraCrypt aborts instead of installing a loader that firmware will reject. If you manually change firmware Secure Boot db or dbx entries, run VeraCrypt repair or reinstall to refresh the installed bootloader set. For details, including the Microsoft 2023 certificate transition and recovery procedures, see EFI Secure Boot.
Next Section >>
diff --git a/doc/html/ru/EFISecureBoot.html b/doc/html/ru/EFISecureBoot.html
index 5eaf1601..3cc58c11 100644
--- a/doc/html/ru/EFISecureBoot.html
+++ b/doc/html/ru/EFISecureBoot.html
@@ -53,7 +53,7 @@
-При установке, обновлении, восстановлении/переустановке и запуске шифрования системы VeraCrypt считывает базу данных подписей прошивки (db) и выбирает набор загрузчиков, чьим подписывающим центрам сертификации доверяет прошивка. Если присутствует пара центров сертификации 2023 года, предпочтение отдаётся набору 2023 года; в противном случае используется набор 2011 года, если прошивка доверяет Microsoft Corporation UEFI CA 2011. Если Secure Boot включён и прошивка не доверяет ни одному набору, VeraCrypt отказывается устанавливать свой загрузчик и выводит ошибку, вместо того чтобы установить загрузчик, который прошивка отклонит при следующей перезагрузке.
+При установке, обновлении, восстановлении/переустановке и запуске шифрования системы VeraCrypt считывает db и dbx прошивки и выбирает набор загрузчиков, известные подписывающие CA которого присутствуют в db и не перечислены в dbx. Необязательная переменная dbx может отсутствовать (особенно при пользовательских ключах); это считается пустой базой запретов, тогда как реальная ошибка чтения или разбора остаётся ошибкой при включённом Secure Boot. Если доступна пара CA 2023 года, предпочтение отдаётся набору 2023 года; иначе используется набор 2011 года при наличии Microsoft Corporation UEFI CA 2011.
Изменение конфигурации Secure Boot в прошивке (например, включение дополнительных сертификатов в настройках BIOS) само по себе не перезаписывает файлы, уже установленные в системном разделе EFI. После изменения базы данных Secure Boot в прошивке запустите установщик VeraCrypt в режиме
Восстановить/переустановить или позвольте службе VeraCrypt System Favorites автоматически обновить загрузчик (она повторно оценивает выбор при запуске Windows, входе в сеанс или разблокировке, выходе из сна и завершении работы).
@@ -68,6 +68,11 @@ HKEY_LOCAL_MACHINE\SOFTWARE\VeraCrypt\Diagnostics\EfiBootLoader
EfiBootLoaderResourceSet REG_DWORD 2011 (0x7db) или 2023 (0x7e7)
EfiBootLoaderSelectionReason REG_SZ понятная человеку причина выбора
EfiBootLoaderFirmwareDbLastError REG_DWORD последняя ошибка чтения/разбора db прошивки (0 = нет)
+ EfiBootLoaderFirmwareDbxLastError REG_DWORD последняя ошибка чтения/разбора dbx (0 = нет)
+ FirmwareDbxPresent REG_DWORD наличие dbx (0 допустим: переменная отсутствует)
+ EfiBootLoaderInstalledResourceSet REG_DWORD набор, определённый по фактическим файлам ESP
+ VeraCryptLoaderFilesValid REG_DWORD файлы DCS совпадают со встроенным набором
+ WindowsLoaderSigner REG_DWORD встроенная подпись: 0, 2011 или 2023
EfiBootLoaderSelectionTimeUtc REG_SZ время последнего выбора
@@ -83,9 +88,13 @@ $t = [Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).Bytes)
'Microsoft UEFI CA 2023',
'Microsoft Option ROM UEFI CA 2023' |
ForEach-Object { "$_ : $($t -match [regex]::Escape($_))" }
+
+# После подключения ESP как S: проверяйте встроенную подпись, а не подпись каталога.
+Get-PfxCertificate -FilePath S:\EFI\Microsoft\Boot\bootmgfw_ms.vc |
+ Select-Object Subject,Issuer,Thumbprint
-Кроме того, служба VeraCrypt System Favorites записывает предупреждение в журнал приложений Windows (источник VeraCryptSystemFavorites), когда обнаруживает, что активная db Secure Boot больше не доверяет одному из компонентов установленной цепочки загрузки.
+Кроме того, служба VeraCrypt System Favorites предупреждает о несовпадении фактических файлов DCS со встроенным набором, отсутствующей или нераспознанной встроенной подписи Windows Boot Manager, известных CA, отсутствующих в db или перечисленных в dbx, и необходимости миграции копии PCA 2011. Это проверка совместимости известных CA, а не доказательство полного доверия: dbx может также отзывать хэши образов, TBS-хэши сертификатов и версии безопасности.
Переход на сертификаты Microsoft 2023 года
@@ -97,10 +106,10 @@ $t = [Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).Bytes)
-
-Истечение срока действия сертификатов не мешает загрузке уже установленных загрузчиков. UEFI-прошивка не проверяет сроки действия сертификатов во время проверки Secure Boot, поэтому загрузчики, подписанные с помощью CA 2011 года, продолжают загружаться после дат истечения срока действия практически на всех реализациях прошивки. Истечение срока действия означает, что новые двоичные файлы больше нельзя подписывать с помощью CA 2011 года, а системы, которые так и не получат сертификаты 2023 года, перестанут получать обновления безопасности цепочки загрузки.
+Истечение срока действия сертификатов обычно не мешает загрузке уже установленных загрузчиков. Проверка образа UEFI Secure Boot обычно не применяет срок действия подписывающего сертификата, поэтому сам факт истечения CA 2011 не вызывает отказ загрузчика. Однако новые двоичные файлы больше нельзя подписывать в этой экосистеме, а системы без сертификатов 2023 года не смогут получать обновления цепочки загрузки, подписанные заменяющими CA.
-
-Будущий отзыв CA 2011 года не позволит загружать подписанные ими загрузчики. Microsoft объявила, что на более позднем этапе перехода (пока не запланированном) CA 2011 года могут быть отозваны через базу данных запрещённых подписей Secure Boot (dbx) на системах, завершивших переход. Поэтому рекомендуется заранее перейти на набор загрузчиков 2023 года.
+Истечение срока действия и отзыв — разные события. Microsoft предоставляет отдельную, выполняемую намеренно меру защиты, которая добавляет Microsoft Windows Production PCA 2011 в базу запрещённых подписей Secure Boot (dbx). После её применения все Windows Boot Manager, подписанные этим CA, отклоняются. Этот отзыв Windows PCA не является частью миграции сертификатов и Boot Manager с помощью
0x5944. По состоянию на июль 2026 года Microsoft сообщает, что не планирует отзывать Microsoft Corporation UEFI CA 2011 — сторонний CA, используемый набором загрузчиков VeraCrypt 2011 года. Тем не менее перед применением отзыва Windows PCA 2011 рекомендуется перевести на CA 2023 года как часть VeraCrypt, так и часть Windows в цепочке загрузки.
@@ -114,10 +123,10 @@ $t = [Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).Bytes)
Обновление существующей системы до сертификатов 2023 года
-Windows распространяет сертификаты 2023 года поэтапно, на основе телеметрии. Устройства обновляются автоматически только после того, как Microsoft получает достаточную уверенность в конкретном сочетании оборудования и прошивки. Поскольку компьютер с системным шифрованием VeraCrypt загружается через нестандартную цепочку загрузки (загрузчик VeraCrypt занимает место Windows Boot Manager), такие компьютеры обычно не классифицируются для автоматического обновления, и развёртывание не запускается само. Приложение "Безопасность Windows" может сообщать, что "not yet enough data to classify your device". По той же причине участия в управляемом Microsoft развёртывании (значение реестра MicrosoftUpdateManagedOptIn) на таких компьютерах может оказаться недостаточно.
+Windows распространяет сертификаты 2023 года поэтапно, на основе телеметрии. Устройства обновляются автоматически только после того, как Microsoft получает достаточную уверенность в конкретном сочетании оборудования и прошивки. Компьютер с системным шифрованием VeraCrypt использует нестандартную цепочку загрузки, поскольку загрузчик VeraCrypt занимает стандартное расположение Windows Boot Manager; это может влиять на проверки обслуживания, однако Microsoft не указывает VeraCrypt как безусловное исключение из развёртывания. Сообщение "not yet enough data to classify your device" описывает текущее состояние развёртывания, а не доказывает, что его причиной является VeraCrypt. Значение MicrosoftUpdateManagedOptIn отдельно включает асинхронное управляемое Microsoft развёртывание, требует разрешённой передачи диагностических данных и не гарантирует немедленное обновление. Не сочетайте этот способ с ручным применением AvailableUpdates.
-Microsoft документирует значение реестра для явного запуска обновления (см. Microsoft KB5068202,
"Registry key updates for Secure Boot"). Из командной строки с повышенными правами:
+Для контролируемого ручного развёртывания Microsoft документирует
0x5944 как явный запрос миграции CA 2023, KEK и Windows Boot Manager (см.
руководство Microsoft по ключам реестра Secure Boot). Это значение
не применяет отзыв Windows PCA 2011 через dbx, и VeraCrypt никогда не задаёт его автоматически. Используйте его на полностью обновлённой Windows только после изучения мер предосторожности ниже:
reg add HKLM\SYSTEM\CurrentControlSet\Control\Secureboot /v AvailableUpdates /t REG_DWORD /d 0x5944 /f
@@ -126,7 +135,7 @@ rem при необходимости запустите задачу обслу
schtasks /Run /TN "\Microsoft\Windows\PI\Secure-Boot-Update"
-Ход выполнения можно отслеживать в HKLM\SYSTEM\CurrentControlSet\Control\Secureboot\Servicing (значения UEFICA2023Status и UEFICA2023Error) и по событиям обслуживания Secure Boot в журнале событий Windows. Обновление db добавляет Windows UEFI CA 2023, а на системах, которые уже доверяют Microsoft Corporation UEFI CA 2011 (что верно для каждой системы VeraCrypt с Secure Boot), также добавляет Microsoft UEFI CA 2023 и Microsoft Option ROM UEFI CA 2023.
+Ход выполнения можно отслеживать в HKLM\SYSTEM\CurrentControlSet\Control\SecureBoot и его подразделе Servicing, а также по событиям обслуживания Secure Boot. Ожидаемая последовательность AvailableUpdates: 0x5944, затем 0x4100 и после требуемых запусков задачи и перезагрузок — конечный модификатор 0x4000. Дополнительно проверьте UEFICA2023Status=Updated и фактические файлы загрузки: одно значение 0x4000 не доказывает, что файл VeraCrypt bootmgfw_ms.vc обновлён. Обновление db добавляет Windows UEFI CA 2023. На системах, уже доверяющих Microsoft Corporation UEFI CA 2011, оно условно добавляет Microsoft UEFI CA 2023 и Microsoft Option ROM UEFI CA 2023; этот устаревший сторонний CA присутствует не на каждой системе, где можно установить VeraCrypt.
Перед запуском обновления на машине с системным шифрованием VeraCrypt примите следующие меры предосторожности:
@@ -139,7 +148,7 @@ schtasks /Run /TN "\Microsoft\Windows\PI\Secure-Boot-Update"
Сначала создайте или обновите Диск восстановления VeraCrypt и убедитесь, что он загружается.
-Не отключайте службу VeraCrypt System Favorites или её функцию обновления загрузчика. Когда задача обслуживания Windows устанавливает Windows Boot Manager, подписанный сертификатом 2023 года, в стандартное расположение, именно эта служба сохраняет цепочку загрузки VeraCrypt: она сохраняет новый загрузчик как bootmgfw_ms.vc (копию, на которую VeraCrypt передаёт управление после предзагрузочной аутентификации) и восстанавливает загрузчик VeraCrypt.
+Не отключайте службу VeraCrypt System Favorites или её функцию обновления загрузчика. Если Windows заменяет Boot Manager в стандартном расположении ESP, служба сохраняет его как bootmgfw_ms.vc и восстанавливает загрузчик VeraCrypt. Если стандартный путь не изменяется, текущая VeraCrypt также проверяет обслуживаемые Windows копии в %SystemRoot%\Boot\EFI_EX и %SystemRoot%\Boot\EFI, проверяет встроенную подпись и атомарно обновляет bootmgfw_ms.vc лучшей копией, совместимой с известной политикой CA.
Пользователям скрытой операционной системы не следует запускать обновление из скрытой ОС. Автоматическое сохранение цепочки загрузки отключено, когда работает скрытая ОС.
@@ -148,12 +157,15 @@ schtasks /Run /TN "\Microsoft\Windows\PI\Secure-Boot-Update"
Избегайте принудительного отключения питания между моментом, когда Windows заменяет загрузчик, и следующей обычной перезагрузкой или выключением. На большинстве систем загрузочная запись VeraCrypt сохраняет возможность загрузки компьютера в этот промежуток, но прошивка, игнорирующая порядок загрузки, может загрузить обычный Windows Boot Manager, который не сможет запустить зашифрованную Windows (восстанавливается с помощью Диска восстановления).
-Ожидайте, что Windows будет продолжать сообщать о не полностью завершённом обслуживании сертификатов Secure Boot даже после того, как всё работает. Windows проверяет, является ли файл в стандартном расположении загрузчика Microsoft Boot Manager, подписанным сертификатом 2023 года; в системе VeraCrypt это расположение по замыслу занимает загрузчик VeraCrypt. Это состояние носит косметический характер и не влияет на безопасность или работу системы.
+Windows может продолжать сообщать о незавершённом переходе, поскольку стандартное расположение Windows Boot Manager по замыслу занимает загрузчик VeraCrypt. Считайте это возможным ложным отрицательным результатом обслуживания только после появления требуемых CA 2023 в db, определения фактических файлов как EfiBootLoaderInstalledResourceSet=2023, подтверждения встроенного издателя bootmgfw_ms.vc как Windows UEFI CA 2023 и отсутствия неустранённых ошибок обслуживания.
После применения обновления db VeraCrypt автоматически переключится на набор загрузчиков 2023 года при следующем обновлении загрузчика (Восстановить/переустановить, обновление версии или одна из автоматических точек обновления службы System Favorites). Результат можно проверить в описанном выше ключе реестра диагностики и заново создать Диск восстановления, когда появится соответствующее приглашение.
+
+Отзыв Windows PCA 2011 через dbx — отдельная последующая операция, описанная в
Microsoft KB5025885. Не запрашивайте бит
0x80 (или объединённое значение
0x280, которое также запрашивает обновление SVN), пока не подтверждено, что
bootmgfw_ms.vc подписан
Windows UEFI CA 2023, носители восстановления актуальны и контрольная перезагрузка с включённым Secure Boot прошла успешно. VeraCrypt никогда не включает этот отзыв автоматически.
+
Восстановление после сбоя загрузки Secure Boot
@@ -172,19 +184,19 @@ schtasks /Run /TN "\Microsoft\Windows\PI\Secure-Boot-Update"
-
-Временно отключите Secure Boot в настройках прошивки и запустите Windows обычным образом (предзагрузочная аутентификация VeraCrypt работает и с отключённым Secure Boot) или загрузите Диск восстановления VeraCrypt и используйте "Restore VeraCrypt loader binaries to system disk".
+Временно отключите Secure Boot в настройках прошивки и запустите Windows обычным образом (предзагрузочная аутентификация VeraCrypt работает и с отключённым Secure Boot). Диск восстановления VeraCrypt может восстановить отсутствующие или повреждённые компоненты загрузчика VeraCrypt, но не может создать актуальный Windows Boot Manager или сделать подписанный PCA 2011 файл
bootmgfw_ms.vc допустимым после добавления этого CA в dbx; он не заменяет завершение миграции Windows.
-
-В Windows настройте сертификаты Secure Boot в прошивке/Windows по необходимости (включите сторонние центры сертификации в настройках прошивки или примените обновления сертификатов Windows Secure Boot, как описано выше), затем запустите установщик VeraCrypt в режиме Восстановить/переустановить.
+В Windows исправьте политику Secure Boot (включите сторонние CA, восстановите актуальную dbx после пользовательской процедуры либо примените обновления Windows), затем запустите VeraCrypt в режиме Восстановить/переустановить. Восстановление проверит обслуживаемые копии
EFI_EX/EFI и сможет установить совместимый актуальный Windows Boot Manager.
-
-Снова включите Secure Boot.
+Проверьте диагностику VeraCrypt и встроенную подпись, затем включите Secure Boot и выполните одну контролируемую перезагрузку. Не включайте его при неполной оценке политики или несовместимых файлах загрузчика.
Устаревшая процедура с пользовательскими ключами (не рекомендуется)
-В более старых версиях VeraCrypt была задокументирована процедура с пользовательскими ключами (скрипт VeraCrypt-DCS SecureBoot, sb_set_siglists.ps1), которая заменяла базы Secure Boot прошивки пользовательским ключом платформы и сертификатами Microsoft эпохи 2011 года. Эта процедура устарела и не должна использоваться на системах с цепочкой сертификатов 2023 года: она удаляет доверие к Windows Boot Manager, подписанному сертификатом 2023 года, и нарушает загрузку Windows после предзагрузочной аутентификации VeraCrypt. Системы, где она применялась, должны восстановить заводские ключи Secure Boot производителя, а затем следовать обычной процедуре, описанной на этой странице.
+В более старых версиях VeraCrypt была задокументирована процедура с пользовательскими ключами (скрипт VeraCrypt-DCS SecureBoot, sb_set_siglists.ps1), которая заменяла PK, KEK, db и dbx пользовательскими ключами, сертификатами Microsoft 2011 года и устаревшей копией dbx 2018 года. Эта процедура устарела и не должна использоваться с цепочкой 2023 года: она удаляет доверие к новому Windows Boot Manager, отбрасывает современные отзывы и может нарушить передачу управления Windows. Восстановите заводские ключи производителя и актуальную dbx.
diff --git a/doc/html/ru/System Encryption.html b/doc/html/ru/System Encryption.html
index 68e17dc7..d2c73139 100644
--- a/doc/html/ru/System Encryption.html
+++ b/doc/html/ru/System Encryption.html
@@ -96,7 +96,7 @@ XTS (см. раздел
EFI Secure Boot.
+
В режиме загрузки EFI с включённым Secure Boot при установке, восстановлении/переустановке, обновлении или восстановлении после Windows PostOOBE VeraCrypt выбирает набор загрузчиков, подписанный Microsoft UEFI CA и разрешённый активной политикой Secure Boot прошивки: каждый требуемый CA должен присутствовать в базе разрешённых подписей (db) и отсутствовать в базе запрещённых подписей (dbx). Для набора загрузчиков VeraCrypt 2023 года требуются Microsoft UEFI CA 2023 и Microsoft Option ROM UEFI CA 2023, а для набора 2011 года — Microsoft Corporation UEFI CA 2011. Если активная политика db/dbx не разрешает ни один поддерживаемый набор, VeraCrypt прерывает операцию и не устанавливает загрузчик, который прошивка отклонит при следующей перезагрузке. Если вы вручную изменили записи db или dbx Secure Boot в прошивке, запустите восстановление/переустановку VeraCrypt, чтобы обновить установленный набор загрузчиков. Подробности, включая переход на сертификаты Microsoft 2023 года и процедуры восстановления, см. в разделе EFI Secure Boot.
Следующий раздел >>
diff --git a/doc/html/zh-cn/EFISecureBoot.html b/doc/html/zh-cn/EFISecureBoot.html
index 20019020..8626c3b8 100644
--- a/doc/html/zh-cn/EFISecureBoot.html
+++ b/doc/html/zh-cn/EFISecureBoot.html
@@ -53,7 +53,7 @@ VeraCrypt系统加密兼容EFI Secure Boot(安全启动):VeraCrypt EFI引
-在安装、升级、修复/重新安装以及开始系统加密时,VeraCrypt会读取固件db,并选择签名CA受固件信任的引导加载程序套件。如果存在2023 CA对,则优先使用2023套件;否则,在 Microsoft Corporation UEFI CA 2011 受信任时使用2011套件。如果启用安全启动且固件不信任任何套件,VeraCrypt会拒绝安装其引导加载程序并显示错误,而不会安装一个在下次重启时会被固件拒绝的加载程序。
+在安装、升级、修复/重新安装以及开始系统加密时,VeraCrypt会读取固件db和dbx,并选择其已知签名CA存在于db且未列入dbx的套件。可选的dbx变量可以合法地不存在(自定义密钥系统尤其如此);此状态按空禁止数据库处理,而启用安全启动时真正的读取或解析错误仍会导致拒绝安装。若2023 CA对可用则优先选择2023套件,否则在存在 Microsoft Corporation UEFI CA 2011 时使用2011套件。
更改固件安全启动配置(例如在BIOS设置中启用其他证书)本身不会重写已经安装到EFI系统分区上的文件。更改固件安全启动数据库后,请以
修复/重新安装 模式运行VeraCrypt安装程序,或让VeraCrypt System Favorites服务自动刷新引导加载程序(它会在Windows启动、会话登录或解锁、从睡眠恢复以及关机时重新评估选择)。
@@ -68,6 +68,11 @@ HKEY_LOCAL_MACHINE\SOFTWARE\VeraCrypt\Diagnostics\EfiBootLoader
EfiBootLoaderResourceSet REG_DWORD 2011 (0x7db) 或 2023 (0x7e7)
EfiBootLoaderSelectionReason REG_SZ 可读的选择原因
EfiBootLoaderFirmwareDbLastError REG_DWORD 上次读取/解析固件db的错误(0 = 无)
+ EfiBootLoaderFirmwareDbxLastError REG_DWORD 上次读取/解析dbx的错误(0 = 无)
+ FirmwareDbxPresent REG_DWORD dbx是否存在(0可为合法缺失)
+ EfiBootLoaderInstalledResourceSet REG_DWORD 由ESP实际文件识别的套件
+ VeraCryptLoaderFilesValid REG_DWORD DCS文件与一个内嵌套件完全匹配
+ WindowsLoaderSigner REG_DWORD 内嵌签名:0、2011或2023
EfiBootLoaderSelectionTimeUtc REG_SZ 上次选择的时间
@@ -83,9 +88,13 @@ $t = [Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).Bytes)
'Microsoft UEFI CA 2023',
'Microsoft Option ROM UEFI CA 2023' |
ForEach-Object { "$_ : $($t -match [regex]::Escape($_))" }
+
+# 将ESP挂载为S:后检查内嵌签名;不要依赖可能返回目录签名的命令。
+Get-PfxCertificate -FilePath S:\EFI\Microsoft\Boot\bootmgfw_ms.vc |
+ Select-Object Subject,Issuer,Thumbprint
-此外,当VeraCrypt System Favorites服务检测到当前安全启动db不再信任已安装启动链中的某个组件时,会向Windows应用程序事件日志(源 VeraCryptSystemFavorites)写入警告。
+此外,VeraCrypt System Favorites服务会针对实际DCS文件与内嵌套件不匹配、Windows启动管理器缺失或其内嵌签名无法识别、已知所需CA不在db或被列入dbx,以及PCA 2011副本需要迁移等情况写入警告。这只是“已知CA兼容性”评估,并非固件一定接受映像的证明;dbx还可撤销映像哈希、证书TBS哈希和安全版本。
Microsoft 2023证书过渡
@@ -97,10 +106,10 @@ VeraCrypt用户需要注意两点:
-
-证书到期不会阻止已安装的引导加载程序启动。 UEFI固件在安全启动验证期间不会评估证书有效期,因此通过2011 CA签名的引导加载程序在到期日期之后仍会在几乎所有固件实现上继续加载。到期意味着 新的 二进制文件不能再通过2011 CA签名,并且从未收到2023证书的系统将停止接收启动链安全更新。
+证书到期通常不会阻止已安装的引导加载程序启动。 UEFI安全启动映像验证通常不强制执行签名证书有效期,因此仅因2011 CA到期并不会拒绝加载程序。但新的二进制文件无法继续通过该签名体系签发,未获得2023证书的系统也无法接收由替代CA签名的启动链更新。
-
-未来撤销2011 CA会阻止通过它们签名的引导加载程序启动。 Microsoft已宣布,在过渡的后续阶段(尚未排期),可能会通过安全启动禁止签名数据库(dbx)在已完成过渡的系统上撤销2011 CA。因此建议在该阶段之前迁移到2023引导加载程序套件。
+证书到期与撤销是两回事。 Microsoft提供了一项需明确执行的独立缓解措施,将 Microsoft Windows Production PCA 2011 添加到安全启动禁止签名数据库(dbx);应用后,所有通过该CA签名的Windows启动管理器都会被拒绝。此Windows PCA撤销不属于下文由
0x5944 执行的证书/启动管理器迁移。截至2026年7月,Microsoft表示目前没有撤销Microsoft Corporation UEFI CA 2011的计划;该第三方CA用于VeraCrypt 2011引导加载程序套件。尽管如此,在应用任何Windows PCA 2011撤销之前,仍建议将启动链中的VeraCrypt和Windows部分都迁移到相应的2023 CA。
@@ -114,10 +123,10 @@ VeraCrypt用户需要注意两点:
将现有系统更新到2023证书
-Windows通过基于遥测的分阶段部署流程分发2023证书。只有在Microsoft对设备硬件/固件组合有足够信心后,设备才会自动更新。由于VeraCrypt系统加密的计算机通过非标准启动链启动(VeraCrypt引导加载程序占用Windows启动管理器的位置),此类计算机通常不会被归类为自动更新对象,因此部署流程不会自行触发。Windows安全中心可能报告 "not yet enough data to classify your device"。同样,选择加入Microsoft管理的部署流程(MicrosoftUpdateManagedOptIn 注册表值)在这些计算机上可能仍不足以触发更新。
+Windows通过基于遥测的分阶段部署流程分发2023证书。只有在Microsoft对设备硬件/固件组合有足够信心后,设备才会自动更新。VeraCrypt系统加密计算机采用非标准启动链,因为VeraCrypt引导加载程序占用Windows启动管理器的标准位置;这可能影响维护检查,但Microsoft并未将VeraCrypt列为必然排除在部署之外的条件。Windows安全中心显示 "not yet enough data to classify your device" 只表示当前部署状态,不能证明原因是VeraCrypt。MicrosoftUpdateManagedOptIn 是加入Microsoft异步托管部署的另一种方式,需要允许发送相应的诊断数据,也不保证立即部署。不要把该方式与手动设置 AvailableUpdates 混用。
-Microsoft文档提供了一个用于显式触发更新的注册表值(参见Microsoft KB5068202,
"Registry key updates for Secure Boot")。在以管理员身份打开的命令提示符中运行:
+对于受控的手动部署,Microsoft将
0x5944 记录为显式请求2023 CA、KEK和Windows启动管理器迁移的值(参见
Microsoft安全启动注册表指导)。它
不会应用Windows PCA 2011的dbx撤销,VeraCrypt也绝不会自动设置此值。阅读下述预防措施后,才应在完全更新的Windows上使用:
reg add HKLM\SYSTEM\CurrentControlSet\Control\Secureboot /v AvailableUpdates /t REG_DWORD /d 0x5944 /f
@@ -126,7 +135,7 @@ rem 可选:立即运行维护任务(否则它每 12 小时运行一次):
schtasks /Run /TN "\Microsoft\Windows\PI\Secure-Boot-Update"
-可在 HKLM\SYSTEM\CurrentControlSet\Control\Secureboot\Servicing 下监视进度(值 UEFICA2023Status 和 UEFICA2023Error),也可通过Windows事件日志中的安全启动维护事件监视。db更新会添加 Windows UEFI CA 2023;在已经信任 Microsoft Corporation UEFI CA 2011 的系统上(每台启用安全启动的VeraCrypt系统都是如此),还会添加 Microsoft UEFI CA 2023 和 Microsoft Option ROM UEFI CA 2023。
+可在 HKLM\SYSTEM\CurrentControlSet\Control\SecureBoot 及其 Servicing 子项下监视进度,也可查看安全启动维护事件。AvailableUpdates 的预期变化顺序为 0x5944、0x4100,在所需任务运行和重启后最终为修饰值 0x4000。还应确认 UEFICA2023Status=Updated 并检查实际启动文件;仅有 0x4000 不能证明VeraCrypt的 bootmgfw_ms.vc 已刷新。db更新会添加 Windows UEFI CA 2023。对于已经信任 Microsoft Corporation UEFI CA 2011 的系统,它会有条件地添加 Microsoft UEFI CA 2023 和 Microsoft Option ROM UEFI CA 2023;并非所有可安装VeraCrypt的系统都具有该旧版第三方CA。
在VeraCrypt系统加密机器上触发更新之前,请采取以下预防措施:
@@ -139,7 +148,7 @@ schtasks /Run /TN "\Microsoft\Windows\PI\Secure-Boot-Update"
首先创建或更新VeraCrypt救援盘,并验证它能够启动。
-不要禁用 VeraCrypt System Favorites 服务或其引导加载程序更新功能。当Windows维护任务在标准位置安装2023证书签名的Windows启动管理器时,该服务负责保留VeraCrypt启动链:它将新的启动管理器保存为 bootmgfw_ms.vc(VeraCrypt在预启动身份验证后链式加载的副本),并恢复VeraCrypt引导加载程序。
+不要禁用 VeraCrypt System Favorites 服务或其引导加载程序更新功能。如果Windows替换标准ESP位置的启动管理器,该服务会将其保存为 bootmgfw_ms.vc 并恢复VeraCrypt加载程序。如果标准路径保持不变,当前VeraCrypt还会检查 %SystemRoot%\Boot\EFI_EX 和 %SystemRoot%\Boot\EFI 中Windows维护的副本,验证内嵌签名,并用已知固件CA策略允许的最佳副本原子刷新 bootmgfw_ms.vc。
隐藏操作系统用户不应从隐藏操作系统触发更新。 运行隐藏操作系统时,自动启动链保留功能被禁用。
@@ -148,12 +157,15 @@ schtasks /Run /TN "\Microsoft\Windows\PI\Secure-Boot-Update"
避免在Windows替换启动管理器到下一次正常重启或关机之间强制断电。在大多数系统上,VeraCrypt启动项会在这个时间窗口内保持计算机可启动,但忽略启动顺序的固件可能会启动普通Windows启动管理器,而它无法启动加密的Windows(可用救援盘恢复)。
-即使一切正常,也应预期Windows仍会报告安全启动证书维护未完全完成。Windows会检查标准启动管理器位置的文件是否为2023证书签名的Microsoft Boot Manager;在VeraCrypt系统上,该位置按设计保存VeraCrypt引导加载程序。此状态仅为显示问题,不影响系统安全性或运行。
+由于标准Windows启动管理器位置按设计保存VeraCrypt加载程序,Windows可能仍报告迁移未完成。只有在固件db包含所需2023 CA、EfiBootLoaderInstalledResourceSet 从实际文件识别出2023套件、bootmgfw_ms.vc 的内嵌签发者为 Windows UEFI CA 2023 且事件日志无未解决维护错误后,才可将其视为可能的维护误报。
应用db更新后,VeraCrypt会在下次刷新引导加载程序时自动切换到2023引导加载程序套件(修复/重新安装、升级,或System Favorites服务的某个自动刷新点)。您可以在上文所述的诊断注册表键中验证结果,并在提示时重新创建救援盘。
+
+Windows PCA 2011的dbx撤销是后续的独立操作,详见
Microsoft KB5025885。在确认
bootmgfw_ms.vc 由
Windows UEFI CA 2023 签名、恢复介质已更新,并且启用安全启动的受控重启成功之前,不要请求其
0x80 位(或还会请求SVN更新的组合值
0x280)。VeraCrypt绝不会自动启用此撤销。
+
从安全启动故障中恢复
@@ -172,19 +184,19 @@ schtasks /Run /TN "\Microsoft\Windows\PI\Secure-Boot-Update"
-
-暂时在固件设置中禁用安全启动并正常启动Windows(禁用安全启动时VeraCrypt预启动身份验证仍可工作),或启动VeraCrypt救援盘并使用 "将VeraCrypt加载程序二进制文件恢复到系统磁盘"。
+暂时在固件设置中禁用安全启动并正常启动Windows(禁用安全启动时VeraCrypt预启动身份验证仍可工作)。VeraCrypt救援盘可以恢复缺失或损坏的VeraCrypt引导加载程序组件,但无法生成当前的Windows启动管理器,也无法在PCA 2011 CA被加入dbx后使由其签名的
bootmgfw_ms.vc 重新获得信任;它不能替代完成Windows迁移。
-
-在Windows中,根据需要调整固件/Windows安全启动证书(在固件设置中启用第三方CA,或按上文所述应用Windows安全启动证书更新),然后以 修复/重新安装 模式运行VeraCrypt安装程序。
+在Windows中修复固件/Windows安全启动策略(启用第三方CA、自定义密钥流程后恢复当前dbx,或应用上述Windows更新),然后以 修复/重新安装 模式运行VeraCrypt。修复会检查Windows维护的
EFI_EX/EFI 副本,并可安装兼容的当前Windows启动管理器。
-
-重新启用安全启动。
+检查VeraCrypt诊断和内嵌签名,然后重新启用安全启动并执行一次受控重启。策略评估不完整或加载程序文件不兼容时不要重新启用。
旧版自定义密钥步骤(已弃用)
-较旧的VeraCrypt版本曾记录一种自定义密钥流程(VeraCrypt-DCS的 SecureBoot 脚本,sb_set_siglists.ps1),它用自定义平台密钥和2011版Microsoft证书替换固件安全启动数据库。此流程已经弃用,在使用2023证书链的系统上不得使用:它会移除对2023证书签名的Windows启动管理器的信任,并在VeraCrypt预启动身份验证后破坏Windows启动过程。已应用该流程的系统应恢复制造商安全启动密钥,然后按照本页所述的正常步骤操作。
+较旧VeraCrypt版本记录的自定义密钥流程(VeraCrypt-DCS SecureBoot 脚本 sb_set_siglists.ps1)会用自定义密钥、2011版Microsoft证书及过时的2018 dbx替换PK、KEK、db和dbx。此流程已经弃用,在2023证书链系统上不得使用:它会移除对新Windows启动管理器的信任、丢弃当前撤销并可能破坏Windows交接。应恢复制造商密钥和当前dbx。
diff --git a/doc/html/zh-cn/System Encryption.html b/doc/html/zh-cn/System Encryption.html
index a4dcbc85..d0658bd8 100644
--- a/doc/html/zh-cn/System Encryption.html
+++ b/doc/html/zh-cn/System Encryption.html
@@ -61,7 +61,7 @@ VeraCrypt可以对系统分区或整个系统驱动器进行即时加密,即
由于BIOS要求,预启动密码需使用 美国键盘布局 输入。在系统加密过程中,VeraCrypt会自动透明地将键盘切换到美国布局,以确保输入的密码值与预启动模式下输入的密码值匹配。然而,从剪贴板粘贴密码可能会覆盖此保护措施。为防止因这种差异而产生的任何问题,VeraCrypt在系统加密向导中禁用了从剪贴板粘贴密码的选项。因此,在设置或输入密码时,务必手动使用与创建系统加密时相同的按键进行输入,以确保能够一致地访问您的加密系统。
注意:默认情况下,Windows 7及更高版本从一个特殊的小分区启动。该分区包含启动系统所需的文件。Windows只允许具有管理员权限的应用程序在系统运行时写入该分区。在EFI启动模式(现代PC的默认模式)下,VeraCrypt无法加密此分区,因为它必须保持未加密状态,以便BIOS可以从中加载EFI引导加载程序。这反过来意味着在EFI启动模式下,VeraCrypt仅提供对安装Windows的系统分区进行加密(用户以后可以使用VeraCrypt手动加密其他数据分区)。在MBR传统启动模式下,只有当您选择加密整个系统驱动器(而不是仅选择加密安装Windows的分区)时,VeraCrypt才会对该分区进行加密。
-
在启用安全启动的EFI启动模式下,VeraCrypt会在安装、修复/重新安装、升级或Windows PostOOBE修复期间,选择受当前固件安全启动db信任且由Microsoft UEFI CA签名的引导加载程序套件。VeraCrypt 2023引导加载程序套件需要Microsoft UEFI CA 2023和Microsoft Option ROM UEFI CA 2023;2011引导加载程序套件需要Microsoft Corporation UEFI CA 2011。如果当前db不信任任何受支持的套件,VeraCrypt会中止操作,而不会安装会在下一次重启时被固件拒绝的加载程序。如果您手动更改固件安全启动db条目,请运行VeraCrypt修复/重新安装以刷新已安装的引导加载程序套件。有关详细信息,包括Microsoft 2023证书过渡和恢复步骤,请参阅 EFI安全启动。
+
在启用安全启动的EFI启动模式下,VeraCrypt会在安装、修复/重新安装、升级或Windows PostOOBE修复期间,选择由Microsoft UEFI CA签名且当前固件安全启动策略允许的引导加载程序套件:每个所需CA都必须存在于允许签名数据库(db)中,并且不在禁止签名数据库(dbx)中。VeraCrypt 2023引导加载程序套件需要Microsoft UEFI CA 2023和Microsoft Option ROM UEFI CA 2023;2011引导加载程序套件需要Microsoft Corporation UEFI CA 2011。如果当前db/dbx策略不允许任何受支持的套件,VeraCrypt会中止操作,而不会安装会在下一次重启时被固件拒绝的加载程序。如果您手动更改固件安全启动db或dbx条目,请运行VeraCrypt修复/重新安装以刷新已安装的引导加载程序套件。有关详细信息,包括Microsoft 2023证书过渡和恢复步骤,请参阅 EFI安全启动。
下一部分 >>
diff --git a/src/Common/BootEncryption.cpp b/src/Common/BootEncryption.cpp
index b1c535d6..bd7e2c04 100644
--- a/src/Common/BootEncryption.cpp
+++ b/src/Common/BootEncryption.cpp
@@ -39,6 +39,12 @@
#include
#include
+#include
+#include
+#include
+
+#pragma comment(lib, "Crypt32.lib")
+#pragma comment(lib, "Wintrust.lib")
static unsigned char g_pbEFIDcsPK[1385] = {
0xA1, 0x59, 0xC0, 0xA5, 0xE4, 0x94, 0xA7, 0x4A, 0x87, 0xB5, 0xAB, 0x15,
@@ -2614,6 +2620,7 @@ namespace VeraCrypt
DWORD ResourceSet;
const wchar_t *SelectionReason;
DWORD FirmwareDbError;
+ DWORD FirmwareDbxError;
};
struct EfiBootLoaderResourceSelection
@@ -2622,6 +2629,7 @@ namespace VeraCrypt
DWORD ResourceSet;
const wchar_t *Reason;
DWORD FirmwareDbError;
+ DWORD FirmwareDbxError;
};
struct FirmwareDbMicrosoftUefiCaSupport
@@ -2741,9 +2749,9 @@ namespace VeraCrypt
return bRet;
}
- static EfiBootLoaderResourceSelection MakeEfiBootLoaderResourceSelection (const EfiBootLoaderResourceSet& resources, DWORD resourceSet, const wchar_t *reason, DWORD firmwareDbError)
+ static EfiBootLoaderResourceSelection MakeEfiBootLoaderResourceSelection (const EfiBootLoaderResourceSet& resources, DWORD resourceSet, const wchar_t *reason, DWORD firmwareDbError, DWORD firmwareDbxError = ERROR_SUCCESS)
{
- EfiBootLoaderResourceSelection selection = { &resources, resourceSet, reason, firmwareDbError };
+ EfiBootLoaderResourceSelection selection = { &resources, resourceSet, reason, firmwareDbError, firmwareDbxError };
return selection;
}
@@ -2816,7 +2824,7 @@ namespace VeraCrypt
SetLastError (previousLastError);
}
- static void RecordEfiBootLoaderResourceSetSelectionDiagnostics (DWORD resourceSet, const wchar_t *selectionReason, DWORD firmwareDbError)
+ static void RecordEfiBootLoaderResourceSetSelectionDiagnostics (DWORD resourceSet, const wchar_t *selectionReason, DWORD firmwareDbError, DWORD firmwareDbxError = ERROR_SUCCESS)
{
if (!selectionReason)
return;
@@ -2835,6 +2843,7 @@ namespace VeraCrypt
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"EfiBootLoaderFirmwareDbxLastError", firmwareDbxError);
WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderSelectionReason", selectionReason, FALSE);
WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootLoaderSelectionTimeUtc", selectionTimeUtc, FALSE);
SetLastError (previousLastError);
@@ -2845,7 +2854,7 @@ namespace VeraCrypt
if (!images.ResourceSet || !images.SelectionReason)
return;
- RecordEfiBootLoaderResourceSetSelectionDiagnostics (images.ResourceSet, images.SelectionReason, images.FirmwareDbError);
+ RecordEfiBootLoaderResourceSetSelectionDiagnostics (images.ResourceSet, images.SelectionReason, images.FirmwareDbError, images.FirmwareDbxError);
}
static uint32 ReadUint32LittleEndian (const uint8* buffer)
@@ -2889,12 +2898,13 @@ namespace VeraCrypt
return FirmwareDbMicrosoftUefiCaSupportContainsSupportedSet (support);
}
- // Returns true when the db is structurally valid, or when malformed data appears only
+ // Parses either the allowed database (db) or forbidden database (dbx). Returns true
+ // when the signature database is structurally valid, or when malformed data appears only
// after a complete VeraCrypt-supported Microsoft CA set has already been found. In the
// latter case support.DbMalformed remains set so selection diagnostics can report it.
- static bool FirmwareDbBufferGetMicrosoftUefiCaSupport (const std::vector& db, FirmwareDbMicrosoftUefiCaSupport& support)
+ static bool FirmwareSignatureDatabaseBufferGetMicrosoftUefiCaSupport (const std::vector& database, FirmwareDbMicrosoftUefiCaSupport& support)
{
- // Microsoft documents these CAs as valid db entries in EFI_CERT_X509_GUID or EFI_CERT_RSA2048_GUID form:
+ // Microsoft documents these CAs as valid signature-database entries in EFI_CERT_X509_GUID or EFI_CERT_RSA2048_GUID form:
// https://learn.microsoft.com/windows-hardware/manufacture/desktop/windows-secure-boot-key-creation-and-management-guidance
// EFI_CERT_X509_GUID {a5c059a1-94e4-4aa7-87b5-ab155c2bf072}
static const uint8 efiCertX509Guid[16] = { 0xA1, 0x59, 0xC0, 0xA5, 0xE4, 0x94, 0xA7, 0x4A, 0x87, 0xB5, 0xAB, 0x15, 0x5C, 0x2B, 0xF0, 0x72 };
@@ -3020,7 +3030,7 @@ namespace VeraCrypt
// The two Windows boot manager signing CAs below are not used for loader-set selection.
// They are tracked so that the trust of the chainloaded Windows boot manager copy
- // (bootmgfw_ms.vc) can be verified against the active Secure Boot db before a reboot.
+ // (bootmgfw_ms.vc) can be checked against the active Secure Boot db and dbx before a reboot.
// Microsoft Windows Production PCA 2011, SHA-1 thumbprint 580A6F4CC4E4B669B9EBDC1B2B3E087B80D0678D.
// DER source: https://go.microsoft.com/fwlink/p/?linkid=321192, SHA-256 E8E95F0733A55E8BAD7BE0A1413EE23C51FCEA64B3C8FA6A786935FDDCC71961.
static const uint8 microsoftWindowsProductionPca2011Rsa2048Modulus[256] =
@@ -3102,18 +3112,18 @@ namespace VeraCrypt
size_t offset = 0;
memset (&support, 0, sizeof (support));
- while (offset < db.size ())
+ while (offset < database.size ())
{
- if (db.size () - offset < efiSignatureListHeaderSize)
+ if (database.size () - offset < efiSignatureListHeaderSize)
return FirmwareDbMicrosoftUefiCaSupportSetMalformed (support, ERROR_INVALID_DATA);
- const uint8* signatureList = &db[offset];
+ const uint8* signatureList = &database[offset];
uint32 signatureListSize = ReadUint32LittleEndian (signatureList + efiGuidSize);
uint32 signatureHeaderSize = ReadUint32LittleEndian (signatureList + efiGuidSize + sizeof (uint32));
uint32 signatureSize = ReadUint32LittleEndian (signatureList + efiGuidSize + sizeof (uint32) * 2);
if ((signatureListSize < efiSignatureListHeaderSize)
- || (signatureListSize > db.size () - offset)
+ || (signatureListSize > database.size () - offset)
|| (signatureHeaderSize > signatureListSize - efiSignatureListHeaderSize))
return FirmwareDbMicrosoftUefiCaSupportSetMalformed (support, ERROR_INVALID_DATA);
@@ -3129,7 +3139,7 @@ namespace VeraCrypt
for (size_t signatureOffset = signaturesOffset; signatureOffset < offset + signatureListSize; signatureOffset += signatureSize)
{
- const uint8* certificate = &db[signatureOffset + efiSignatureOwnerSize];
+ const uint8* certificate = &database[signatureOffset + efiSignatureOwnerSize];
size_t certificateSize = signatureSize - efiSignatureOwnerSize;
if (!support.ContainsMicrosoftCorporationUefiCa2011
@@ -3170,7 +3180,7 @@ namespace VeraCrypt
for (size_t signatureOffset = signaturesOffset; signatureOffset < offset + signatureListSize; signatureOffset += signatureSize)
{
- const uint8* publicKey = &db[signatureOffset + efiSignatureOwnerSize];
+ const uint8* publicKey = &database[signatureOffset + efiSignatureOwnerSize];
if (!support.ContainsMicrosoftCorporationUefiCa2011
&& BufferEquals (publicKey, efiRsa2048KeySize, microsoftCorporationUefiCa2011Rsa2048Modulus, sizeof (microsoftCorporationUefiCa2011Rsa2048Modulus)))
@@ -3206,17 +3216,18 @@ namespace VeraCrypt
return true;
}
- static bool TryFirmwareDbGetMicrosoftUefiCaSupport (FirmwareDbMicrosoftUefiCaSupport& support)
+ static bool TryFirmwareSignatureDatabaseGetMicrosoftUefiCaSupport (const wchar_t *variableName, FirmwareDbMicrosoftUefiCaSupport& support)
{
- std::vector db;
+ memset (&support, 0, sizeof (support));
+ std::vector database;
DWORD dwError = ERROR_SUCCESS;
- if (!ReadFirmwareEnvironmentVariableBuffer (L"db", EfiImageSecurityDatabaseGuid, db, &dwError))
+ if (!ReadFirmwareEnvironmentVariableBuffer (variableName, EfiImageSecurityDatabaseGuid, database, &dwError))
{
SetLastError (dwError);
return false;
}
- if (!FirmwareDbBufferGetMicrosoftUefiCaSupport (db, support))
+ if (!FirmwareSignatureDatabaseBufferGetMicrosoftUefiCaSupport (database, support))
{
SetLastError (support.ParseError ? support.ParseError : ERROR_INVALID_DATA);
return false;
@@ -3225,6 +3236,36 @@ namespace VeraCrypt
return true;
}
+ static bool TryFirmwareDbGetMicrosoftUefiCaSupport (FirmwareDbMicrosoftUefiCaSupport& support)
+ {
+ return TryFirmwareSignatureDatabaseGetMicrosoftUefiCaSupport (L"db", support);
+ }
+
+ static bool TryFirmwareDbxGetMicrosoftUefiCaSupport (FirmwareDbMicrosoftUefiCaSupport& support, bool *pPresent = NULL)
+ {
+ if (pPresent)
+ *pPresent = false;
+
+ if (TryFirmwareSignatureDatabaseGetMicrosoftUefiCaSupport (L"dbx", support))
+ {
+ if (pPresent)
+ *pPresent = true;
+ return true;
+ }
+
+ // dbx is optional in UEFI. Custom-key deployments in particular may have no
+ // dbx variable at all; that is a valid empty forbidden database, not a read
+ // failure. Preserve fail-closed handling for every other error.
+ if (GetLastError () == ERROR_ENVVAR_NOT_FOUND)
+ {
+ memset (&support, 0, sizeof (support));
+ SetLastError (ERROR_SUCCESS);
+ return true;
+ }
+
+ return false;
+ }
+
static bool IsFirmwareDbUnavailableError (DWORD dwError)
{
return (dwError == ERROR_ENVVAR_NOT_FOUND) || (dwError == ERROR_INVALID_FUNCTION);
@@ -3254,9 +3295,9 @@ namespace VeraCrypt
return true;
}
- static __declspec(noreturn) void ThrowUnsupportedEfiSecureBootDb (const wchar_t *reason, DWORD firmwareDbError)
+ static __declspec(noreturn) void ThrowUnsupportedEfiSecureBootDb (const wchar_t *reason, DWORD firmwareDbError, DWORD firmwareDbxError = ERROR_SUCCESS)
{
- RecordEfiBootLoaderResourceSetSelectionDiagnostics (0, reason, firmwareDbError);
+ RecordEfiBootLoaderResourceSetSelectionDiagnostics (0, reason, firmwareDbError, firmwareDbxError);
throw ErrorException ("SYSENC_EFI_UNSUPPORTED_SECUREBOOT_CA", SRC_POS);
}
@@ -3264,47 +3305,93 @@ namespace VeraCrypt
{
// The current 2023 DCS set uses both Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023:
// DcsInt.dcs and LegacySpeaker.dcs are signed through the Option ROM UEFI CA 2023 chain.
- // If Secure Boot is enabled, only select a loader set whose signing CA is trusted by the active db.
+ // If Secure Boot is enabled (or its state cannot be established), only select a loader set whose
+ // signing CA is allowed by the active db and is not forbidden by the active dbx.
FirmwareDbMicrosoftUefiCaSupport support;
if (TryFirmwareDbGetMicrosoftUefiCaSupport (support))
{
DWORD firmwareDbError = FirmwareDbMicrosoftUefiCaSupportGetDiagnosticError (support);
-
- if (FirmwareDbMicrosoftUefiCaSupportContains2023Set (support))
- {
- return MakeEfiBootLoaderResourceSelection (
- EfiBootLoaderResources2023,
- VC_EFI_BOOT_LOADER_RESOURCE_SET_2023,
- support.DbMalformed
- ? L"firmware db contains Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023 before malformed data"
- : L"firmware db contains Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023",
- firmwareDbError);
- }
-
- if (support.ContainsMicrosoftCorporationUefiCa2011)
- {
- return MakeEfiBootLoaderResourceSelection (
- EfiBootLoaderResources2011,
- VC_EFI_BOOT_LOADER_RESOURCE_SET_2011,
- support.DbMalformed
- ? L"firmware db contains Microsoft Corporation UEFI CA 2011 before malformed data"
- : L"firmware db contains Microsoft Corporation UEFI CA 2011",
- firmwareDbError);
- }
-
bool bSecureBootEnabled = false;
bool bSecureBootStateKnown = TryFirmwareSecureBootEnabled (bSecureBootEnabled);
DWORD secureBootLastError = bSecureBootStateKnown ? ERROR_SUCCESS : GetLastError ();
+ if (support.DbMalformed && (!bSecureBootStateKnown || bSecureBootEnabled))
+ {
+ ThrowUnsupportedEfiSecureBootDb (
+ L"Secure Boot is enabled or unavailable, but firmware db could not be parsed completely; refusing to select an EFI bootloader from partial policy data",
+ firmwareDbError);
+ }
+
+ FirmwareDbMicrosoftUefiCaSupport forbiddenSupport;
+ bool bFirmwareDbxChecked = false;
+ bool bFirmwareDbxPresent = false;
+ DWORD firmwareDbxError = ERROR_SUCCESS;
+
+ if (!TryFirmwareDbxGetMicrosoftUefiCaSupport (forbiddenSupport, &bFirmwareDbxPresent) || forbiddenSupport.DbMalformed)
+ {
+ firmwareDbxError = forbiddenSupport.ParseError ? forbiddenSupport.ParseError : GetLastError ();
+ if (firmwareDbxError == ERROR_SUCCESS)
+ firmwareDbxError = ERROR_INVALID_DATA;
+
+ if (!bSecureBootStateKnown || bSecureBootEnabled)
+ {
+ ThrowUnsupportedEfiSecureBootDb (
+ L"Secure Boot is enabled or unavailable, but firmware dbx could not be read and parsed completely; refusing to select an EFI bootloader without checking revocations",
+ firmwareDbError,
+ firmwareDbxError);
+ }
+ }
+ else
+ bFirmwareDbxChecked = true;
+
+ bool b2023SetPresent = FirmwareDbMicrosoftUefiCaSupportContains2023Set (support);
+ bool b2023SetRevoked = b2023SetPresent && bFirmwareDbxChecked
+ && (forbiddenSupport.ContainsMicrosoftUefiCa2023 || forbiddenSupport.ContainsMicrosoftOptionRomUefiCa2023);
+ bool b2011SetPresent = support.ContainsMicrosoftCorporationUefiCa2011;
+ bool b2011SetRevoked = b2011SetPresent && bFirmwareDbxChecked && forbiddenSupport.ContainsMicrosoftCorporationUefiCa2011;
+
+ if (b2023SetPresent && !b2023SetRevoked)
+ {
+ const wchar_t *reason = bFirmwareDbxChecked
+ ? (bFirmwareDbxPresent
+ ? L"firmware db contains the Microsoft 2023 UEFI CA pair and dbx contains no known revocation of either CA"
+ : L"firmware db contains the Microsoft 2023 UEFI CA pair and the optional dbx variable is absent")
+ : L"Secure Boot is disabled; firmware db contains the Microsoft 2023 UEFI CA pair, but dbx could not be checked";
+ return MakeEfiBootLoaderResourceSelection (
+ EfiBootLoaderResources2023,
+ VC_EFI_BOOT_LOADER_RESOURCE_SET_2023,
+ reason,
+ firmwareDbError,
+ firmwareDbxError);
+ }
+
+ if (b2011SetPresent && !b2011SetRevoked)
+ {
+ const wchar_t *reason = bFirmwareDbxChecked
+ ? (bFirmwareDbxPresent
+ ? L"firmware db contains Microsoft Corporation UEFI CA 2011 and dbx contains no known revocation of that CA"
+ : L"firmware db contains Microsoft Corporation UEFI CA 2011 and the optional dbx variable is absent")
+ : L"Secure Boot is disabled; firmware db contains Microsoft Corporation UEFI CA 2011, but dbx could not be checked";
+ return MakeEfiBootLoaderResourceSelection (
+ EfiBootLoaderResources2011,
+ VC_EFI_BOOT_LOADER_RESOURCE_SET_2011,
+ reason,
+ firmwareDbError,
+ firmwareDbxError);
+ }
+
if (bSecureBootStateKnown && !bSecureBootEnabled)
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, VC_EFI_BOOT_LOADER_RESOURCE_SET_2011, L"Secure Boot is disabled and firmware db does not contain a supported Microsoft UEFI CA; using 2011 compatibility fallback", ERROR_SUCCESS);
if (!bSecureBootStateKnown && IsFirmwareDbUnavailableError (secureBootLastError))
return MakeEfiBootLoaderResourceSelection (EfiBootLoaderResources2011, VC_EFI_BOOT_LOADER_RESOURCE_SET_2011, L"Secure Boot is unavailable and firmware db does not contain a supported Microsoft UEFI CA; using 2011 compatibility fallback", ERROR_SUCCESS);
- 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);
+ if (b2023SetRevoked || b2011SetRevoked)
+ ThrowUnsupportedEfiSecureBootDb (L"Secure Boot is enabled, but every VeraCrypt EFI bootloader signing CA set present in firmware db is forbidden by firmware dbx", firmwareDbError, firmwareDbxError);
- 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);
+ 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", firmwareDbError, firmwareDbxError);
+
+ 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, firmwareDbxError);
}
DWORD dwError = GetLastError ();
@@ -3357,9 +3444,8 @@ namespace VeraCrypt
return resource;
}
- static EfiBootLoaderImages MapEfiBootLoaderImages (bool rescueDisk)
+ static EfiBootLoaderImages MapEfiBootLoaderImages (const EfiBootLoaderResourceSelection& selection, bool rescueDisk)
{
- EfiBootLoaderResourceSelection selection = GetPreferredEfiBootLoaderResourceSet ();
const EfiBootLoaderResourceSet& resources = *selection.Resources;
EfiBootLoaderImages images = {0};
@@ -3372,10 +3458,29 @@ namespace VeraCrypt
images.ResourceSet = selection.ResourceSet;
images.SelectionReason = selection.Reason;
images.FirmwareDbError = selection.FirmwareDbError;
+ images.FirmwareDbxError = selection.FirmwareDbxError;
return images;
}
+ static EfiBootLoaderImages MapEfiBootLoaderImages (bool rescueDisk)
+ {
+ return MapEfiBootLoaderImages (GetPreferredEfiBootLoaderResourceSet (), rescueDisk);
+ }
+
+ static EfiBootLoaderImages MapEfiBootLoaderImages (DWORD resourceSet, bool rescueDisk)
+ {
+ if (resourceSet == VC_EFI_BOOT_LOADER_RESOURCE_SET_2011)
+ return MapEfiBootLoaderImages (MakeEfiBootLoaderResourceSelection (
+ EfiBootLoaderResources2011, resourceSet, L"explicit 2011 resource-set inspection", ERROR_SUCCESS), rescueDisk);
+
+ if (resourceSet == VC_EFI_BOOT_LOADER_RESOURCE_SET_2023)
+ return MapEfiBootLoaderImages (MakeEfiBootLoaderResourceSelection (
+ EfiBootLoaderResources2023, resourceSet, L"explicit 2023 resource-set inspection", ERROR_SUCCESS), rescueDisk);
+
+ throw ParameterIncorrect (SRC_POS);
+ }
+
static void BackupEfiBootLoaderImageIfDifferent (EfiBoot& efiBoot, const wchar_t* imageName, const wchar_t* backupName, uint8* replacementData, DWORD replacementSize)
{
std::vector currentImage;
@@ -3404,7 +3509,7 @@ namespace VeraCrypt
{
std::vector currentImage;
if (!efiBoot.ReadFileToBuffer (imageName, currentImage))
- return false;
+ return true;
return (currentImage.size () != replacementSize)
|| ((replacementSize != 0) && (memcmp (currentImage.data (), replacementData, replacementSize) != 0));
@@ -3419,6 +3524,11 @@ namespace VeraCrypt
|| EfiBootLoaderImageDiffers (efiBoot, L"\\EFI\\VeraCrypt\\DcsInfo.dcs", images.DcsInfo, images.SizeDcsInfo);
}
+ static bool EfiBootLoaderImagesMatch (EfiBoot& efiBoot, const EfiBootLoaderImages& images)
+ {
+ return !EfiBootLoaderImagesDiffer (efiBoot, images);
+ }
+
static bool EfiBootLoaderRefreshRequiresRescueDiskPrompt (EfiBoot& efiBoot, const EfiBootLoaderImages& images)
{
DWORD recordedResourceSet = 0;
@@ -4015,6 +4125,395 @@ namespace VeraCrypt
&& BufferHasPattern (fileContent.data (), fileContent.size (), g_szMsBootString, strlen (g_szMsBootString));
}
+ template
+ static bool ReadStructureFromBuffer (const std::vector& buffer, size_t offset, T& value)
+ {
+ if (offset > buffer.size () || sizeof (T) > buffer.size () - offset)
+ return false;
+
+ memcpy (&value, buffer.data () + offset, sizeof (T));
+ return true;
+ }
+
+ static bool GetPeSecurityDirectory (const std::vector& image, IMAGE_DATA_DIRECTORY& securityDirectory)
+ {
+ memset (&securityDirectory, 0, sizeof (securityDirectory));
+
+ IMAGE_DOS_HEADER dosHeader;
+ if (!ReadStructureFromBuffer (image, 0, dosHeader)
+ || dosHeader.e_magic != IMAGE_DOS_SIGNATURE
+ || dosHeader.e_lfanew < 0)
+ return false;
+
+ size_t ntOffset = (size_t) dosHeader.e_lfanew;
+ DWORD ntSignature = 0;
+ IMAGE_FILE_HEADER fileHeader;
+ if (!ReadStructureFromBuffer (image, ntOffset, ntSignature)
+ || ntSignature != IMAGE_NT_SIGNATURE
+ || !ReadStructureFromBuffer (image, ntOffset + sizeof (ntSignature), fileHeader))
+ return false;
+
+ size_t optionalOffset = ntOffset + sizeof (ntSignature) + sizeof (fileHeader);
+ WORD optionalMagic = 0;
+ if (!ReadStructureFromBuffer (image, optionalOffset, optionalMagic))
+ return false;
+
+ size_t dataDirectoryOffset = 0;
+ size_t numberOfRvaAndSizesOffset = 0;
+ if (optionalMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ dataDirectoryOffset = offsetof (IMAGE_OPTIONAL_HEADER32, DataDirectory);
+ numberOfRvaAndSizesOffset = offsetof (IMAGE_OPTIONAL_HEADER32, NumberOfRvaAndSizes);
+ }
+ else if (optionalMagic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+ {
+ dataDirectoryOffset = offsetof (IMAGE_OPTIONAL_HEADER64, DataDirectory);
+ numberOfRvaAndSizesOffset = offsetof (IMAGE_OPTIONAL_HEADER64, NumberOfRvaAndSizes);
+ }
+ else
+ return false;
+
+ DWORD numberOfRvaAndSizes = 0;
+ if (!ReadStructureFromBuffer (image, optionalOffset + numberOfRvaAndSizesOffset, numberOfRvaAndSizes)
+ || numberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_SECURITY)
+ return false;
+
+ size_t securityEntryOffset = dataDirectoryOffset + IMAGE_DIRECTORY_ENTRY_SECURITY * sizeof (IMAGE_DATA_DIRECTORY);
+ if (securityEntryOffset > fileHeader.SizeOfOptionalHeader
+ || sizeof (IMAGE_DATA_DIRECTORY) > fileHeader.SizeOfOptionalHeader - securityEntryOffset
+ || !ReadStructureFromBuffer (image, optionalOffset + securityEntryOffset, securityDirectory)
+ || securityDirectory.VirtualAddress == 0
+ || securityDirectory.Size < sizeof (WIN_CERTIFICATE))
+ return false;
+
+ size_t certificateTableOffset = (size_t) securityDirectory.VirtualAddress;
+ return certificateTableOffset <= image.size ()
+ && (size_t) securityDirectory.Size <= image.size () - certificateTableOffset;
+ }
+
+ static DWORD GetCertificateIssuerFamily (PCCERT_CONTEXT certificate)
+ {
+ wchar_t issuerName[256] = {0};
+ if (CertGetNameStringW (certificate, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG,
+ NULL, issuerName, ARRAYSIZE (issuerName)) <= 1)
+ return VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+
+ if (_wcsicmp (issuerName, L"Microsoft Windows Production PCA 2011") == 0)
+ return VC_EFI_WINDOWS_LOADER_SIGNER_PCA_2011;
+ if (_wcsicmp (issuerName, L"Windows UEFI CA 2023") == 0)
+ return VC_EFI_WINDOWS_LOADER_SIGNER_CA_2023;
+
+ return VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+ }
+
+ static bool GetPkcs7SignerFamily (const uint8 *pkcs7Data, DWORD pkcs7Size, DWORD& signerFamily)
+ {
+ signerFamily = VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+ CRYPT_DATA_BLOB blob = { pkcs7Size, const_cast (pkcs7Data) };
+ HCERTSTORE certificateStore = NULL;
+ HCRYPTMSG cryptMsg = NULL;
+ bool bParsed = false;
+
+ if (!CryptQueryObject (CERT_QUERY_OBJECT_BLOB, &blob,
+ CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
+ CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, &certificateStore, &cryptMsg, NULL))
+ return false;
+
+ DWORD signerCount = 0;
+ DWORD signerCountSize = sizeof (signerCount);
+ if (CryptMsgGetParam (cryptMsg, CMSG_SIGNER_COUNT_PARAM, 0, &signerCount, &signerCountSize))
+ {
+ bParsed = signerCount != 0;
+ for (DWORD signerIndex = 0; signerIndex < signerCount; ++signerIndex)
+ {
+ DWORD signerInfoSize = 0;
+ if (!CryptMsgGetParam (cryptMsg, CMSG_SIGNER_INFO_PARAM, signerIndex, NULL, &signerInfoSize)
+ || signerInfoSize < sizeof (CMSG_SIGNER_INFO))
+ {
+ bParsed = false;
+ break;
+ }
+
+ std::vector signerInfoBuffer (signerInfoSize);
+ if (!CryptMsgGetParam (cryptMsg, CMSG_SIGNER_INFO_PARAM, signerIndex, signerInfoBuffer.data (), &signerInfoSize))
+ {
+ bParsed = false;
+ break;
+ }
+
+ PCMSG_SIGNER_INFO signerInfo = reinterpret_cast (signerInfoBuffer.data ());
+ CERT_INFO certificateInfo;
+ memset (&certificateInfo, 0, sizeof (certificateInfo));
+ certificateInfo.Issuer = signerInfo->Issuer;
+ certificateInfo.SerialNumber = signerInfo->SerialNumber;
+ PCCERT_CONTEXT signerCertificate = CertFindCertificateInStore (certificateStore,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, &certificateInfo, NULL);
+ if (!signerCertificate)
+ {
+ bParsed = false;
+ break;
+ }
+
+ DWORD currentFamily = GetCertificateIssuerFamily (signerCertificate);
+ CertFreeCertificateContext (signerCertificate);
+ if (currentFamily != VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN)
+ {
+ if (signerFamily != VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN && signerFamily != currentFamily)
+ {
+ signerFamily = VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+ bParsed = false;
+ break;
+ }
+ signerFamily = currentFamily;
+ }
+ }
+ }
+
+ if (cryptMsg)
+ CryptMsgClose (cryptMsg);
+ if (certificateStore)
+ CertCloseStore (certificateStore, 0);
+
+ return bParsed;
+ }
+
+ // Extracts the signer from the PE image's embedded WIN_CERTIFICATE table. This
+ // deliberately ignores catalog signatures: the firmware evaluates the image's
+ // embedded Authenticode signature, and Get-AuthenticodeSignature may otherwise
+ // report an unrelated catalog signer for a Windows boot file.
+ static bool GetEmbeddedPeSignerFamily (const std::vector& image, DWORD& signerFamily)
+ {
+ signerFamily = VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+ IMAGE_DATA_DIRECTORY securityDirectory;
+ if (!GetPeSecurityDirectory (image, securityDirectory))
+ return false;
+
+ size_t tableOffset = (size_t) securityDirectory.VirtualAddress;
+ size_t tableEnd = tableOffset + (size_t) securityDirectory.Size;
+ bool bParsedSignature = false;
+ DWORD detectedFamily = VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+
+ while (tableOffset + sizeof (WIN_CERTIFICATE) <= tableEnd)
+ {
+ WIN_CERTIFICATE certificateHeader;
+ if (!ReadStructureFromBuffer (image, tableOffset, certificateHeader)
+ || certificateHeader.dwLength < offsetof (WIN_CERTIFICATE, bCertificate)
+ || certificateHeader.dwLength > tableEnd - tableOffset)
+ return false;
+
+ if (certificateHeader.wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA)
+ {
+ DWORD currentFamily = VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+ const size_t certificateDataOffset = offsetof (WIN_CERTIFICATE, bCertificate);
+ DWORD certificateDataSize = certificateHeader.dwLength - (DWORD) certificateDataOffset;
+ if (!GetPkcs7SignerFamily (image.data () + tableOffset + certificateDataOffset,
+ certificateDataSize, currentFamily))
+ return false;
+
+ bParsedSignature = true;
+ if (currentFamily != VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN)
+ {
+ if (detectedFamily != VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN && detectedFamily != currentFamily)
+ return false;
+ detectedFamily = currentFamily;
+ }
+ }
+
+ size_t alignedLength = ((size_t) certificateHeader.dwLength + 7) & ~(size_t) 7;
+ if (alignedLength == 0 || alignedLength > tableEnd - tableOffset)
+ break;
+ tableOffset += alignedLength;
+ }
+
+ signerFamily = detectedFamily;
+ return bParsedSignature;
+ }
+
+ static bool ReadLocalFileToBuffer (const wchar_t *path, std::vector& fileContent)
+ {
+ fileContent.clear ();
+ File file (path, true);
+ if (!file.IsOpened ())
+ return false;
+
+ unsigned __int64 fileSize = 0;
+ file.GetFileSize (fileSize);
+ if (fileSize == 0 || fileSize > TC_MAX_EFI_BOOT_LOADER_FILE_SIZE || fileSize > UINT_MAX)
+ {
+ file.Close ();
+ return false;
+ }
+
+ fileContent.resize ((size_t) fileSize);
+ bool bRead = file.Read (fileContent.data (), (DWORD) fileSize) == (DWORD) fileSize;
+ file.Close ();
+ if (!bRead)
+ fileContent.clear ();
+ return bRead;
+ }
+
+ static bool IsWindowsLoaderSignerAllowedByKnownCaPolicy (DWORD signerFamily,
+ const FirmwareDbMicrosoftUefiCaSupport& allowedSupport,
+ const FirmwareDbMicrosoftUefiCaSupport& forbiddenSupport)
+ {
+ if (signerFamily == VC_EFI_WINDOWS_LOADER_SIGNER_CA_2023)
+ return allowedSupport.ContainsWindowsUefiCa2023 && !forbiddenSupport.ContainsWindowsUefiCa2023;
+ if (signerFamily == VC_EFI_WINDOWS_LOADER_SIGNER_PCA_2011)
+ return allowedSupport.ContainsMicrosoftWindowsProductionPca2011
+ && !forbiddenSupport.ContainsMicrosoftWindowsProductionPca2011;
+ return false;
+ }
+
+ static bool EfiBootLoaderStandardCopiesMatch (EfiBoot& efiBoot, const EfiBootLoaderImages& images)
+ {
+ const wchar_t *standardPaths[] =
+ {
+ L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi",
+ L"\\EFI\\Boot\\bootx64.efi"
+ };
+
+ for (size_t pathIndex = 0; pathIndex < ARRAYSIZE (standardPaths); ++pathIndex)
+ {
+ std::vector standardImage;
+ if (!efiBoot.ReadFileToBuffer (standardPaths[pathIndex], standardImage))
+ {
+ if (efiBoot.FileExists (standardPaths[pathIndex]))
+ return false;
+ continue;
+ }
+
+ if (BufferHasVeraCryptBootLoaderPattern (standardImage)
+ && !BufferEquals (standardImage.data (), standardImage.size (), images.DcsBoot, images.SizeDcsBoot))
+ return false;
+ }
+
+ return true;
+ }
+
+ static int GetWindowsLoaderSignerPreference (DWORD signerFamily)
+ {
+ return signerFamily == VC_EFI_WINDOWS_LOADER_SIGNER_CA_2023 ? 2
+ : (signerFamily == VC_EFI_WINDOWS_LOADER_SIGNER_PCA_2011 ? 1 : 0);
+ }
+
+ static bool VerifyFileAuthenticodeSignature (const wchar_t *path)
+ {
+ WINTRUST_FILE_INFO fileInfo;
+ memset (&fileInfo, 0, sizeof (fileInfo));
+ fileInfo.cbStruct = sizeof (fileInfo);
+ fileInfo.pcwszFilePath = path;
+
+ WINTRUST_DATA trustData;
+ memset (&trustData, 0, sizeof (trustData));
+ trustData.cbStruct = sizeof (trustData);
+ trustData.dwUIChoice = WTD_UI_NONE;
+ trustData.fdwRevocationChecks = WTD_REVOKE_NONE;
+ trustData.dwUnionChoice = WTD_CHOICE_FILE;
+ trustData.pFile = &fileInfo;
+ trustData.dwStateAction = WTD_STATEACTION_VERIFY;
+ trustData.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
+
+ GUID action = WINTRUST_ACTION_GENERIC_VERIFY_V2;
+ LONG trustResult = WinVerifyTrust (NULL, &action, &trustData);
+ trustData.dwStateAction = WTD_STATEACTION_CLOSE;
+ WinVerifyTrust (NULL, &action, &trustData);
+ return trustResult == ERROR_SUCCESS;
+ }
+
+ static bool RefreshWindowsBootManagerFromWindows (EfiBoot& efiBoot, const wchar_t *destinationName)
+ {
+ FirmwareDbMicrosoftUefiCaSupport allowedSupport;
+ FirmwareDbMicrosoftUefiCaSupport forbiddenSupport;
+ if (!TryFirmwareDbGetMicrosoftUefiCaSupport (allowedSupport) || allowedSupport.DbMalformed
+ || !TryFirmwareDbxGetMicrosoftUefiCaSupport (forbiddenSupport) || forbiddenSupport.DbMalformed)
+ return false;
+
+ wchar_t windowsDirectory[MAX_PATH] = {0};
+ UINT windowsDirectoryLength = ::GetWindowsDirectoryW (windowsDirectory, ARRAYSIZE (windowsDirectory));
+ if (windowsDirectoryLength == 0 || windowsDirectoryLength >= ARRAYSIZE (windowsDirectory))
+ return false;
+
+ const wchar_t *relativeCandidatePaths[] =
+ {
+ L"\\Boot\\EFI_EX\\bootmgfw_EX.efi",
+ L"\\Boot\\EFI\\bootmgfw.efi"
+ };
+ std::vector preferredCandidate;
+ wstring preferredCandidatePath;
+ DWORD preferredSigner = VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+
+ for (size_t candidateIndex = 0; candidateIndex < ARRAYSIZE (relativeCandidatePaths); ++candidateIndex)
+ {
+ wstring candidatePath = windowsDirectory;
+ candidatePath += relativeCandidatePaths[candidateIndex];
+ std::vector candidate;
+ DWORD candidateSigner = VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+ static const char windowsBootManagerMarker[] = "bootmgfw.pdb";
+ if (!ReadLocalFileToBuffer (candidatePath.c_str (), candidate)
+ || !BufferHasPattern (candidate.data (), candidate.size (), windowsBootManagerMarker, strlen (windowsBootManagerMarker))
+ || !VerifyFileAuthenticodeSignature (candidatePath.c_str ())
+ || !GetEmbeddedPeSignerFamily (candidate, candidateSigner)
+ || !IsWindowsLoaderSignerAllowedByKnownCaPolicy (candidateSigner, allowedSupport, forbiddenSupport))
+ continue;
+
+ if (GetWindowsLoaderSignerPreference (candidateSigner) > GetWindowsLoaderSignerPreference (preferredSigner))
+ {
+ preferredCandidate.swap (candidate);
+ preferredCandidatePath = candidatePath;
+ preferredSigner = candidateSigner;
+ }
+ }
+
+ if (preferredCandidate.empty ())
+ return false;
+
+ std::vector installedLoader;
+ DWORD installedSigner = VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN;
+ bool bInstalledLoaderRead = false;
+ try
+ {
+ bInstalledLoaderRead = efiBoot.ReadFileToBuffer (destinationName, installedLoader);
+ }
+ catch (...)
+ {
+ installedLoader.clear ();
+ }
+
+ if (bInstalledLoaderRead
+ && GetEmbeddedPeSignerFamily (installedLoader, installedSigner)
+ && IsWindowsLoaderSignerAllowedByKnownCaPolicy (installedSigner, allowedSupport, forbiddenSupport)
+ && GetWindowsLoaderSignerPreference (installedSigner) > GetWindowsLoaderSignerPreference (preferredSigner))
+ return true;
+
+ if (!installedLoader.empty ()
+ && BufferEquals (installedLoader.data (), installedLoader.size (), preferredCandidate.data (), preferredCandidate.size ()))
+ return true;
+
+ // Keep the currently bootable manager intact until a complete replacement has
+ // been written and read back on the ESP.
+ wstring temporaryName = destinationName;
+ temporaryName += L".vc_new";
+ try
+ {
+ efiBoot.SaveFile (temporaryName.c_str (), preferredCandidate.data (), (DWORD) preferredCandidate.size ());
+ std::vector verifiedCandidate;
+ if (!efiBoot.ReadFileToBuffer (temporaryName.c_str (), verifiedCandidate)
+ || !BufferEquals (verifiedCandidate.data (), verifiedCandidate.size (), preferredCandidate.data (), preferredCandidate.size ()))
+ throw ErrorException ("EFI_BOOT_LOADER_FILE_READ_FAILED", SRC_POS);
+ throw_sys_if (!efiBoot.RenameFile (temporaryName.c_str (), destinationName, TRUE));
+ }
+ catch (...)
+ {
+ efiBoot.DelFile (temporaryName.c_str ());
+ throw;
+ }
+
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"WindowsLoaderRefreshSigner", preferredSigner);
+ WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"WindowsLoaderRefreshSource",
+ (wchar_t *) preferredCandidatePath.c_str (), FALSE);
+ return true;
+ }
+
void EfiBoot::SaveFile(const wchar_t* name, uint8* data, DWORD size) {
wstring path = EfiBootPartPath;
path += name;
@@ -4404,10 +4903,12 @@ namespace VeraCrypt
const wchar_t * szBackupMsBootloader = L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc";
const wchar_t * szStdEfiBootloader = L"\\EFI\\Boot\\bootx64.efi";
const wchar_t * szBackupEfiBootloader = L"\\EFI\\Boot\\original_bootx64.vc_backup";
+ const bool bCanRefreshWindowsLoaderFromOs = !hiddenOSCreation && !IsHiddenOSRunning ();
if (preserveUserConfig)
{
bool bModifiedMsBoot = true, bMissingMsBoot = false, bMsBootloaderMovedToBackup = false;
+ bool bWindowsLoaderRefreshedFromOs = false;
if (EfiBootInst.FileExists (szStdMsBootloader))
EfiBootInst.GetFileSize(szStdMsBootloader, loaderSize);
else
@@ -4485,10 +4986,21 @@ namespace VeraCrypt
}
if (!bFound && !PostOOBEMode)
- throw ErrorException ("WINDOWS_EFI_BOOT_LOADER_MISSING", SRC_POS);
+ {
+ // Windows keeps servicing copies outside the ESP. They are especially
+ // important after the 2023 CA migration, because the standard ESP path
+ // intentionally contains DcsBoot and Windows may therefore not replace it.
+ bWindowsLoaderRefreshedFromOs = bCanRefreshWindowsLoaderFromOs
+ && RefreshWindowsBootManagerFromWindows (EfiBootInst, szBackupMsBootloader);
+ if (!bWindowsLoaderRefreshedFromOs)
+ throw ErrorException ("WINDOWS_EFI_BOOT_LOADER_MISSING", SRC_POS);
+ }
}
}
+ if (bCanRefreshWindowsLoaderFromOs && !bWindowsLoaderRefreshedFromOs)
+ RefreshWindowsBootManagerFromWindows (EfiBootInst, szBackupMsBootloader);
+
if (PostOOBEMode && EfiBootInst.FileExists (L"\\EFI\\VeraCrypt\\DcsBoot.efi"))
{
const bool bRefreshMsBootloader = !bModifiedMsBoot
@@ -6212,6 +6724,44 @@ namespace VeraCrypt
*pMicrosoft2023UefiCAsSupported = GetPreferredEfiBootLoaderResourceSet ().ResourceSet == VC_EFI_BOOT_LOADER_RESOURCE_SET_2023;
}
+ static void RecordEfiBootChainTrustStatusDiagnostics (
+ const EfiBootChainTrustStatus& status,
+ DWORD chainError = ERROR_SUCCESS,
+ DWORD firmwareDbError = ERROR_SUCCESS,
+ DWORD firmwareDbxError = ERROR_SUCCESS)
+ {
+ DWORD previousLastError = GetLastError ();
+ WCHAR checkTimeUtc[32] = {0};
+ SYSTEMTIME systemTime;
+ GetSystemTime (&systemTime);
+ StringCchPrintfW (checkTimeUtc, ARRAYSIZE (checkTimeUtc), L"%04u-%02u-%02uT%02u:%02u:%02uZ",
+ systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
+
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"EfiBootChainStatusKnown", status.StatusKnown ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"EfiBootChainLastError", chainError);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"EfiBootLoaderFirmwareDbLastError", firmwareDbError);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"EfiBootLoaderFirmwareDbxLastError", firmwareDbxError);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"SecureBootEnabled", status.SecureBootEnabled ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"FirmwareDbxPresent", status.FirmwareDbxPresent ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"VeraCryptLoaderFilesValid", status.VeraCryptLoaderFilesValid ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"VeraCryptLoaderKnownCaAllowed", status.VeraCryptLoaderKnownCaAllowed ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"VeraCryptLoaderKnownCaRevoked", status.VeraCryptLoaderKnownCaRevoked ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"WindowsLoaderInspectionSucceeded", status.WindowsLoaderInspectionSucceeded ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"WindowsLoaderPresent", status.WindowsLoaderPresent ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"WindowsLoaderSigner", status.WindowsLoaderSigner);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"WindowsLoaderKnownCaAllowed", status.WindowsLoaderKnownCaAllowed ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"WindowsLoaderKnownCaRevoked", status.WindowsLoaderKnownCaRevoked ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"WindowsLoaderMigrationRecommended", status.WindowsLoaderMigrationRecommended ? 1 : 0);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"EfiBootLoaderInstalledResourceSet", status.InstalledResourceSet);
+ WriteEfiBootLoaderDiagnosticsRegistryDword (L"EfiBootLoaderRecordedResourceSet", status.RecordedResourceSet);
+ RegDeleteKeyValueW (HKEY_LOCAL_MACHINE, EfiBootLoaderDiagnosticsRegistryKey, L"VeraCryptLoaderTrusted");
+ RegDeleteKeyValueW (HKEY_LOCAL_MACHINE, EfiBootLoaderDiagnosticsRegistryKey, L"VeraCryptLoaderRevoked");
+ RegDeleteKeyValueW (HKEY_LOCAL_MACHINE, EfiBootLoaderDiagnosticsRegistryKey, L"WindowsLoaderTrusted");
+ RegDeleteKeyValueW (HKEY_LOCAL_MACHINE, EfiBootLoaderDiagnosticsRegistryKey, L"WindowsLoaderRevoked");
+ WriteLocalMachineRegistryString (EfiBootLoaderDiagnosticsRegistryKey, L"EfiBootChainCheckTimeUtc", checkTimeUtc, FALSE);
+ SetLastError (previousLastError);
+ }
+
bool BootEncryption::GetEfiBootChainTrustStatus (EfiBootChainTrustStatus& status)
{
memset (&status, 0, sizeof (status));
@@ -6222,57 +6772,122 @@ namespace VeraCrypt
bool bSecureBootEnabled = false;
if (!TryFirmwareSecureBootEnabled (bSecureBootEnabled))
- return false;
+ {
+ DWORD dwError = GetLastError ();
+ RecordEfiBootChainTrustStatusDiagnostics (status, dwError);
+ return true;
+ }
status.SecureBootEnabled = bSecureBootEnabled;
- // Trust facts are only asserted from a fully parsed firmware db: acting on
- // partial data could produce false "untrusted" reports.
+ // Known-CA policy facts are asserted only from fully parsed db and dbx
+ // variables. This does not model the other UEFI revocation forms (image
+ // hashes, certificate TBS hashes, and security-version revocations).
FirmwareDbMicrosoftUefiCaSupport support;
- if (!TryFirmwareDbGetMicrosoftUefiCaSupport (support) || support.DbMalformed)
- return false;
+ if (!TryFirmwareDbGetMicrosoftUefiCaSupport (support))
+ {
+ DWORD dwError = GetLastError ();
+ RecordEfiBootChainTrustStatusDiagnostics (status, dwError, dwError);
+ return true;
+ }
+ if (support.DbMalformed)
+ {
+ DWORD dwError = support.ParseError ? support.ParseError : ERROR_INVALID_DATA;
+ RecordEfiBootChainTrustStatusDiagnostics (status, dwError, dwError);
+ return true;
+ }
+
+ FirmwareDbMicrosoftUefiCaSupport forbiddenSupport;
+ bool bFirmwareDbxPresent = false;
+ if (!TryFirmwareDbxGetMicrosoftUefiCaSupport (forbiddenSupport, &bFirmwareDbxPresent))
+ {
+ DWORD dwError = GetLastError ();
+ RecordEfiBootChainTrustStatusDiagnostics (status, dwError, ERROR_SUCCESS, dwError);
+ return true;
+ }
+ if (forbiddenSupport.DbMalformed)
+ {
+ DWORD dwError = forbiddenSupport.ParseError ? forbiddenSupport.ParseError : ERROR_INVALID_DATA;
+ RecordEfiBootChainTrustStatusDiagnostics (status, dwError, ERROR_SUCCESS, dwError);
+ return true;
+ }
+ status.FirmwareDbxPresent = bFirmwareDbxPresent;
DWORD recordedResourceSet = 0;
- if (!ReadRecordedEfiBootLoaderResourceSet (recordedResourceSet))
- return false;
- status.InstalledResourceSet = recordedResourceSet;
-
- if (recordedResourceSet == VC_EFI_BOOT_LOADER_RESOURCE_SET_2023)
- status.VeraCryptLoaderTrusted = FirmwareDbMicrosoftUefiCaSupportContains2023Set (support);
- else if (recordedResourceSet == VC_EFI_BOOT_LOADER_RESOURCE_SET_2011)
- status.VeraCryptLoaderTrusted = support.ContainsMicrosoftCorporationUefiCa2011;
- else
- return false;
+ if (ReadRecordedEfiBootLoaderResourceSet (recordedResourceSet))
+ status.RecordedResourceSet = recordedResourceSet;
try
{
EfiBootInst.PrepareBootPartition (true);
- // The signer family of the chainloaded Windows boot manager copy is identified by the
- // issuer name embedded in its Authenticode certificate table. Like loader-set selection,
- // this is a byte-presence heuristic, not a signature verification.
- std::vector loader;
- if (EfiBootInst.ReadFileToBuffer (L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", loader) && !loader.empty ())
+ EfiBootLoaderImages images2011 = MapEfiBootLoaderImages (VC_EFI_BOOT_LOADER_RESOURCE_SET_2011, false);
+ EfiBootLoaderImages images2023 = MapEfiBootLoaderImages (VC_EFI_BOOT_LOADER_RESOURCE_SET_2023, false);
+ bool bMatches2011 = EfiBootLoaderImagesMatch (EfiBootInst, images2011);
+ bool bMatches2023 = EfiBootLoaderImagesMatch (EfiBootInst, images2023);
+ const EfiBootLoaderImages *installedImages = NULL;
+ if (bMatches2011 != bMatches2023)
{
- static const char szWindowsProductionPca2011Name[] = "Microsoft Windows Production PCA 2011";
- static const char szWindowsUefiCa2023Name[] = "Windows UEFI CA 2023";
- bool bSignedThroughPca2011 = BufferHasPattern (loader.data (), loader.size (), szWindowsProductionPca2011Name, strlen (szWindowsProductionPca2011Name));
- bool bSignedThroughWindowsCa2023 = BufferHasPattern (loader.data (), loader.size (), szWindowsUefiCa2023Name, strlen (szWindowsUefiCa2023Name));
+ installedImages = bMatches2023 ? &images2023 : &images2011;
+ status.InstalledResourceSet = installedImages->ResourceSet;
+ status.VeraCryptLoaderFilesValid = EfiBootLoaderStandardCopiesMatch (EfiBootInst, *installedImages);
+ }
- if (bSignedThroughPca2011 || bSignedThroughWindowsCa2023)
+ if (status.VeraCryptLoaderFilesValid && status.InstalledResourceSet == VC_EFI_BOOT_LOADER_RESOURCE_SET_2023)
+ {
+ status.VeraCryptLoaderKnownCaRevoked = forbiddenSupport.ContainsMicrosoftUefiCa2023
+ || forbiddenSupport.ContainsMicrosoftOptionRomUefiCa2023;
+ status.VeraCryptLoaderKnownCaAllowed = FirmwareDbMicrosoftUefiCaSupportContains2023Set (support)
+ && !status.VeraCryptLoaderKnownCaRevoked;
+ }
+ else if (status.VeraCryptLoaderFilesValid && status.InstalledResourceSet == VC_EFI_BOOT_LOADER_RESOURCE_SET_2011)
+ {
+ status.VeraCryptLoaderKnownCaRevoked = forbiddenSupport.ContainsMicrosoftCorporationUefiCa2011;
+ status.VeraCryptLoaderKnownCaAllowed = support.ContainsMicrosoftCorporationUefiCa2011
+ && !status.VeraCryptLoaderKnownCaRevoked;
+ }
+
+ status.WindowsLoaderPresent = EfiBootInst.FileExists (L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc");
+
+ if (status.WindowsLoaderPresent)
+ {
+ std::vector loader;
+ if (EfiBootInst.ReadFileToBuffer (L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", loader) && !loader.empty ())
{
- status.WindowsLoaderSignerKnown = true;
- status.WindowsLoaderTrusted =
- (bSignedThroughPca2011 && support.ContainsMicrosoftWindowsProductionPca2011)
- || (bSignedThroughWindowsCa2023 && support.ContainsWindowsUefiCa2023);
+ static const char windowsBootManagerMarker[] = "bootmgfw.pdb";
+ status.WindowsLoaderInspectionSucceeded = !BufferHasVeraCryptBootLoaderPattern (loader)
+ && BufferHasPattern (loader.data (), loader.size (), windowsBootManagerMarker, strlen (windowsBootManagerMarker))
+ && GetEmbeddedPeSignerFamily (loader, status.WindowsLoaderSigner);
+ if (status.WindowsLoaderInspectionSucceeded)
+ {
+ status.WindowsLoaderSignerKnown = status.WindowsLoaderSigner == VC_EFI_WINDOWS_LOADER_SIGNER_PCA_2011
+ || status.WindowsLoaderSigner == VC_EFI_WINDOWS_LOADER_SIGNER_CA_2023;
+ if (status.WindowsLoaderSigner == VC_EFI_WINDOWS_LOADER_SIGNER_PCA_2011)
+ {
+ status.WindowsLoaderKnownCaRevoked = forbiddenSupport.ContainsMicrosoftWindowsProductionPca2011;
+ status.WindowsLoaderKnownCaAllowed = support.ContainsMicrosoftWindowsProductionPca2011
+ && !status.WindowsLoaderKnownCaRevoked;
+ status.WindowsLoaderMigrationRecommended = status.WindowsLoaderKnownCaAllowed
+ && support.ContainsWindowsUefiCa2023;
+ }
+ else if (status.WindowsLoaderSigner == VC_EFI_WINDOWS_LOADER_SIGNER_CA_2023)
+ {
+ status.WindowsLoaderKnownCaRevoked = forbiddenSupport.ContainsWindowsUefiCa2023;
+ status.WindowsLoaderKnownCaAllowed = support.ContainsWindowsUefiCa2023
+ && !status.WindowsLoaderKnownCaRevoked;
+ }
+ }
}
}
}
catch (...)
{
- // The EFI system partition could not be inspected; the VeraCrypt loader facts above remain valid.
+ // The EFI system partition could not be inspected; the known CA facts above remain valid.
+ status.VeraCryptLoaderFilesValid = false;
+ status.WindowsLoaderInspectionSucceeded = false;
}
status.StatusKnown = true;
+ RecordEfiBootChainTrustStatusDiagnostics (status);
return true;
}
diff --git a/src/Common/BootEncryption.h b/src/Common/BootEncryption.h
index 1fb04a25..8f7ee0e7 100644
--- a/src/Common/BootEncryption.h
+++ b/src/Common/BootEncryption.h
@@ -232,16 +232,26 @@ namespace VeraCrypt
std::wstring BootVolumePath;
};
- // Trust facts about the installed EFI boot chain, derived from the active Secure Boot db.
- // Only valid when StatusKnown is true: partial or malformed firmware data never asserts facts.
+ // Known-CA compatibility facts for the installed EFI boot chain. UEFI dbx can
+ // also revoke individual image hashes, certificate TBS hashes, or security
+ // versions, so these fields deliberately do not claim complete firmware trust.
struct EfiBootChainTrustStatus
{
- bool StatusKnown; // Secure Boot state read and firmware db parsed completely
+ bool StatusKnown; // Secure Boot state read and firmware db/dbx CA entries parsed completely
bool SecureBootEnabled;
- bool VeraCryptLoaderTrusted; // signing CA(s) of the installed VeraCrypt EFI loader set found in db
- bool WindowsLoaderSignerKnown; // signer family of EFI\Microsoft\Boot\bootmgfw_ms.vc identified
- bool WindowsLoaderTrusted; // signing CA of bootmgfw_ms.vc found in db
- DWORD InstalledResourceSet; // VC_EFI_BOOT_LOADER_RESOURCE_SET_2011 or VC_EFI_BOOT_LOADER_RESOURCE_SET_2023
+ bool FirmwareDbxPresent; // false is valid and means the optional dbx variable is absent
+ bool VeraCryptLoaderFilesValid; // installed DCS files and any VeraCrypt standard-path copies match one embedded set
+ bool VeraCryptLoaderKnownCaAllowed; // required signing CA(s) found in db and no matching CA found in dbx
+ bool VeraCryptLoaderKnownCaRevoked; // at least one required signing CA found in dbx
+ bool WindowsLoaderInspectionSucceeded; // file read and embedded Authenticode signature parsed
+ bool WindowsLoaderPresent; // EFI\Microsoft\Boot\bootmgfw_ms.vc exists
+ bool WindowsLoaderSignerKnown; // embedded signer family of bootmgfw_ms.vc identified
+ bool WindowsLoaderKnownCaAllowed; // signing CA found in db and no matching CA found in dbx
+ bool WindowsLoaderKnownCaRevoked; // signing CA of bootmgfw_ms.vc found in dbx
+ bool WindowsLoaderMigrationRecommended; // PCA 2011 copy remains while Windows UEFI CA 2023 is available
+ DWORD WindowsLoaderSigner; // VC_EFI_WINDOWS_LOADER_SIGNER_* value
+ DWORD InstalledResourceSet; // resource set identified from the actual installed DCS files
+ DWORD RecordedResourceSet; // last resource set recorded at installation/refresh time
};
class BootEncryption
diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h
index a3b756e5..6ebb6c53 100644
--- a/src/Common/Dlgcode.h
+++ b/src/Common/Dlgcode.h
@@ -89,6 +89,9 @@ enum
#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_RESOURCE_SET_VALUE_NAME L"EfiBootLoaderRescueDiskResourceSet"
+#define VC_EFI_WINDOWS_LOADER_SIGNER_UNKNOWN 0
+#define VC_EFI_WINDOWS_LOADER_SIGNER_PCA_2011 2011
+#define VC_EFI_WINDOWS_LOADER_SIGNER_CA_2023 2023
#define VC_ERROR_EFI_UNSUPPORTED_SECURE_BOOT_DB ((DWORD) 0xE0000201)
#define VC_FILENAME_RENAMED_SUFFIX L"_old"
diff --git a/src/Common/Language.xml b/src/Common/Language.xml
index b981636f..f205f6f9 100644
--- a/src/Common/Language.xml
+++ b/src/Common/Language.xml
@@ -1685,11 +1685,12 @@
macOS reported the selected device as read-only. If this is an APFS disk, make sure you selected the physical APFS store partition, not an APFS synthesized volume. Use Disk Utility or 'diskutil list' to identify the physical partition, then retry.
This volume is registered as a System Favorite and its PIM and/or KDF settings were changed.\nDo you want VeraCrypt to automatically update the System Favorite configuration (administrator privileges required)?\n\nPlease note that if you answer no, you'll have to update the System Favorite manually.
The selected KDF uses different PIM parameters, so VeraCrypt will not reuse the current custom PIM. The new volume header will use the default PIM for the selected KDF unless you select "Use PIM" in the New section and enter a custom value.\n\nDo you want to continue?
- Secure Boot is enabled, but the firmware Secure Boot database does not trust any Microsoft UEFI CA set supported by VeraCrypt's EFI bootloader. Enable either Microsoft Corporation UEFI CA 2011, or both Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023, then run VeraCrypt Repair/Reinstall. Alternatively, disable Secure Boot.
+ VeraCrypt could not confirm that an EFI bootloader set is compatible with the current Secure Boot configuration. A required Microsoft CA may be missing from db or listed by dbx, or a firmware variable may be unreadable or malformed. An absent dbx variable is valid; a nonzero dbx diagnostic error is not.\n\nEnable either Microsoft Corporation UEFI CA 2011, or both Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023, and run VeraCrypt Repair/Reinstall. Keep Secure Boot disabled until the diagnostics show a complete compatible assessment.
A Terminal window will open after you press 'OK' and check the file system on the selected VeraCrypt volume using 'diskutil'. The result will be shown in that window.\n\nIf the check cannot be started, Disk Utility will be launched instead.
A Terminal window will open after you press 'OK' and attempt to repair the file system on the selected VeraCrypt volume using 'diskutil'. The result will be shown in that window.\n\nIf the repair cannot be started, Disk Utility will be launched instead.
- Warning: Secure Boot is enabled, but the Microsoft UEFI CA that signs the installed VeraCrypt EFI bootloader was not found in the firmware Secure Boot database (db). The firmware may refuse to start VeraCrypt at the next reboot, so Windows will not start until Secure Boot is disabled or the trusted certificates/loader set are repaired.\n\nBefore restarting this computer, do not disable or remove Microsoft Corporation UEFI CA 2011 unless the firmware db contains both Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023 and VeraCrypt has been repaired/reinstalled so the 2023-signed loader set is installed. Enable the required Microsoft certificates in the BIOS/UEFI settings if needed, then run VeraCrypt Repair/Reinstall. Make sure you have an up-to-date VeraCrypt Rescue Disk before restarting.
- Warning: Secure Boot is enabled, but the Microsoft CA that signs the Windows Boot Manager copy used by VeraCrypt (bootmgfw_ms.vc) was not found in the firmware Secure Boot database (db). After successful pre-boot authentication, the handoff to Windows may fail and the computer may return to the VeraCrypt password prompt.\n\nBefore restarting this computer, do not disable or revoke Microsoft Windows Production PCA 2011 unless Windows Boot Manager has migrated to a Windows UEFI CA 2023-signed version and the firmware db contains Windows UEFI CA 2023. Apply the Windows Secure Boot certificate updates, then run VeraCrypt Repair/Reinstall if needed. Make sure you have an up-to-date VeraCrypt Rescue Disk before restarting.
+ Warning: VeraCrypt could not validate the installed EFI bootloader files against one complete embedded resource set and confirm that all known required signing CAs are present in db and not listed by dbx. Firmware may reject VeraCrypt when Secure Boot is enabled.\n\nBefore booting with Secure Boot enabled, restore the required Microsoft certificates and current dbx as needed, then run VeraCrypt Repair/Reinstall. Do not remove Microsoft Corporation UEFI CA 2011 until db contains both Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023 and the actual installed files match VeraCrypt's 2023 set. This check cannot model every image-hash or security-version revocation. Make sure you have an up-to-date VeraCrypt Rescue Disk.
+ Warning: VeraCrypt could not validate the embedded signature and known-CA compatibility of the Windows Boot Manager it chainloads (bootmgfw_ms.vc). The file may be missing, unreadable, not a Windows Boot Manager, have an unrecognized embedded signer, or use a known signing CA that is absent from db or listed by dbx. The handoff to Windows may fail when Secure Boot is enabled.\n\nComplete or repair the Windows Secure Boot certificate and boot-manager update, keep the VeraCrypt System Favorites service enabled, and run VeraCrypt Repair/Reinstall. Repair also checks Windows' serviced EFI_EX/EFI copies for a compatible current Boot Manager. If Windows cannot start, temporarily disable Secure Boot to recover. Make sure you have an up-to-date VeraCrypt Rescue Disk.
+ Warning: The embedded signature of the Windows Boot Manager used by VeraCrypt (bootmgfw_ms.vc) is still issued by Microsoft Windows Production PCA 2011, although firmware db already contains Windows UEFI CA 2023. Its known CA is currently allowed, but it will no longer start after the PCA 2011 certificate is added to dbx.\n\nDo not apply the PCA 2011 revocation (AvailableUpdates bit 0x80, including combined value 0x280) yet. First complete the Windows 2023 boot-manager update while the VeraCrypt System Favorites service is enabled, then run VeraCrypt Repair/Reinstall so VeraCrypt can import a compatible serviced EFI_EX/EFI copy. Verify the embedded issuer of bootmgfw_ms.vc is Windows UEFI CA 2023 and make sure you have an up-to-date VeraCrypt Rescue Disk.
diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c
index 88a72033..8d72805d 100644
--- a/src/Mount/Mount.c
+++ b/src/Mount/Mount.c
@@ -10836,7 +10836,7 @@ static void SystemFavoritesServiceLogBootLoaderUpdateError (const wchar_t *opera
{
if (IsUnsupportedEfiSecureBootDbException (e))
{
- SystemFavoritesServiceLogError (wstring (operation) + L" failed: Secure Boot is enabled, but the firmware Secure Boot db does not trust any Microsoft UEFI CA set supported by VeraCrypt. See HKLM\\SOFTWARE\\VeraCrypt\\Diagnostics\\EfiBootLoader for the recorded selection reason.");
+ SystemFavoritesServiceLogError (wstring (operation) + L" failed: Secure Boot is enabled, but the firmware Secure Boot db/dbx policy does not permit a Microsoft UEFI CA set supported by VeraCrypt, or the policy could not be read completely. See HKLM\\SOFTWARE\\VeraCrypt\\Diagnostics\\EfiBootLoader for the recorded selection reason.");
return;
}
@@ -10881,6 +10881,15 @@ static BOOL GetSystemFavoritesServiceBootLoaderUpdateOptions (uint32 serviceFlag
return TRUE;
}
+enum
+{
+ VC_EFI_BOOT_CHAIN_WARNING_VERACRYPT_LOADER = 0x01,
+ VC_EFI_BOOT_CHAIN_WARNING_WINDOWS_LOADER = 0x02,
+ VC_EFI_BOOT_CHAIN_WARNING_WINDOWS_MIGRATION = 0x04
+};
+
+static DWORD SystemFavoritesServiceLastEfiBootChainWarningMask = MAXDWORD;
+
static void SystemFavoritesServiceUpdateLoaderProcessing (BOOL bForce)
{
SystemFavoritesServiceLogInfo (L"SystemFavoritesServiceUpdateLoaderProcessing called");
@@ -10901,18 +10910,39 @@ static void SystemFavoritesServiceUpdateLoaderProcessing (BOOL bForce)
bootEnc.InstallBootLoader (true);
SystemFavoritesServiceLogInfo (L"SystemFavoritesServiceUpdateLoaderProcessing: InstallBootLoader called");
- // Record in the event log when the active Secure Boot db no longer trusts a
- // component of the boot chain (e.g. after a Secure Boot certificate update),
- // so that a subsequent pre-boot failure can be diagnosed from Windows.
+ // Record actual-file and known-CA compatibility failures so a subsequent
+ // firmware-enforced pre-boot failure can be diagnosed from Windows.
try
{
EfiBootChainTrustStatus trustStatus;
- if (bootEnc.GetEfiBootChainTrustStatus (trustStatus) && trustStatus.StatusKnown && trustStatus.SecureBootEnabled)
+ if (bootEnc.GetEfiBootChainTrustStatus (trustStatus))
{
- if (!trustStatus.VeraCryptLoaderTrusted)
- SystemFavoritesServiceLogWarning (L"Secure Boot chain check: the firmware Secure Boot db does not trust the Microsoft UEFI CA that signs the installed VeraCrypt EFI bootloader. Pre-boot authentication may fail at the next reboot.");
- else if (trustStatus.WindowsLoaderSignerKnown && !trustStatus.WindowsLoaderTrusted)
- SystemFavoritesServiceLogWarning (L"Secure Boot chain check: the firmware Secure Boot db does not trust the Microsoft CA that signs the Windows boot manager copy used by VeraCrypt (bootmgfw_ms.vc). The handoff to Windows after pre-boot authentication may fail at the next reboot.");
+ DWORD warningMask = 0;
+ if (!trustStatus.StatusKnown
+ || !trustStatus.VeraCryptLoaderFilesValid
+ || !trustStatus.VeraCryptLoaderKnownCaAllowed)
+ warningMask |= VC_EFI_BOOT_CHAIN_WARNING_VERACRYPT_LOADER;
+ if (trustStatus.StatusKnown && (!trustStatus.WindowsLoaderInspectionSucceeded
+ || !trustStatus.WindowsLoaderPresent
+ || !trustStatus.WindowsLoaderSignerKnown
+ || !trustStatus.WindowsLoaderKnownCaAllowed))
+ warningMask |= VC_EFI_BOOT_CHAIN_WARNING_WINDOWS_LOADER;
+ else if (trustStatus.StatusKnown && trustStatus.WindowsLoaderMigrationRecommended)
+ warningMask |= VC_EFI_BOOT_CHAIN_WARNING_WINDOWS_MIGRATION;
+
+ // The service refreshes the loader at several lifecycle events. Emit each
+ // unchanged warning state only once per service process to avoid log spam.
+ if (warningMask != SystemFavoritesServiceLastEfiBootChainWarningMask)
+ {
+ if (warningMask & VC_EFI_BOOT_CHAIN_WARNING_VERACRYPT_LOADER)
+ SystemFavoritesServiceLogWarning (L"Secure Boot compatibility check: VeraCrypt could not validate the installed DCS files against an embedded loader set and confirm that its known signing CAs are allowed by db and not listed by dbx. Do not boot with Secure Boot enabled until the policy and loader set have been repaired.");
+ if (warningMask & VC_EFI_BOOT_CHAIN_WARNING_WINDOWS_LOADER)
+ SystemFavoritesServiceLogWarning (L"Secure Boot compatibility check: the Windows boot manager used by VeraCrypt (bootmgfw_ms.vc) is missing or unreadable, its embedded signer is unrecognized, or its known signing CA is not allowed by db or is listed by dbx. The handoff to Windows may fail when Secure Boot is enabled.");
+ else if (warningMask & VC_EFI_BOOT_CHAIN_WARNING_WINDOWS_MIGRATION)
+ SystemFavoritesServiceLogWarning (L"Secure Boot transition check: bootmgfw_ms.vc is still signed by Microsoft Windows Production PCA 2011 although firmware db already contains Windows UEFI CA 2023. Complete the Windows 2023 boot manager update before applying the PCA 2011 dbx revocation.");
+
+ SystemFavoritesServiceLastEfiBootChainWarningMask = warningMask;
+ }
}
}
catch (...) { }
diff --git a/src/Setup/Setup.c b/src/Setup/Setup.c
index 33c92acb..8e466192 100644
--- a/src/Setup/Setup.c
+++ b/src/Setup/Setup.c
@@ -1799,18 +1799,25 @@ BOOL UpgradeBootLoader (HWND hwndDlg)
bootEnc.InstallBootLoader (true);
- // Verify the whole boot chain against the active Secure Boot db before the user
- // reboots: a component that the firmware no longer trusts (e.g. after a Secure Boot
- // certificate update) would otherwise only surface as a pre-boot failure.
+ // Validate the actual boot files and their known-CA compatibility with the active
+ // Secure Boot db/dbx before the user reboots. Other dbx revocation forms remain
+ // firmware-enforced and cannot be completely predicted here.
try
{
EfiBootChainTrustStatus trustStatus;
- if (bootEnc.GetEfiBootChainTrustStatus (trustStatus) && trustStatus.StatusKnown && trustStatus.SecureBootEnabled)
+ if (bootEnc.GetEfiBootChainTrustStatus (trustStatus))
{
- if (!trustStatus.VeraCryptLoaderTrusted)
+ if (!trustStatus.StatusKnown)
+ Warning ("SYSENC_EFI_UNSUPPORTED_SECUREBOOT_CA", hwndDlg);
+ else if (!trustStatus.VeraCryptLoaderFilesValid || !trustStatus.VeraCryptLoaderKnownCaAllowed)
Warning ("SYSENC_EFI_LOADER_NOT_TRUSTED_BY_SECUREBOOT", hwndDlg);
- else if (trustStatus.WindowsLoaderSignerKnown && !trustStatus.WindowsLoaderTrusted)
+ if (trustStatus.StatusKnown && (!trustStatus.WindowsLoaderInspectionSucceeded
+ || !trustStatus.WindowsLoaderPresent
+ || !trustStatus.WindowsLoaderSignerKnown
+ || !trustStatus.WindowsLoaderKnownCaAllowed))
Warning ("SYSENC_EFI_WINDOWS_LOADER_NOT_TRUSTED_BY_SECUREBOOT", hwndDlg);
+ else if (trustStatus.StatusKnown && trustStatus.WindowsLoaderMigrationRecommended)
+ Warning ("SYSENC_EFI_WINDOWS_LOADER_PCA2011_MIGRATION_NEEDED", hwndDlg);
}
}
catch (...) { }
diff --git a/src/SetupDLL/Setup.c b/src/SetupDLL/Setup.c
index 29589855..0f0f6651 100644
--- a/src/SetupDLL/Setup.c
+++ b/src/SetupDLL/Setup.c
@@ -1826,9 +1826,8 @@ BOOL UpgradeBootLoader_Dll (MSIHANDLE hInstaller, HWND hwndDlg)
// this is done by the service now
//bootEnc.InstallBootLoader (true);
- // Verify the installed boot chain against the active Secure Boot db before the user
- // reboots: a component that the firmware no longer trusts (e.g. after a Secure Boot
- // certificate update) would otherwise only surface as a pre-boot failure. In the MSI
+ // Validate the installed boot files and their known-CA compatibility with the active
+ // Secure Boot db/dbx before the user reboots. In the MSI
// upgrade path, the System Favorites service has already attempted the loader refresh.
try
{
@@ -1839,12 +1838,19 @@ BOOL UpgradeBootLoader_Dll (MSIHANDLE hInstaller, HWND hwndDlg)
else
{
EfiBootChainTrustStatus trustStatus;
- if (bootEnc.GetEfiBootChainTrustStatus (trustStatus) && trustStatus.StatusKnown && trustStatus.SecureBootEnabled)
+ if (bootEnc.GetEfiBootChainTrustStatus (trustStatus))
{
- if (!trustStatus.VeraCryptLoaderTrusted)
+ if (!trustStatus.StatusKnown)
+ MSILogAndShow (hInstaller, MSI_WARNING_LEVEL, GetString("SYSENC_EFI_UNSUPPORTED_SECUREBOOT_CA"));
+ else if (!trustStatus.VeraCryptLoaderFilesValid || !trustStatus.VeraCryptLoaderKnownCaAllowed)
MSILogAndShow (hInstaller, MSI_WARNING_LEVEL, GetString("SYSENC_EFI_LOADER_NOT_TRUSTED_BY_SECUREBOOT"));
- else if (trustStatus.WindowsLoaderSignerKnown && !trustStatus.WindowsLoaderTrusted)
+ if (trustStatus.StatusKnown && (!trustStatus.WindowsLoaderInspectionSucceeded
+ || !trustStatus.WindowsLoaderPresent
+ || !trustStatus.WindowsLoaderSignerKnown
+ || !trustStatus.WindowsLoaderKnownCaAllowed))
MSILogAndShow (hInstaller, MSI_WARNING_LEVEL, GetString("SYSENC_EFI_WINDOWS_LOADER_NOT_TRUSTED_BY_SECUREBOOT"));
+ else if (trustStatus.StatusKnown && trustStatus.WindowsLoaderMigrationRecommended)
+ MSILogAndShow (hInstaller, MSI_WARNING_LEVEL, GetString("SYSENC_EFI_WINDOWS_LOADER_PCA2011_MIGRATION_NEEDED"));
}
}
}