VeraCrypt
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMounir IDRASSI <mounir.idrassi@idrix.fr>2019-01-31 00:00:54 (GMT)
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2019-01-31 23:35:42 (GMT)
commit915855f43b6bd30c2e01a49e261f813ccc7a0237 (patch)
tree255a25220917f4fabdb3b8a02011a0a06e8dccda
parent3c18d54d1e3f10462ccdb2d44f220db1ee021477 (diff)
downloadVeraCrypt-915855f43b6bd30c2e01a49e261f813ccc7a0237.zip
VeraCrypt-915855f43b6bd30c2e01a49e261f813ccc7a0237.tar.gz
Fix detection of CPU features AVX2 & BMI2. Add detection of RDRAND & RDSEED CPU features. Detect Hygon CPU as AMD one.
-rw-r--r--src/Crypto/cpu.c40
-rw-r--r--src/Crypto/cpu.h4
2 files changed, 41 insertions, 3 deletions
diff --git a/src/Crypto/cpu.c b/src/Crypto/cpu.c
index 69a7fcf..b831696 100644
--- a/src/Crypto/cpu.c
+++ b/src/Crypto/cpu.c
@@ -203,6 +203,7 @@ 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 uint32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
VC_INLINE int IsIntel(const uint32 output[4])
@@ -221,6 +222,14 @@ VC_INLINE int IsAMD(const uint32 output[4])
(output[3] /*EDX*/ == 0x444D4163);
}
+VC_INLINE int IsHygon(const uint32 output[4])
+{
+ // This is the "HygonGenuine" string.
+ return (output[1] /*EBX*/ == 0x6f677948) &&
+ (output[2] /*ECX*/ == 0x656e6975) &&
+ (output[3] /*EDX*/ == 0x6e65476e);
+}
+
#if !defined (_UEFI) && ((defined(__AES__) && defined(__PCLMUL__)) || defined(__INTEL_COMPILER) || CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE)
static int TryAESNI ()
@@ -296,15 +305,18 @@ static int Detect_MS_HyperV_AES ()
void DetectX86Features()
{
- uint32 cpuid[4] = {0}, cpuid1[4] = {0};
+ uint32 cpuid[4] = {0}, cpuid1[4] = {0}, cpuid2[4] = {0};
if (!CpuId(0, cpuid))
return;
if (!CpuId(1, cpuid1))
return;
g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
+
+ // cpuid1[2] & (1 << 27) is XSAVE/XRESTORE and signals OS support for SSE; use it to avoid probes.
+ // See http://github.com/weidai11/cryptopp/issues/511 and http://stackoverflow.com/a/22521619/608639
if ((cpuid1[3] & (1 << 26)) != 0)
- g_hasSSE2 = TrySSE2();
+ g_hasSSE2 = (cpuid1[2] & (1 << 27)) || TrySSE2();
if (g_hasSSE2 && (cpuid1[2] & (1 << 28)) && (cpuid1[2] & (1 << 27)) && (cpuid1[2] & (1 << 26))) /* CPU has AVX and OS supports XSAVE/XRSTORE */
{
uint64 xcrFeatureMask = xgetbv();
@@ -345,12 +357,34 @@ void DetectX86Features()
g_isIntel = 1;
g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
+ g_hasRDRAND = (cpuid1[2] & (1 << 30)) != 0;
+
+ if (cpuid[0] >= 7)
+ {
+ if (CpuId(7, cpuid2))
+ {
+ g_hasRDSEED = (cpuid2[1] & (1 << 18)) != 0;
+ g_hasAVX2 = (cpuid2[1] & (1 << 5)) != 0;
+ g_hasBMI2 = (cpuid2[1] & (1 << 8)) != 0;
+ }
+ }
}
- else if (IsAMD(cpuid))
+ else if (IsAMD(cpuid) || IsHygon(cpuid))
{
g_isAMD = 1;
CpuId(0x80000005, cpuid);
g_cacheLineSize = GETBYTE(cpuid[2], 0);
+ g_hasRDRAND = (cpuid1[2] & (1 << 30)) != 0;
+
+ if (cpuid[0] >= 7)
+ {
+ if (CpuId(7, cpuid2))
+ {
+ g_hasRDSEED = (cpuid2[1] & (1 << 18)) != 0;
+ g_hasAVX2 = (cpuid2[1] & (1 << 5)) != 0;
+ g_hasBMI2 = (cpuid2[1] & (1 << 8)) != 0;
+ }
+ }
}
if (!g_cacheLineSize)
diff --git a/src/Crypto/cpu.h b/src/Crypto/cpu.h
index 8856a3e..4dd5d88 100644
--- a/src/Crypto/cpu.h
+++ b/src/Crypto/cpu.h
@@ -199,6 +199,8 @@ extern volatile int g_hasSSSE3;
extern volatile int g_hasAESNI;
extern volatile int g_hasCLMUL;
extern volatile int g_isP4;
+extern volatile int g_hasRDRAND;
+extern volatile int g_hasRDSEED;
extern volatile int g_isIntel;
extern volatile int g_isAMD;
extern volatile uint32 g_cacheLineSize;
@@ -225,6 +227,8 @@ void DisableCPUExtendedFeatures ();
#define HasAESNI() g_hasAESNI
#define HasCLMUL() g_hasCLMUL
#define IsP4() g_isP4
+#define HasRDRAND() g_hasRDRAND
+#define HasRDSEED() g_hasRDSEED
#define IsCpuIntel() g_isIntel
#define IsCpuAMD() g_isAMD
#define GetCacheLineSize() g_cacheLineSize