From 71e6add60cc1212d52591690fbf9d6dbff18ab82 Mon Sep 17 00:00:00 2001 From: Bernard Ladenthin Date: Sat, 1 Aug 2026 18:23:49 +0200 Subject: [PATCH] Tests: verify that CRYPTOPP_ALIGN_DATA delivers the requested alignment The macro expands to nothing for compilers that are neither MSVC nor GCC/Clang, and the SIMD backends issue aligned loads against buffers declared with it, so a silent expansion to nothing would fault at run time. Nothing verified this so far. Add TC_IS_ALIGNED next to the existing alignment constants and check both of them from the platform self-test suites. The probe buffers stay below the alignment under test because the ABI already aligns larger objects by itself, which would make the check pass vacuously. The check is skipped in the Windows driver: a failing self-test there reaches TC_BUG_CHECK and would bugcheck the machine. --- src/Common/Tests.c | 30 ++++++++++++++++++++++++++++++ src/Common/Volumes.h | 3 +++ src/Volume/EncryptionTest.cpp | 20 ++++++++++++++++++++ src/Volume/EncryptionTest.h | 1 + 4 files changed, 54 insertions(+) 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 ();