VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Crypto/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Crypto/cpu.c')
-rw-r--r--src/Crypto/cpu.c137
1 files changed, 116 insertions, 21 deletions
diff --git a/src/Crypto/cpu.c b/src/Crypto/cpu.c
index effde6ba..a5b5bb19 100644
--- a/src/Crypto/cpu.c
+++ b/src/Crypto/cpu.c
@@ -15,10 +15,14 @@
#include <setjmp.h>
#endif
#ifdef CRYPTOPP_CPUID_AVAILABLE
+#if defined(__GNUC__) || defined(__clang__)
+ #include <cpuid.h> // for __get_cpuid and __get_cpuid_count
+#endif
+
#if _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
int CpuId(uint32 input, uint32 output[4])
{
__cpuid((int *)output, input);
@@ -134,15 +138,10 @@ static int TrySSE2()
{
#if CRYPTOPP_BOOL_X64
return 1;
#elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) && !defined(_UEFI)
volatile int result = 1;
-#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
- KFLOATING_SAVE floatingPointState;
- if (NT_SUCCESS (KeSaveFloatingPointState (&floatingPointState)))
- {
-#endif
__try
{
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
AS2(por xmm0, xmm0) // executing SSE2 instruction
#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
@@ -152,16 +151,10 @@ static int TrySSE2()
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
result = 0;
}
-#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
- KeRestoreFloatingPointState (&floatingPointState);
- }
- else
- return 0;
-#endif
return result;
#elif !defined(_UEFI)
// longjmp and clobber warnings. Volatile is required.
// http://github.com/weidai11/cryptopp/issues/24
// http://stackoverflow.com/q/7721854
@@ -205,10 +198,11 @@ static uint64 xgetbv()
volatile int g_x86DetectionDone = 0;
volatile int g_hasISSE = 0, g_hasSSE2 = 0, g_hasSSSE3 = 0, g_hasMMX = 0, g_hasAESNI = 0, g_hasCLMUL = 0, g_isP4 = 0;
volatile int g_hasAVX = 0, g_hasAVX2 = 0, g_hasBMI2 = 0, g_hasSSE42 = 0, g_hasSSE41 = 0, g_isIntel = 0, g_isAMD = 0;
volatile int g_hasRDRAND = 0, g_hasRDSEED = 0;
+volatile int g_hasSHA256 = 0;
volatile uint32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
VC_INLINE int IsIntel(const uint32 output[4])
{
// This is the "GenuineIntel" string
@@ -286,28 +280,51 @@ static int Detect_MS_HyperV_AES ()
CpuId(0x40000000, cpuid);
memcpy (HvProductName, &cpuid[1], 12);
HvProductName[12] = 0;
if (_stricmp(HvProductName, "Microsoft Hv") == 0)
{
-#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
- KFLOATING_SAVE floatingPointState;
- if (NT_SUCCESS (KeSaveFloatingPointState (&floatingPointState)))
- {
-#endif
hasAesNI = TryAESNI ();
-
-#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
- KeRestoreFloatingPointState (&floatingPointState);
- }
-#endif
}
return hasAesNI;
}
#endif
+#if defined(__SHA__) || defined(__INTEL_COMPILER) || CRYPTOPP_SHANI_AVAILABLE
+extern int TrySHA256();
+#endif
+
+static BOOL CheckSHA256Support() {
+#if CRYPTOPP_BOOL_X64 && CRYPTOPP_SHANI_AVAILABLE
+#if defined(_MSC_VER) // Windows with MSVC
+ int cpuInfo[4] = { 0 };
+ __cpuidex(cpuInfo, 7, 0);
+ return (cpuInfo[1] & (1 << 29)) != 0? TRUE : FALSE;
+
+#elif defined(__GNUC__) || defined(__clang__) // Linux, FreeBSD, macOS with GCC/Clang
+ unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
+ // First check if CPUID leaf 7 is supported
+ if (__get_cpuid(0, &eax, &ebx, &ecx, &edx)) {
+ if (eax >= 7) {
+ // Now check SHA-256 support in leaf 7, sub-leaf 0
+ if (__get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx)) {
+ return (ebx & (1 << 29)) != 0? TRUE : FALSE;
+ }
+ }
+ }
+ return FALSE;
+
+#else
+ #error "Unsupported compiler"
+#endif
+#else
+ return FALSE;
+#endif
+}
+
+
void DetectX86Features()
{
uint32 cpuid[4] = {0}, cpuid1[4] = {0}, cpuid2[4] = {0};
if (!CpuId(0, cpuid))
return;
@@ -332,20 +349,28 @@ void DetectX86Features()
g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
#ifndef CRYPTOPP_DISABLE_AESNI
g_hasAESNI = g_hasSSE2 && (cpuid1[2] & (1<<25));
#endif
g_hasCLMUL = g_hasSSE2 && (cpuid1[2] & (1<<1));
+ g_hasSHA256 = CheckSHA256Support();
#if !defined (_UEFI) && ((defined(__AES__) && defined(__PCLMUL__)) || defined(__INTEL_COMPILER) || CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE)
// Hypervisor = bit 31 of ECX of CPUID leaf 0x1
// reference: http://artemonsecurity.com/vmde.pdf
if (!g_hasAESNI && (cpuid1[2] & (1<<31)))
{
g_hasAESNI = Detect_MS_HyperV_AES ();
}
#endif
+#if defined(__SHA__) || defined(__INTEL_COMPILER) || CRYPTOPP_SHANI_AVAILABLE
+ if (!g_hasSHA256)
+ {
+ g_hasSHA256 = TrySHA256();
+ }
+#endif
+
if ((cpuid1[3] & (1 << 25)) != 0)
g_hasISSE = 1;
else
{
CpuId(0x080000000, cpuid2);
@@ -437,9 +462,79 @@ void DisableCPUExtendedFeatures ()
g_hasSSE42 = 0;
g_hasSSE41 = 0;
g_hasSSSE3 = 0;
g_hasAESNI = 0;
g_hasCLMUL = 0;
+ g_hasSHA256 = 0;
+}
+
+#endif
+
+#if CRYPTOPP_BOOL_ARMV8
+#if defined(__linux__) && defined(__aarch64__)
+#include <sys/auxv.h>
+#ifndef HWCAP_AES
+# define HWCAP_AES (1 << 3)
+#endif
+#ifndef HWCAP_SHA2
+# define HWCAP_SHA2 (1 << 6)
+#endif
+#endif
+
+volatile int g_hasAESARM = 0;
+volatile int g_hasSHA256ARM = 0;
+
+inline int CPU_QueryAES()
+{
+#if defined(CRYPTOPP_ARM_AES_AVAILABLE)
+#if defined(__linux__) && defined(__aarch64__)
+ if ((getauxval(AT_HWCAP) & HWCAP_AES) != 0)
+ return 1;
+#elif defined(__APPLE__) && defined(__aarch64__)
+ // Apple Sillcon (M1) and later
+ return 1;
+#elif defined(_WIN32) && defined(_M_ARM64)
+#ifdef TC_WINDOWS_DRIVER
+ if (ExIsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
+ return 1;
+#else
+ if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
+ return 1;
+#endif
+#endif
+ return 0;
+#else
+ return 0;
+#endif
}
+inline int CPU_QuerySHA2()
+{
+#if defined(CRYPTOPP_ARM_SHA2_AVAILABLE)
+#if defined(__linux__) && defined(__aarch64__)
+ if ((getauxval(AT_HWCAP) & HWCAP_SHA2) != 0)
+ return 1;
+#elif defined(__APPLE__) && defined(__aarch64__)
+ // Apple Sillcon (M1) and later
+ return 1;
+#elif defined(_WIN32) && defined(_M_ARM64)
+#ifdef TC_WINDOWS_DRIVER
+ if (ExIsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
+ return 1;
+#else
+ if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
+ return 1;
+#endif
+#endif
+ return 0;
+#else
+ return 0;
#endif
+}
+
+void DetectArmFeatures()
+{
+ g_hasAESARM = CPU_QueryAES();
+ g_hasSHA256ARM = CPU_QuerySHA2();
+}
+#endif \ No newline at end of file