mirror of
https://github.com/veracrypt/VeraCrypt
synced 2024-11-24 03:53:29 +01:00
Crypto: Workaround for AES-NI issue under Hyper-V on Windows Server 2008 R2 which masks AES-NI from applications although it is available.
This commit is contained in:
parent
2dbf366184
commit
0fca588275
@ -21,6 +21,7 @@
|
|||||||
#include "EncryptionThreadPool.h"
|
#include "EncryptionThreadPool.h"
|
||||||
#endif
|
#endif
|
||||||
#include "Volumes.h"
|
#include "Volumes.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
/* Update the following when adding a new cipher or EA:
|
/* Update the following when adding a new cipher or EA:
|
||||||
|
|
||||||
@ -1051,7 +1052,11 @@ BOOL IsAesHwCpuSupported ()
|
|||||||
|
|
||||||
if (!stateValid)
|
if (!stateValid)
|
||||||
{
|
{
|
||||||
|
#ifdef TC_WINDOWS_BOOT_AES
|
||||||
state = is_aes_hw_cpu_supported() ? TRUE : FALSE;
|
state = is_aes_hw_cpu_supported() ? TRUE : FALSE;
|
||||||
|
#else
|
||||||
|
state = g_hasAESNI ? TRUE : FALSE;
|
||||||
|
#endif
|
||||||
stateValid = TRUE;
|
stateValid = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,20 +118,32 @@ static int TrySSE2()
|
|||||||
#if CRYPTOPP_BOOL_X64
|
#if CRYPTOPP_BOOL_X64
|
||||||
return 1;
|
return 1;
|
||||||
#elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
|
#elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
|
||||||
|
volatile int result = 1;
|
||||||
|
#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
|
||||||
|
KFLOATING_SAVE floatingPointState;
|
||||||
|
if (NT_SUCCESS (KeSaveFloatingPointState (&floatingPointState)))
|
||||||
|
{
|
||||||
|
#endif
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
|
||||||
AS2(por xmm0, xmm0) // executing SSE2 instruction
|
AS2(por xmm0, xmm0) // executing SSE2 instruction
|
||||||
#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
|
||||||
__m128i x = _mm_setzero_si128();
|
__m128i x = _mm_setzero_si128();
|
||||||
return _mm_cvtsi128_si32(x) == 0 ? 1 : 0;
|
result = _mm_cvtsi128_si32(x) == 0 ? 1 : 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
return 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
return 1;
|
#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
|
||||||
|
KeRestoreFloatingPointState (&floatingPointState);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
#else
|
#else
|
||||||
// longjmp and clobber warnings. Volatile is required.
|
// longjmp and clobber warnings. Volatile is required.
|
||||||
// http://github.com/weidai11/cryptopp/issues/24
|
// http://github.com/weidai11/cryptopp/issues/24
|
||||||
@ -198,6 +210,48 @@ void DetectX86Features()
|
|||||||
g_hasAESNI = g_hasSSE2 && (cpuid1[2] & (1<<25));
|
g_hasAESNI = g_hasSSE2 && (cpuid1[2] & (1<<25));
|
||||||
g_hasCLMUL = g_hasSSE2 && (cpuid1[2] & (1<<1));
|
g_hasCLMUL = g_hasSSE2 && (cpuid1[2] & (1<<1));
|
||||||
|
|
||||||
|
#if (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)))
|
||||||
|
{
|
||||||
|
// when Hyper-V is enabled on older versions of Windows Server (i.e. 2008 R2), the AES-NI capability
|
||||||
|
// gets masked out for all applications, even running on the host.
|
||||||
|
// We try to detect Hyper-V virtual CPU and perform a dummy AES-NI operation to check its real presence
|
||||||
|
uint32 cpuid2[4];
|
||||||
|
char HvProductName[13];
|
||||||
|
|
||||||
|
CpuId(0x40000000, cpuid2);
|
||||||
|
memcpy (HvProductName, &cpuid2[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
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
__m128i block, subkey, ciphered;
|
||||||
|
// perform AES round.
|
||||||
|
block = _mm_setr_epi32(0x11223344,0x55667788,0x99AABBCC,0xDDEEFF00);
|
||||||
|
subkey = _mm_setr_epi32(0xA5A5A5A5,0xA5A5A5A5,0x5A5A5A5A,0x5A5A5A5A);
|
||||||
|
ciphered = _mm_aesenc_si128(block, subkey);
|
||||||
|
g_hasAESNI = (ciphered.m128i_u64[0] == LL(0x2f4654b9485061fa) && ciphered.m128i_u64[1] == LL(0xc8b51f1fe1256f99));
|
||||||
|
}
|
||||||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
// ignore error if AES-NI not supported
|
||||||
|
}
|
||||||
|
#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
|
||||||
|
KeRestoreFloatingPointState (&floatingPointState);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((cpuid1[3] & (1 << 25)) != 0)
|
if ((cpuid1[3] & (1 << 25)) != 0)
|
||||||
g_hasISSE = 1;
|
g_hasISSE = 1;
|
||||||
else
|
else
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <string.h> // for memcpy and memmove
|
#include <string.h> // for memcpy and memmove
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <strings.h> // for strcasecmp
|
||||||
|
#define _stricmp strcasecmp
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#if _MSC_VER >= 1400
|
#if _MSC_VER >= 1400
|
||||||
|
Loading…
Reference in New Issue
Block a user