VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMounir IDRASSI <mounir.idrassi@idrix.fr>2016-07-29 15:50:30 +0200
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2016-07-29 22:40:44 +0200
commitfe31cf5b83383cbc02f5bc31411367c0128f2df6 (patch)
treeb43bf3351bf30671973ae39b7dc756568168e947 /src
parent2389561406cb9e498008f884bed36e6e9d78ea80 (diff)
downloadVeraCrypt-fe31cf5b83383cbc02f5bc31411367c0128f2df6.tar.gz
VeraCrypt-fe31cf5b83383cbc02f5bc31411367c0128f2df6.zip
Crypto: Use Hyper-V AES-NI detection workaround when displaying AES hardware availability in GUI.
Diffstat (limited to 'src')
-rw-r--r--src/Common/Dlgcode.c5
-rw-r--r--src/Crypto/Aes_hw_cpu.asm25
-rw-r--r--src/Crypto/cpu.c99
-rw-r--r--src/Volume/Cipher.cpp3
4 files changed, 84 insertions, 48 deletions
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index c9955714..1ecc3c0a 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -5517,12 +5517,13 @@ BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP
uint32 driverConfig = ReadDriverConfigurationFlags();
+ int isAesHwSupported = is_aes_hw_cpu_supported();
- SetDlgItemTextW (hwndDlg, IDC_HW_AES, (wstring (L" ") + (GetString (is_aes_hw_cpu_supported() ? ((driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION) ? "UISTR_DISABLED" : "UISTR_YES") : "NOT_APPLICABLE_OR_NOT_AVAILABLE"))).c_str());
+ SetDlgItemTextW (hwndDlg, IDC_HW_AES, (wstring (L" ") + (GetString (isAesHwSupported ? ((driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION) ? "UISTR_DISABLED" : "UISTR_YES") : "NOT_APPLICABLE_OR_NOT_AVAILABLE"))).c_str());
ToHyperlink (hwndDlg, IDC_HW_AES_LABEL_LINK);
- if (is_aes_hw_cpu_supported() && (driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION))
+ if (isAesHwSupported && (driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION))
{
Warning ("DISABLED_HW_AES_AFFECTS_PERFORMANCE", hwndDlg);
}
diff --git a/src/Crypto/Aes_hw_cpu.asm b/src/Crypto/Aes_hw_cpu.asm
index faaba4f3..edc20b29 100644
--- a/src/Crypto/Aes_hw_cpu.asm
+++ b/src/Crypto/Aes_hw_cpu.asm
@@ -286,17 +286,20 @@
; byte is_aes_hw_cpu_supported ();
- export_function is_aes_hw_cpu_supported
- push %[R]bx
-
- mov eax, 1
- cpuid
- mov eax, ecx
- shr eax, 25
- and eax, 1
-
- pop %[R]bx
- ret
+; We comment this since we have an alternative C implementation
+; that supports Hyper-V detection workaround
+;
+; export_function is_aes_hw_cpu_supported
+; push %[R]bx
+;
+; mov eax, 1
+; cpuid
+; mov eax, ecx
+; shr eax, 25
+; and eax, 1
+;
+; pop %[R]bx
+; ret
; void aes_hw_cpu_decrypt (const byte *ks, byte *data);
diff --git a/src/Crypto/cpu.c b/src/Crypto/cpu.c
index 53e5e686..5743e6fc 100644
--- a/src/Crypto/cpu.c
+++ b/src/Crypto/cpu.c
@@ -192,6 +192,47 @@ VC_INLINE int IsAMD(const uint32 output[4])
(output[3] /*EDX*/ == 0x444D4163);
}
+static int Detect_MS_HyperV_AES ()
+{
+ int hasAesNI = 0;
+ // 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 cpuid[4];
+ char HvProductName[13];
+
+ 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
+ __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);
+ 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
+ }
+
+ return hasAesNI;
+}
+
void DetectX86Features()
{
uint32 cpuid[4], cpuid1[4];
@@ -215,40 +256,7 @@ void DetectX86Features()
// 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
- }
+ g_hasAESNI = Detect_MS_HyperV_AES ();
}
#endif
@@ -282,4 +290,27 @@ void DetectX86Features()
*((volatile int*)&g_x86DetectionDone) = 1;
}
+int is_aes_hw_cpu_supported ()
+{
+ int bHasAESNI = 0;
+ uint32 cpuid[4];
+
+ if (CpuId(1, cpuid))
+ {
+ if (cpuid[2] & (1<<25))
+ bHasAESNI = 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 (!bHasAESNI && (cpuid[2] & (1<<31)))
+ {
+ bHasAESNI = Detect_MS_HyperV_AES ();
+ }
+#endif
+ }
+
+ return bHasAESNI;
+}
+
#endif
+
diff --git a/src/Volume/Cipher.cpp b/src/Volume/Cipher.cpp
index 743ef34c..a90b3c46 100644
--- a/src/Volume/Cipher.cpp
+++ b/src/Volume/Cipher.cpp
@@ -19,6 +19,7 @@
#ifdef TC_AES_HW_CPU
# include "Crypto/Aes_hw_cpu.h"
+# include "Crypto/cpu.h"
#endif
namespace VeraCrypt
@@ -181,7 +182,7 @@ namespace VeraCrypt
if (!stateValid)
{
- state = is_aes_hw_cpu_supported() ? true : false;
+ state = g_hasAESNI ? true : false;
stateValid = true;
}
return state && HwSupportEnabled;