From 8b2a3ca9bde898e1ae4ce3d99abdb181b18d7209 Mon Sep 17 00:00:00 2001 From: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Date: Mon, 29 Jun 2026 07:31:46 -0700 Subject: [PATCH 1/2] fix: clarify outer-vs-hidden credentials in hidden volume protection UI Fixes #1673 --- src/Common/Language.xml | 6 ++++-- src/Mount/Mount.c | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Common/Language.xml b/src/Common/Language.xml index b981636fc5..e84d20d294 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -89,6 +89,7 @@ Current pool content (partial) Pass Password: + Outer p&assword: Volume PIM: Volume PIM: Progress: @@ -350,8 +351,8 @@ Speed is affected by CPU load and storage device characteristics.\n\nThese tests take place in RAM. Buffer Size: Cipher: - P&assword to hidden volume:\n(if empty, cache is used) - Hidden Volume Protection + Hidden volume p&assword:\n(if empty, cache is used) + Hidden Volume Protection (Hidden Credentials) Key size: IMPORTANT: Move your mouse as randomly as possible within this window. The longer you move it, the better. This significantly increases the cryptographic strength of the keyfile. WARNING: If you lose a keyfile or if any bit of its first 1024 kilobytes changes, it will be impossible to mount volumes that use the keyfile! @@ -637,6 +638,7 @@ Operation failed due to one or more of the following:\n - Wrong mount mode.\n - Incorrect keyfile(s).\n - Incorrect password.\n - Incorrect Volume PIM number.\n - Incorrect PRF (hash).\n - Not a valid volume.\n - Volume uses an old algorithm that has been removed.\n - TrueCrypt format volumes are no longer supported. Auto-mount failed due to one or more of the following:\n - Incorrect password.\n - Incorrect Volume PIM number.\n - Incorrect PRF (hash).\n - No valid volume found.\n - Volume uses an old algorithm that has been removed.\n - TrueCrypt format volumes are no longer supported. Auto-mount failed due to one or more of the following:\n - Incorrect keyfile(s).\n - Incorrect password.\n - Incorrect Volume PIM number.\n - Incorrect PRF (hash).\n - No valid volume found.\n - Volume uses an old algorithm that has been removed.\n - TrueCrypt format volumes are no longer supported. + Operation failed while hidden volume protection was enabled.\n\nUse the OUTER (decoy) volume password, PIM, PRF, and keyfile(s), if any, in the main password dialog. Use the HIDDEN volume password, PIM, PRF, and keyfile(s), if any, in Mount Options > Hidden Volume Protection.\n\nOne or more credentials may be incorrect, or the selected volume may be invalid or unsupported. \n\nWarning: Caps Lock is on. This may cause you to enter your password incorrectly. Remember Number to Mount Volume Outer Volume PIM diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index 88a720334f..ac3c350f5b 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -3572,6 +3572,12 @@ static wchar_t PasswordDlgVolume[MAX_PATH + 1]; static BOOL PasswordDialogDisableMountOptions; static char *PasswordDialogTitleStringId; +static void UpdatePasswordDlgPasswordLabel (HWND hwndDlg) +{ + SetDlgItemTextW (hwndDlg, IDT_PASSWORD, + GetString (!PasswordDialogDisableMountOptions && mountOptions.ProtectHiddenVolume ? "IDT_OUTER_VOL_PASSWORD" : "IDT_PASSWORD")); +} + /* Except in response to the WM_INITDIALOG message, the dialog box procedure should return nonzero if it processes the message, and zero if it does not. - see DialogProc */ @@ -3591,6 +3597,7 @@ BOOL CALLBACK PasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa pkcs5 = ((PasswordDlgParam *) lParam) -> pkcs5; pim = ((PasswordDlgParam *) lParam) -> pim; LocalizeDialog (hwndDlg, "IDD_PASSWORD_DLG"); + UpdatePasswordDlgPasswordLabel (hwndDlg); DragAcceptFiles (hwndDlg, TRUE); if (PasswordDialogTitleStringId) @@ -3842,6 +3849,7 @@ BOOL CALLBACK PasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), hwndDlg, (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions); + UpdatePasswordDlgPasswordLabel (hwndDlg); if (!bPrebootPasswordDlgMode && mountOptions.PartitionInInactiveSysEncScope) SendMessage (hwndDlg, TC_APPMSG_PREBOOT_PASSWORD_MODE, 0, 0); @@ -6618,7 +6626,8 @@ static BOOL MountAllDevicesThreadCode (HWND hwndDlg, MountAllDevicesThreadParam* { WCHAR szTmp[4096]; - StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable || FirstCmdKeyFile ? "PASSWORD_OR_KEYFILE_WRONG_AUTOMOUNT" : "PASSWORD_WRONG_AUTOMOUNT")); + StringCbPrintfW (szTmp, sizeof(szTmp), + GetString (mountOptions.ProtectHiddenVolume ? "HIDVOL_PROT_PASSWORD_OR_KEYFILE_WRONG" : (KeyFilesEnable || FirstCmdKeyFile ? "PASSWORD_OR_KEYFILE_WRONG_AUTOMOUNT" : "PASSWORD_WRONG_AUTOMOUNT"))); if (CheckCapsLock (hwndDlg, TRUE)) StringCbCatW (szTmp, sizeof(szTmp), GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); From 55ce763f718d2be434ae9438c5a97002e0fe5f77 Mon Sep 17 00:00:00 2001 From: mvanhorn Date: Mon, 6 Jul 2026 07:38:47 -0700 Subject: [PATCH 2/2] Address @idrassi review: clarify hidden-vol-protection credentials - Single-volume mount failures under hidden volume protection now show the clarified HIDVOL_PROT_PASSWORD_OR_KEYFILE_WRONG guidance (via a new GetWrongPasswordErrorMessageEx with a hiddenVolumeProtection flag), not just the Auto-Mount path. The block is reached only for ERR_PASSWORD_WRONG. - Main password dialog now shows an info balloon (HIDVOL_PROT_OUTER_CREDENTIALS_NOTE) noting the dialog expects OUTER volume credentials (password, PIM, PRF/KDF, keyfiles) when hidden volume protection is enabled, covering the PIM/PRF/keyfile ambiguity, not just the password label. - Move the newly added Language.xml entries to the end of the en block so translators can track new strings. --- src/Common/Dlgcode.c | 44 +++++++++++++++++++++++++++-------------- src/Common/Language.xml | 9 +++++---- src/Mount/Mount.c | 15 +++++++++++++- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index ed03e5b4df..42d427492b 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -5748,11 +5748,11 @@ BOOL BrowseDirectories(HWND hwndDlg, char *lpszDlgTitle, wchar_t *dirName, const return bOK; } -std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg) +static std::wstring GetWrongPasswordErrorMessageEx (HWND hwndDlg, BOOL hiddenVolumeProtection) { WCHAR szTmp[8192]; - StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_WRONG" : "PASSWORD_WRONG")); + StringCbPrintfW (szTmp, sizeof(szTmp), GetString (hiddenVolumeProtection ? "HIDVOL_PROT_PASSWORD_OR_KEYFILE_WRONG" : (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_WRONG" : "PASSWORD_WRONG"))); if (CheckCapsLock (hwndDlg, TRUE)) StringCbCatW (szTmp, sizeof(szTmp), GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); @@ -5760,7 +5760,7 @@ std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg) wchar_t szDevicePath [TC_MAX_PATH+1] = {0}; GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szDevicePath, ARRAYSIZE (szDevicePath)); - if (TCBootLoaderOnInactiveSysEncDrive (szDevicePath)) + if (!hiddenVolumeProtection && TCBootLoaderOnInactiveSysEncDrive (szDevicePath)) { StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_OR_MODE_WRONG" : "PASSWORD_OR_MODE_WRONG")); @@ -5784,6 +5784,11 @@ std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg) return msg; } +std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg) +{ + return GetWrongPasswordErrorMessageEx (hwndDlg, FALSE); +} + void handleError (HWND hwndDlg, int code, const char* srcPos) { @@ -9577,24 +9582,33 @@ int MountVolume (HWND hwndDlg, goto retry; } - if (bDevice && mount.bProtectHiddenVolume) + if (mount.bProtectHiddenVolume) { - int diskNo; + BOOL passwordErrorMessageShown = FALSE; - if (swscanf (volumePath, L"\\Device\\Harddisk%d\\Partition", &diskNo) == 1) + if (bDevice) { - OPEN_TEST_STRUCT openTestStruct; - memset (&openTestStruct, 0, sizeof (openTestStruct)); + int diskNo; + + if (swscanf (volumePath, L"\\Device\\Harddisk%d\\Partition", &diskNo) == 1) + { + OPEN_TEST_STRUCT openTestStruct; + memset (&openTestStruct, 0, sizeof (openTestStruct)); - openTestStruct.bDetectTCBootLoader = TRUE; - StringCchPrintfW ((wchar_t *) openTestStruct.wszFileName, array_capacity (openTestStruct.wszFileName), L"\\Device\\Harddisk%d\\Partition0", diskNo); + openTestStruct.bDetectTCBootLoader = TRUE; + StringCchPrintfW ((wchar_t *) openTestStruct.wszFileName, array_capacity (openTestStruct.wszFileName), L"\\Device\\Harddisk%d\\Partition0", diskNo); - DWORD cbBytesReturned; - if (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, &openTestStruct, sizeof (OPEN_TEST_STRUCT), &openTestStruct, sizeof (OPEN_TEST_STRUCT), &cbBytesReturned, NULL) && openTestStruct.TCBootLoaderDetected) - WarningDirect ((GetWrongPasswordErrorMessage (hwndDlg) + L"\n\n" + GetString ("HIDDEN_VOL_PROT_PASSWORD_US_KEYB_LAYOUT")).c_str(), hwndDlg); - else - handleError (hwndDlg, mount.nReturnCode, SRC_POS); + DWORD cbBytesReturned; + if (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, &openTestStruct, sizeof (OPEN_TEST_STRUCT), &openTestStruct, sizeof (OPEN_TEST_STRUCT), &cbBytesReturned, NULL) && openTestStruct.TCBootLoaderDetected) + { + WarningDirect ((GetWrongPasswordErrorMessageEx (hwndDlg, TRUE) + L"\n\n" + GetString ("HIDDEN_VOL_PROT_PASSWORD_US_KEYB_LAYOUT")).c_str(), hwndDlg); + passwordErrorMessageShown = TRUE; + } + } } + + if (!passwordErrorMessageShown) + MessageBoxW (hwndDlg, AppendSrcPos (GetWrongPasswordErrorMessageEx (hwndDlg, TRUE).c_str(), SRC_POS).c_str(), lpszTitle, MB_ICONWARNING); } else handleError (hwndDlg, mount.nReturnCode, SRC_POS); diff --git a/src/Common/Language.xml b/src/Common/Language.xml index e84d20d294..35b72a8e1b 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -89,7 +89,6 @@ Current pool content (partial) Pass Password: - Outer p&assword: Volume PIM: Volume PIM: Progress: @@ -351,8 +350,6 @@ Speed is affected by CPU load and storage device characteristics.\n\nThese tests take place in RAM. Buffer Size: Cipher: - Hidden volume p&assword:\n(if empty, cache is used) - Hidden Volume Protection (Hidden Credentials) Key size: IMPORTANT: Move your mouse as randomly as possible within this window. The longer you move it, the better. This significantly increases the cryptographic strength of the keyfile. WARNING: If you lose a keyfile or if any bit of its first 1024 kilobytes changes, it will be impossible to mount volumes that use the keyfile! @@ -638,7 +635,6 @@ Operation failed due to one or more of the following:\n - Wrong mount mode.\n - Incorrect keyfile(s).\n - Incorrect password.\n - Incorrect Volume PIM number.\n - Incorrect PRF (hash).\n - Not a valid volume.\n - Volume uses an old algorithm that has been removed.\n - TrueCrypt format volumes are no longer supported. Auto-mount failed due to one or more of the following:\n - Incorrect password.\n - Incorrect Volume PIM number.\n - Incorrect PRF (hash).\n - No valid volume found.\n - Volume uses an old algorithm that has been removed.\n - TrueCrypt format volumes are no longer supported. Auto-mount failed due to one or more of the following:\n - Incorrect keyfile(s).\n - Incorrect password.\n - Incorrect Volume PIM number.\n - Incorrect PRF (hash).\n - No valid volume found.\n - Volume uses an old algorithm that has been removed.\n - TrueCrypt format volumes are no longer supported. - Operation failed while hidden volume protection was enabled.\n\nUse the OUTER (decoy) volume password, PIM, PRF, and keyfile(s), if any, in the main password dialog. Use the HIDDEN volume password, PIM, PRF, and keyfile(s), if any, in Mount Options > Hidden Volume Protection.\n\nOne or more credentials may be incorrect, or the selected volume may be invalid or unsupported. \n\nWarning: Caps Lock is on. This may cause you to enter your password incorrectly. Remember Number to Mount Volume Outer Volume PIM @@ -1692,6 +1688,11 @@ 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. + Outer p&assword: + Hidden volume p&assword:\n(if empty, cache is used) + Hidden Volume Protection (Hidden Credentials) + Operation failed while hidden volume protection was enabled.\n\nUse the OUTER (decoy) volume password, PIM, PRF, and keyfile(s), if any, in the main password dialog. Use the HIDDEN volume password, PIM, PRF, and keyfile(s), if any, in Mount Options > Hidden Volume Protection.\n\nOne or more credentials may be incorrect, or the selected volume may be invalid or unsupported. + Use OUTER (decoy) volume password, PIM, PRF/KDF, and keyfile(s) here. Use HIDDEN credentials in Mount Options > Hidden Volume Protection. diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index ac3c350f5b..b0e0416f62 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -3576,6 +3576,19 @@ static void UpdatePasswordDlgPasswordLabel (HWND hwndDlg) { SetDlgItemTextW (hwndDlg, IDT_PASSWORD, GetString (!PasswordDialogDisableMountOptions && mountOptions.ProtectHiddenVolume ? "IDT_OUTER_VOL_PASSWORD" : "IDT_PASSWORD")); + + if (!PasswordDialogDisableMountOptions && mountOptions.ProtectHiddenVolume) + { + EDITBALLOONTIP ebt; + ebt.cbStruct = sizeof (EDITBALLOONTIP); + ebt.pszText = GetString ("HIDVOL_PROT_OUTER_CREDENTIALS_NOTE"); + ebt.pszTitle = GetString ("IDT_HIDDEN_VOL_PROTECTION"); + ebt.ttiIcon = TTI_INFO_LARGE; + + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_SHOWBALLOONTIP, 0, (LPARAM) &ebt); + } + else + SendMessage (GetDlgItem (hwndDlg, IDC_PASSWORD), EM_HIDEBALLOONTIP, 0, 0); } /* Except in response to the WM_INITDIALOG message, the dialog box procedure @@ -3597,7 +3610,6 @@ BOOL CALLBACK PasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa pkcs5 = ((PasswordDlgParam *) lParam) -> pkcs5; pim = ((PasswordDlgParam *) lParam) -> pim; LocalizeDialog (hwndDlg, "IDD_PASSWORD_DLG"); - UpdatePasswordDlgPasswordLabel (hwndDlg); DragAcceptFiles (hwndDlg, TRUE); if (PasswordDialogTitleStringId) @@ -3646,6 +3658,7 @@ BOOL CALLBACK PasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa SendMessage (hComboBox, CB_SETCURSEL, defaultPrfIndex, 0); ToNormalPwdField (hwndDlg, IDC_PASSWORD); + UpdatePasswordDlgPasswordLabel (hwndDlg); SendMessage (GetDlgItem (hwndDlg, IDC_CACHE), BM_SETCHECK, bCacheInDriver ? BST_CHECKED:BST_UNCHECKED, 0); SendMessage (GetDlgItem (hwndDlg, IDC_PIM), EM_LIMITTEXT, MAX_PIM, 0);