Unix: process protection keyfiles before cached mounts

Apply protection keyfiles once in the application, including cached-password
mounts. This keeps PC/SC out of the core service before FUSE forks.

Preserve protection errors and cache retries, and ignore protection
credentials when protection is disabled.
This commit is contained in:
Mounir IDRASSI
2026-09-25 09:36:30 +02:00
parent 55920deffb
commit ab9d636e52
+70 -49
View File
@@ -91,65 +91,86 @@ namespace VeraCrypt
virtual shared_ptr <VolumeInfo> MountVolume (MountOptions &options)
{
shared_ptr <VolumeInfo> mountedVolume;
if (!VolumePasswordCache::IsEmpty()
const bool useCachedPasswords = !VolumePasswordCache::IsEmpty()
&& (!options.Password || options.Password->IsEmpty())
&& (!options.Keyfiles || options.Keyfiles->empty()))
{
finally_do_arg (MountOptions*, &options, { if (finally_arg->Password) finally_arg->Password.reset(); });
PasswordIncorrect passwordException;
foreach (shared_ptr <VolumePassword> password, VolumePasswordCache::GetPasswords())
{
try
{
options.Password = password;
mountedVolume = CoreService::RequestMountVolume (options);
break;
}
catch (PasswordIncorrect &e)
{
passwordException = e;
}
}
if (!mountedVolume)
passwordException.Throw();
}
else
{
MountOptions newOptions = options;
&& (!options.Keyfiles || options.Keyfiles->empty());
MountOptions newOptions = options;
// Resolve keyfiles in the application process, also when the outer password
// is cached. Token access must not initialize PC/SC in the core service
// before it forks FUSE.
if (!useCachedPasswords)
newOptions.Password = Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVSupportEnabled);
if (newOptions.Keyfiles)
newOptions.Keyfiles->clear();
if (newOptions.Keyfiles)
newOptions.Keyfiles->clear();
if (options.Protection == VolumeProtection::HiddenVolumeReadOnly)
newOptions.ProtectionPassword = Keyfile::ApplyListToPassword (options.ProtectionKeyfiles, options.ProtectionPassword, options.EMVSupportEnabled);
if (newOptions.ProtectionKeyfiles)
newOptions.ProtectionKeyfiles->clear();
else
newOptions.ProtectionPassword.reset();
if (newOptions.ProtectionKeyfiles)
newOptions.ProtectionKeyfiles->clear();
try
try
{
if (useCachedPasswords)
{
finally_do_arg (MountOptions*, &options, { if (finally_arg->Password) finally_arg->Password.reset(); });
PasswordIncorrect passwordException;
foreach (shared_ptr <VolumePassword> password, VolumePasswordCache::GetPasswords())
{
try
{
newOptions.Password = password;
mountedVolume = CoreService::RequestMountVolume (newOptions);
break;
}
catch (ProtectionPasswordIncorrect&)
{
// The outer password was accepted; another cached password cannot
// correct the hidden-volume protection credentials.
throw;
}
catch (ProtectionPasswordKeyfilesIncorrect&)
{
throw;
}
catch (PasswordIncorrect &e)
{
passwordException = e;
}
}
if (!mountedVolume)
passwordException.Throw();
}
else
{
mountedVolume = CoreService::RequestMountVolume (newOptions);
}
catch (ProtectionPasswordIncorrect &e)
{
if (options.ProtectionKeyfiles && !options.ProtectionKeyfiles->empty())
throw ProtectionPasswordKeyfilesIncorrect (e.what());
throw;
}
catch (PasswordIncorrect &e)
{
if (options.Keyfiles && !options.Keyfiles->empty())
throw PasswordKeyfilesIncorrect (e.what());
throw;
}
}
catch (ProtectionPasswordIncorrect &e)
{
if (options.ProtectionKeyfiles && !options.ProtectionKeyfiles->empty())
throw ProtectionPasswordKeyfilesIncorrect (e.what());
throw;
}
catch (ProtectionPasswordKeyfilesIncorrect&)
{
throw;
}
catch (PasswordIncorrect &e)
{
if (options.Keyfiles && !options.Keyfiles->empty())
throw PasswordKeyfilesIncorrect (e.what());
throw;
}
if (options.CachePassword
&& ((options.Password && !options.Password->IsEmpty()) || (options.Keyfiles && !options.Keyfiles->empty())))
{
VolumePasswordCache::Store (*Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVSupportEnabled));
}
if (!useCachedPasswords && options.CachePassword
&& ((options.Password && !options.Password->IsEmpty()) || (options.Keyfiles && !options.Keyfiles->empty())))
{
VolumePasswordCache::Store (*Keyfile::ApplyListToPassword (options.Keyfiles, options.Password, options.EMVSupportEnabled));
}
VolumeEventArgs eventArgs (mountedVolume);