diff --git a/doc/chm/VeraCrypt User Guide.chm b/doc/chm/VeraCrypt User Guide.chm
index fb895efa..9615fadf 100644
Binary files a/doc/chm/VeraCrypt User Guide.chm and b/doc/chm/VeraCrypt User Guide.chm differ
diff --git a/doc/html/Personal Iterations Multiplier (PIM).html b/doc/html/Personal Iterations Multiplier (PIM).html
index b039a74f..d2da3b7b 100644
--- a/doc/html/Personal Iterations Multiplier (PIM).html
+++ b/doc/html/Personal Iterations Multiplier (PIM).html
@@ -44,7 +44,7 @@
PIM
Header Key Derivation).
When a PIM value is specified, the number of iterations is calculated as follows:
-- For system encryption: Iterations = PIM x 2048
- For non-system encryption and file containers: Iterations = 15000 + (PIM x 1000)
+
- For system encryption that doesn't use SHA-512 or Whirlpool: Iterations = PIM x 2048
- For system encryption that uses SHA-512 or Whirlpool, non-system encryption and file containers: Iterations = 15000 + (PIM x 1000)
Prior to version 1.12, the security of a VeraCrypt volume was only based on the password strength because VeraCrypt was using a fixed number of iterations.
With the introduction of PIM, VeraCrypt has a 2-dimensional security space for volumes based on the couple (Password, PIM). This provides more flexibility for adjusting the desired security level while also controlling the performance of the mount/boot operation.
@@ -61,8 +61,8 @@ PIM Usage
During the creation of a volume or the encryption of the system, VeraCrypt forces the PIM value to be greater than or equal to a certain minimal value when the password is less than 20 characters. This check is done in order to ensure that, for short passwords,
the security level is at least equal to the default level provided by an empty PIM.
-The PIM minimal value for short passwords is
98 for system encryption and
-
485 for non-system encryption and files containers. For password with 20 characters and more, the PIM minimal value is
+
The PIM minimal value for short passwords is
98 for system encryption that doesn't use SHA-512 or Whirlpool and
+
485 for the other cases. For password with 20 characters and more, the PIM minimal value is
1. In all cases, leaving the PIM empty or setting its value to 0 will make VeraCrypt use the default high number of iterations as explained in section
Header Key Derivation.
@@ -70,7 +70,7 @@
PIM Usage
Motivations behind using a custom PIM value can be:
- Add an extra secret parameter (PIM) that an attacker will have to guess
- Increase security level by using large PIM values to thwart future development of brute force attacks.
-
- Speeding up booting or mounting through the use of a small PIM value (less than 98 for system encryption and less than 485 for the other cases)
+
- Speeding up booting or mounting through the use of a small PIM value (less than 98 for system encryption that doesn't use SHA-512 or Whirlpool and less than 485 for the other cases)
The screenshots below show the step to mount a volume using a PIM equal to 231:
diff --git a/src/Common/Password.c b/src/Common/Password.c
index e3876042..8ba91374 100644
--- a/src/Common/Password.c
+++ b/src/Common/Password.c
@@ -133,14 +133,15 @@ BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw)
}
-BOOL CheckPasswordLength (HWND hwndDlg, unsigned __int32 passwordLength, int pim, BOOL bForBoot, BOOL bSkipPasswordWarning, BOOL bSkipPimWarning)
+BOOL CheckPasswordLength (HWND hwndDlg, unsigned __int32 passwordLength, int pim, BOOL bForBoot, int bootPRF, BOOL bSkipPasswordWarning, BOOL bSkipPimWarning)
{
- BOOL bCustomPimSmall = ((pim != 0) && (pim < (bForBoot? 98 : 485)))? TRUE : FALSE;
+ BOOL bootPimCondition = (bForBoot && (bootPRF != SHA512 && bootPRF != WHIRLPOOL))? TRUE : FALSE;
+ BOOL bCustomPimSmall = ((pim != 0) && (pim < (bootPimCondition? 98 : 485)))? TRUE : FALSE;
if (passwordLength < PASSWORD_LEN_WARNING)
{
if (bCustomPimSmall)
{
- Error (bForBoot? "BOOT_PIM_REQUIRE_LONG_PASSWORD": "PIM_REQUIRE_LONG_PASSWORD", hwndDlg);
+ Error (bootPimCondition? "BOOT_PIM_REQUIRE_LONG_PASSWORD": "PIM_REQUIRE_LONG_PASSWORD", hwndDlg);
return FALSE;
}
@@ -157,7 +158,7 @@ BOOL CheckPasswordLength (HWND hwndDlg, unsigned __int32 passwordLength, int pim
}
#endif
- if ((pim != 0) && (pim > (bForBoot? 98 : 485)))
+ if ((pim != 0) && (pim > (bootPimCondition? 98 : 485)))
{
// warn that mount/boot will take more time
Warning ("PIM_LARGE_WARNING", hwndDlg);
diff --git a/src/Common/Password.h b/src/Common/Password.h
index 9afcd060..b2b0511d 100644
--- a/src/Common/Password.h
+++ b/src/Common/Password.h
@@ -39,7 +39,7 @@ typedef struct
#if defined(_WIN32) && !defined(TC_WINDOWS_DRIVER) && !defined(_UEFI)
void VerifyPasswordAndUpdate ( HWND hwndDlg , HWND hButton , HWND hPassword , HWND hVerify , unsigned char *szPassword , char *szVerify, BOOL keyFilesEnabled );
-BOOL CheckPasswordLength (HWND hwndDlg, unsigned __int32 passwordLength, int pim, BOOL bForBoot, BOOL bSkipPasswordWarning, BOOL bSkipPimWarning);
+BOOL CheckPasswordLength (HWND hwndDlg, unsigned __int32 passwordLength, int pim, BOOL bForBoot, int bootPRF, BOOL bSkipPasswordWarning, BOOL bSkipPimWarning);
BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw);
int ChangePwd (const wchar_t *lpszVolume, Password *oldPassword, int old_pkcs5, int old_pim, BOOL truecryptMode, Password *newPassword, int pkcs5, int pim, int wipePassCount, HWND hwndDlg);
diff --git a/src/Format/Tcformat.c b/src/Format/Tcformat.c
index 5b1b0d16..09c52705 100644
--- a/src/Format/Tcformat.c
+++ b/src/Format/Tcformat.c
@@ -4404,7 +4404,7 @@ BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
SetFocus (GetDlgItem (hwndDlg, IDC_PIM));
- SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (SysEncInEffect ()? "PIM_SYSENC_HELP" : "PIM_HELP"));
+ SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (SysEncInEffect () && hash_algo != SHA512 && hash_algo != WHIRLPOOL? "PIM_SYSENC_HELP" : "PIM_HELP"));
ToHyperlink (hwndDlg, IDC_LINK_PIM_INFO);
@@ -6238,7 +6238,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
if (volumePassword.Length > 0)
{
// Check password length (check also done for outer volume which is not the case in TrueCrypt).
- if (!CheckPasswordLength (NULL, volumePassword.Length, volumePim, FALSE, Silent, Silent))
+ if (!CheckPasswordLength (NULL, volumePassword.Length, volumePim, FALSE, 0, Silent, Silent))
{
exit (1);
}
@@ -7514,7 +7514,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
return 1;
}
// Check password length (check also done for outer volume which is not the case in TrueCrypt).
- else if (!CheckPasswordLength (hwndDlg, volumePassword.Length, 0, SysEncInEffect(), FALSE, FALSE))
+ else if (!CheckPasswordLength (hwndDlg, volumePassword.Length, 0, SysEncInEffect(), SysEncInEffect()? hash_algo : 0, FALSE, FALSE))
{
return 1;
}
@@ -7601,7 +7601,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
return 1;
}
// Check password length (check also done for outer volume which is not the case in TrueCrypt).
- else if (!CheckPasswordLength (hwndDlg, volumePassword.Length, volumePim, SysEncInEffect(), TRUE, FALSE))
+ else if (!CheckPasswordLength (hwndDlg, volumePassword.Length, volumePim, SysEncInEffect(), SysEncInEffect()? hash_algo : 0, TRUE, FALSE))
{
return 1;
}
diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c
index b0439ea5..6a4a57a7 100644
--- a/src/Mount/Mount.c
+++ b/src/Mount/Mount.c
@@ -2672,7 +2672,19 @@ BOOL CALLBACK PasswordChangeDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPAR
else if (!(newKeyFilesParam.EnableKeyFiles && newKeyFilesParam.FirstKeyFile != NULL)
&& pwdChangeDlgMode == PCDM_CHANGE_PASSWORD)
{
- if (!CheckPasswordLength (hwndDlg, GetWindowTextLength(GetDlgItem (hwndDlg, IDC_PASSWORD)), pim, bSysEncPwdChangeDlgMode, FALSE, FALSE))
+ int bootPRF = 0;
+ if (bSysEncPwdChangeDlgMode)
+ {
+ try
+ {
+ VOLUME_PROPERTIES_STRUCT properties;
+ BootEncObj->GetVolumeProperties(&properties);
+ bootPRF = properties.pkcs5;
+ }
+ catch(...)
+ {}
+ }
+ if (!CheckPasswordLength (hwndDlg, GetWindowTextLength(GetDlgItem (hwndDlg, IDC_PASSWORD)), pim, bSysEncPwdChangeDlgMode, bootPRF, FALSE, FALSE))
return 1;
}