From 3fb2eedab8ef586cd2686efba0b668a5070fd0af Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 7 Aug 2016 23:45:34 +0200 Subject: Linux: Enable gcc AES-NI built-in functions and adapt Hyper-V AES detection code to gcc. --- src/Crypto/cpu.c | 64 ++++++++++++++++++++++++++++++++++++++++++++------------ src/Makefile | 6 ++++++ 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/Crypto/cpu.c b/src/Crypto/cpu.c index 5743e6fc..21c6c194 100644 --- a/src/Crypto/cpu.c +++ b/src/Crypto/cpu.c @@ -38,6 +38,12 @@ static void SigIllHandlerCPUID(int p) longjmp(s_jmpNoCPUID, 1); } +static jmp_buf s_jmpNoAESNI; +static void SigIllHandlerAESNI(int p) +{ + longjmp(s_jmpNoAESNI, 1); +} + #if CRYPTOPP_BOOL_X64 == 0 static jmp_buf s_jmpNoSSE2; static void SigIllHandlerSSE2(int p) @@ -192,6 +198,47 @@ VC_INLINE int IsAMD(const uint32 output[4]) (output[3] /*EDX*/ == 0x444D4163); } +#if (defined(__AES__) && defined(__PCLMUL__)) || defined(__INTEL_COMPILER) || CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE + +static int TryAESNI () +{ + volatile int result = 0; +#ifdef _MSC_VER + __try +#else + SigHandler oldHandler = signal(SIGILL, SigIllHandlerAESNI); + if (oldHandler == SIG_ERR) + return 0; + + if (setjmp(s_jmpNoAESNI)) + result = 0; + else +#endif + { + __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); +#ifdef _MSC_VER + if (ciphered.m128i_u64[0] == LL(0x2f4654b9485061fa) && ciphered.m128i_u64[1] == LL(0xc8b51f1fe1256f99)) +#else + if (((uint64_t*)(&ciphered))[0] == LL(0x2f4654b9485061fa) && ((uint64_t*)(&ciphered))[1] == LL(0xc8b51f1fe1256f99)) +#endif + result = 1; + } +#ifdef _MSC_VER + __except (EXCEPTION_EXECUTE_HANDLER) + { + // ignore error if AES-NI not supported + } +#else + signal(SIGILL, oldHandler); +#endif + + return result; +} + static int Detect_MS_HyperV_AES () { int hasAesNI = 0; @@ -211,19 +258,8 @@ static int Detect_MS_HyperV_AES () 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 - } + hasAesNI = TryAESNI (); + #if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64) KeRestoreFloatingPointState (&floatingPointState); } @@ -233,6 +269,8 @@ static int Detect_MS_HyperV_AES () return hasAesNI; } +#endif + void DetectX86Features() { uint32 cpuid[4], cpuid1[4]; diff --git a/src/Makefile b/src/Makefile index 70fb26da..4f0a6559 100644 --- a/src/Makefile +++ b/src/Makefile @@ -160,6 +160,12 @@ ifeq "$(shell uname -s)" "Linux" PLATFORM := Linux C_CXX_FLAGS += -DTC_UNIX -DTC_LINUX + + GCC_GTEQ_440 := $(shell expr `gcc -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= 40400) + ifeq "$(GCC_GTEQ_440)" "1" + CFLAGS += -maes + CXXFLAGS += -maes + endif ifeq "$(TC_BUILD_CONFIG)" "Release" C_CXX_FLAGS += -fdata-sections -ffunction-sections -- cgit v1.2.3