diff --git a/src/Common/Tests.c b/src/Common/Tests.c index dc5798d15c..eaf13f8ebc 100644 --- a/src/Common/Tests.c +++ b/src/Common/Tests.c @@ -20,6 +20,7 @@ #include #include "Pkcs5.h" #include "cpu.h" +#include "Volumes.h" typedef struct { CRYPTOPP_ALIGN_DATA(16) unsigned __int8 key1[32]; @@ -1280,6 +1281,28 @@ BOOL TestSectorBufEncryption (PCRYPTO_INFO ci) return (nTestsPerformed == 150); } +#ifndef TC_WINDOWS_DRIVER +// Must stay smaller than the alignment under test: the ABI aligns larger objects by itself. +#define TC_ALIGNMENT_PROBE_SIZE 4 + +/* Verifies that CRYPTOPP_ALIGN_DATA actually delivers the alignment it requests. It expands + to nothing for compilers that are neither MSVC nor GCC/Clang (see Crypto/config.h), and the + SIMD backends issue aligned loads against buffers declared with it. */ +static BOOL TestBufferAlignment (void) +{ + static CRYPTOPP_ALIGN_DATA(TC_DERIVED_KEY_BUFFER_ALIGNMENT) unsigned char derivedKeyProbe[TC_ALIGNMENT_PROBE_SIZE]; + static CRYPTOPP_ALIGN_DATA(TC_KEY_INFO_BUFFER_ALIGNMENT) unsigned char keyInfoProbe[TC_ALIGNMENT_PROBE_SIZE]; + + if (!TC_IS_ALIGNED (derivedKeyProbe, TC_DERIVED_KEY_BUFFER_ALIGNMENT)) + return FALSE; + + if (!TC_IS_ALIGNED (keyInfoProbe, TC_KEY_INFO_BUFFER_ALIGNMENT)) + return FALSE; + + return TRUE; +} +#endif + static BOOL DoAutoTestAlgorithms (void) { PCRYPTO_INFO ci; @@ -1489,6 +1512,13 @@ static BOOL DoAutoTestAlgorithms (void) bFailed = TRUE; crypto_close (ci); + +#ifndef TC_WINDOWS_DRIVER + /* Not run in the driver: a failing self-test there reaches TC_BUG_CHECK and would bugcheck the machine. */ + if (!TestBufferAlignment ()) + bFailed = TRUE; +#endif + return !bFailed; } diff --git a/src/Common/Volumes.h b/src/Common/Volumes.h index bf6428187b..ca8946dd84 100644 --- a/src/Common/Volumes.h +++ b/src/Common/Volumes.h @@ -41,6 +41,9 @@ extern "C" { // Required 16-byte alignment for KEY_INFO buffer to ensure optimal performance and compatibility with SIMD instructions. #define TC_KEY_INFO_BUFFER_ALIGNMENT 16 +// TRUE if the address meets the given alignment. +#define TC_IS_ALIGNED(address, alignment) ((((uint64) (address)) % (alignment)) == 0) + // Current volume format version (created by TrueCrypt 6.0+) #define TC_VOLUME_FORMAT_VERSION 2 diff --git a/src/Volume/EncryptionTest.cpp b/src/Volume/EncryptionTest.cpp index 721f91430d..a78def3434 100644 --- a/src/Volume/EncryptionTest.cpp +++ b/src/Volume/EncryptionTest.cpp @@ -70,10 +70,30 @@ namespace VeraCrypt void EncryptionTest::TestAll () { + TestAlignment(); TestAll (false); TestAll (true); } + // Must stay smaller than the alignment under test: the ABI aligns larger objects by itself. + #define TC_ALIGNMENT_PROBE_SIZE 4 + + // Verifies that CRYPTOPP_ALIGN_DATA actually delivers the alignment it requests. + // It expands to nothing for compilers that are neither MSVC nor GCC/Clang (see + // Crypto/config.h), and the SIMD backends issue aligned loads against buffers + // declared with it, so a silent expansion to nothing would fault at run time. + void EncryptionTest::TestAlignment () + { + static CRYPTOPP_ALIGN_DATA(TC_DERIVED_KEY_BUFFER_ALIGNMENT) uint8 derivedKeyProbe[TC_ALIGNMENT_PROBE_SIZE]; + static CRYPTOPP_ALIGN_DATA(TC_KEY_INFO_BUFFER_ALIGNMENT) uint8 keyInfoProbe[TC_ALIGNMENT_PROBE_SIZE]; + + if (!TC_IS_ALIGNED (derivedKeyProbe, TC_DERIVED_KEY_BUFFER_ALIGNMENT)) + throw TestFailed (SRC_POS); + + if (!TC_IS_ALIGNED (keyInfoProbe, TC_KEY_INFO_BUFFER_ALIGNMENT)) + throw TestFailed (SRC_POS); + } + void EncryptionTest::TestAll (bool enableCpuEncryptionSupport) { bool hwSupportEnabled = Cipher::IsHwSupportEnabled(); diff --git a/src/Volume/EncryptionTest.h b/src/Volume/EncryptionTest.h index ed6a9cdc89..69211a0325 100644 --- a/src/Volume/EncryptionTest.h +++ b/src/Volume/EncryptionTest.h @@ -25,6 +25,7 @@ namespace VeraCrypt static void TestAll (bool enableCpuEncryptionSupport); protected: + static void TestAlignment (); static void TestCiphers (); static void TestLegacyModes (); static void TestPkcs5 ();