Linux/macOS: Implement missing Argon2 KDF support on Unix

This commit is contained in:
Mounir IDRASSI
2026-04-19 17:52:44 +09:00
parent e07bd19f20
commit e59eb421fb
81 changed files with 848 additions and 226 deletions
+139 -7
View File
@@ -21,9 +21,47 @@
#endif
#include "EncryptionTest.h"
#include "Pkcs5Kdf.h"
#include "VolumeHeader.h"
namespace VeraCrypt
{
#if !defined (WOLFCRYPT_BACKEND) && !defined (VC_DCS_DISABLE_ARGON2)
class FailingArgon2Kdf : public Pkcs5Kdf
{
public:
FailingArgon2Kdf () : Pkcs5Kdf() { }
virtual ~FailingArgon2Kdf () { }
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, int pim, const ConstBufferPtr &salt) const
{
(void) key;
(void) password;
(void) pim;
(void) salt;
return 1;
}
virtual int DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
{
(void) key;
(void) password;
(void) salt;
(void) iterationCount;
return 1;
}
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Blake2b); }
virtual int GetIterationCount (int pim) const { return 1; }
virtual wstring GetName () const { return L"Argon2"; }
virtual Pkcs5Kdf* Clone () const { return new FailingArgon2Kdf(); }
virtual bool IsArgon2 () const { return true; }
private:
FailingArgon2Kdf (const FailingArgon2Kdf &);
FailingArgon2Kdf &operator= (const FailingArgon2Kdf &);
};
#endif
void EncryptionTest::TestAll ()
{
TestAll (false);
@@ -1127,37 +1165,131 @@ namespace VeraCrypt
#ifndef WOLFCRYPT_BACKEND
Pkcs5HmacBlake2s pkcs5HmacBlake2s;
pkcs5HmacBlake2s.DeriveKey (derivedKey, password, salt, 5);
if (pkcs5HmacBlake2s.DeriveKey (derivedKey, password, salt, 5) != 0)
throw TestFailed (SRC_POS);
if (memcmp (derivedKey.Ptr(), "\x8d\x51\xfa\x31", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacSha512 pkcs5HmacSha512;
pkcs5HmacSha512.DeriveKey (derivedKey, password, salt, 5);
if (pkcs5HmacSha512.DeriveKey (derivedKey, password, salt, 5) != 0)
throw TestFailed (SRC_POS);
if (memcmp (derivedKey.Ptr(), "\x13\x64\xae\xf8", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacWhirlpool pkcs5HmacWhirlpool;
pkcs5HmacWhirlpool.DeriveKey (derivedKey, password, salt, 5);
if (pkcs5HmacWhirlpool.DeriveKey (derivedKey, password, salt, 5) != 0)
throw TestFailed (SRC_POS);
if (memcmp (derivedKey.Ptr(), "\x50\x7c\x36\x6f", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacSha256 pkcs5HmacSha256;
pkcs5HmacSha256.DeriveKey (derivedKey, password, salt, 5);
if (pkcs5HmacSha256.DeriveKey (derivedKey, password, salt, 5) != 0)
throw TestFailed (SRC_POS);
if (memcmp (derivedKey.Ptr(), "\xf2\xa0\x4f\xb2", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacStreebog pkcs5HmacStreebog;
pkcs5HmacStreebog.DeriveKey (derivedKey, password, salt, 5);
if (pkcs5HmacStreebog.DeriveKey (derivedKey, password, salt, 5) != 0)
throw TestFailed (SRC_POS);
if (memcmp (derivedKey.Ptr(), "\xd0\x53\xa2\x30", 4) != 0)
throw TestFailed (SRC_POS);
#ifndef VC_DCS_DISABLE_ARGON2
Pkcs5Argon2 pkcs5Argon2;
static const uint8 argon2SaltData[] = { 's', 'o', 'm', 'e', 's', 'a', 'l', 't' };
static const uint8 argon2Pim1DerivedKey[] =
{
0x9e, 0x87, 0x89, 0xc8, 0xb4, 0x28, 0x34, 0x22,
0x0a, 0xfc, 0x00, 0x08, 0x5a, 0xc7, 0x3a, 0xcc,
0x30, 0x86, 0x51, 0x21, 0x69, 0x94, 0xab, 0xbf,
0xdd, 0xd6, 0x9b, 0x25, 0x92, 0x03, 0x2e, 0xfd
};
ConstBufferPtr argon2Salt (argon2SaltData, sizeof (argon2SaltData));
Buffer argon2DerivedKey (sizeof (argon2Pim1DerivedKey));
// PIM 1 maps to Argon2id t=3, m=64 MiB, p=1.
if (pkcs5Argon2.DeriveKey (argon2DerivedKey, password, 1, argon2Salt) != 0)
throw TestFailed (SRC_POS);
if (memcmp (argon2DerivedKey.Ptr(), argon2Pim1DerivedKey, sizeof (argon2Pim1DerivedKey)) != 0)
throw TestFailed (SRC_POS);
try
{
if (pkcs5Argon2.DeriveKey (derivedKey, password, salt, 5) != 0)
throw TestFailed (SRC_POS);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect&)
{
}
shared_ptr <Pkcs5Kdf> sha512Kdf (new Pkcs5HmacSha512);
shared_ptr <Pkcs5Kdf> failingArgon2Kdf (new FailingArgon2Kdf);
shared_ptr <EncryptionAlgorithm> ea (new AES);
SecureBuffer headerBuffer (TC_VOLUME_HEADER_SIZE);
SecureBuffer dataKey (ea->GetKeySize() * 2);
SecureBuffer headerSalt (VolumeHeader::GetSaltSize());
SecureBuffer headerKey (VolumeHeader::GetLargestSerializedKeySize());
for (size_t i = 0; i < dataKey.Size(); ++i)
dataKey.Ptr()[i] = (uint8) (i + 1);
for (size_t i = 0; i < headerSalt.Size(); ++i)
headerSalt.Ptr()[i] = (uint8) (i + 2);
if (sha512Kdf->DeriveKey (headerKey, password, 1, headerSalt) != 0)
throw TestFailed (SRC_POS);
VolumeHeaderCreationOptions options;
options.DataKey = dataKey;
options.EA = ea;
options.Kdf = sha512Kdf;
options.HeaderKey = headerKey;
options.Salt = headerSalt;
options.SectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME;
options.VolumeDataStart = TC_VOLUME_HEADER_GROUP_SIZE;
options.VolumeDataSize = TC_MIN_VOLUME_SIZE;
options.Type = VolumeType::Normal;
VolumeHeader header (TC_VOLUME_HEADER_SIZE);
header.Create (headerBuffer, options);
Pkcs5KdfList kdfs;
kdfs.push_back (failingArgon2Kdf);
kdfs.push_back (sha512Kdf);
EncryptionAlgorithmList encryptionAlgorithms;
encryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AES));
EncryptionModeList encryptionModes;
encryptionModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS));
VolumeHeader decryptedHeader (TC_VOLUME_HEADER_SIZE);
if (!decryptedHeader.Decrypt (headerBuffer, password, 1, shared_ptr <Pkcs5Kdf> (), kdfs, encryptionAlgorithms, encryptionModes)
|| decryptedHeader.GetPkcs5Kdf()->GetName() != sha512Kdf->GetName())
{
throw TestFailed (SRC_POS);
}
try
{
decryptedHeader.Decrypt (headerBuffer, password, 1, failingArgon2Kdf, kdfs, encryptionAlgorithms, encryptionModes);
throw TestFailed (SRC_POS);
}
catch (ExternalException&)
{
}
#endif
#else
Pkcs5HmacSha256 pkcs5HmacSha256;
pkcs5HmacSha256.DeriveKey (derivedKey, password, salt, 5);
if (pkcs5HmacSha256.DeriveKey (derivedKey, password, salt, 5) != 0)
throw TestFailed (SRC_POS);
if (memcmp (derivedKey.Ptr(), "\x64\xf3\xa5\xa3", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacSha512 pkcs5HmacSha512;
pkcs5HmacSha512.DeriveKey (derivedKey, password, salt, 5);
if (pkcs5HmacSha512.DeriveKey (derivedKey, password, salt, 5) != 0)
throw TestFailed (SRC_POS);
if (memcmp (derivedKey.Ptr(), "\x55\xa1\x76\xbb", 4) != 0)
throw TestFailed (SRC_POS);
#endif