diff --git a/cpu.cpp b/cpu.cpp
index 1ee18a8e..be34be96 100644
--- a/cpu.cpp
+++ b/cpu.cpp
@@ -94,8 +94,7 @@ bool CpuId(word32 input, word32 output[4])
return true;
#else
// longjmp and clobber warnings. Volatile is required.
- // http://github.com/weidai11/cryptopp/issues/24
- // http://stackoverflow.com/q/7721854
+ // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
volatile bool result = true;
SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
@@ -149,8 +148,7 @@ static bool TrySSE2()
return true;
#else
// longjmp and clobber warnings. Volatile is required.
- // http://github.com/weidai11/cryptopp/issues/24
- // http://stackoverflow.com/q/7721854
+ // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
volatile bool result = true;
SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
@@ -262,7 +260,7 @@ void DetectX86Features()
#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)
bool g_ArmDetectionDone = false;
-bool g_hasNEON = false, g_hasCRC32 = false, g_hasCrypto = false;
+bool g_hasNEON = false, g_hasCRC32 = false, g_hasAES = false, g_hasSHA1 = false, g_hasSHA2 = false;
word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
@@ -292,10 +290,22 @@ extern "C" {
longjmp(s_jmpNoCRC32, 1);
}
- static jmp_buf s_jmpNoCrypto;
- static void SigIllHandlerCrypto(int)
+ static jmp_buf s_jmpNoAES;
+ static void SigIllHandlerAES(int)
{
- longjmp(s_jmpNoCrypto, 1);
+ longjmp(s_jmpNoAES, 1);
+ }
+
+ static jmp_buf s_jmpNoSHA1;
+ static void SigIllHandlerSHA1(int)
+ {
+ longjmp(s_jmpNoSHA1, 1);
+ }
+
+ static jmp_buf s_jmpNoSHA2;
+ static void SigIllHandlerSHA2(int)
+ {
+ longjmp(s_jmpNoSHA2, 1);
}
};
#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
@@ -325,8 +335,7 @@ static bool TryNEON()
return true;
# else
// longjmp and clobber warnings. Volatile is required.
- // http://github.com/weidai11/cryptopp/issues/24
- // http://stackoverflow.com/q/7721854
+ // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
volatile bool result = true;
SigHandler oldHandler = signal(SIGILL, SigIllHandlerNEON);
@@ -376,8 +385,7 @@ static bool TryCRC32()
return true;
# else
// longjmp and clobber warnings. Volatile is required.
- // http://github.com/weidai11/cryptopp/issues/24
- // http://stackoverflow.com/q/7721854
+ // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
volatile bool result = true;
SigHandler oldHandler = signal(SIGILL, SigIllHandlerCRC32);
@@ -402,7 +410,7 @@ static bool TryCRC32()
#endif // CRYPTOPP_BOOL_ARM_CRC32_INTRINSICS_AVAILABLE
}
-static bool TryCrypto()
+static bool TryAES()
{
#if (CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE)
# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
@@ -412,8 +420,7 @@ static bool TryCrypto()
static const uint8x16_t data = vdupq_n_u8(0), key = vdupq_n_u8(0);
uint8x16_t r1 = vaeseq_u8(data, key);
uint8x16_t r2 = vaesdq_u8(data, key);
-
- //
+ CRYPTOPP_UNUSED(r1), CRYPTOPP_UNUSED(r2);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
@@ -422,21 +429,121 @@ static bool TryCrypto()
return true;
# else
// longjmp and clobber warnings. Volatile is required.
- // http://github.com/weidai11/cryptopp/issues/24
- // http://stackoverflow.com/q/7721854
+ // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
volatile bool result = true;
- SigHandler oldHandler = signal(SIGILL, SigIllHandlerCrypto);
+ SigHandler oldHandler = signal(SIGILL, SigIllHandlerAES);
if (oldHandler == SIG_ERR)
result = false;
- if (setjmp(s_jmpNoCrypto))
+ if (setjmp(s_jmpNoAES))
result = false;
else
{
static const uint8x16_t data = vdupq_n_u8(0), key = vdupq_n_u8(0);
uint8x16_t r1 = vaeseq_u8(data, key);
uint8x16_t r2 = vaesdq_u8(data, key);
+ CRYPTOPP_UNUSED(r1), CRYPTOPP_UNUSED(r2);
+ }
+
+ signal(SIGILL, oldHandler);
+ return result;
+# endif
+#else
+ return false;
+#endif // CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE
+}
+
+static bool TrySHA1()
+{
+#if (CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE)
+# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
+ __try
+ {
+ static const uint32x4_t data = vdupq_n_u32(0);
+ static const uint32_t hash = 0x0;
+
+ uint32x4_t r1 = vsha1cq_u32 (data, hash, data);
+ uint32x4_t r2 = vsha1mq_u32 (data, hash, data);
+ uint32x4_t r3 = vsha1pq_u32 (data, hash, data);
+ CRYPTOPP_UNUSED(r1), CRYPTOPP_UNUSED(r2), CRYPTOPP_UNUSED(r3);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return false;
+ }
+ return true;
+# else
+ // longjmp and clobber warnings. Volatile is required.
+ // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
+ volatile bool result = true;
+
+ SigHandler oldHandler = signal(SIGILL, SigIllHandlerSHA1);
+ if (oldHandler == SIG_ERR)
+ result = false;
+
+ if (setjmp(s_jmpNoSHA1))
+ result = false;
+ else
+ {
+ static const uint32x4_t data = vdupq_n_u32(0);
+ static const uint32_t hash = 0x0;
+
+ uint32x4_t r1 = vsha1cq_u32 (data, hash, data);
+ uint32x4_t r2 = vsha1mq_u32 (data, hash, data);
+ uint32x4_t r3 = vsha1pq_u32 (data, hash, data);
+ CRYPTOPP_UNUSED(r1), CRYPTOPP_UNUSED(r2), CRYPTOPP_UNUSED(r3);
+ }
+
+ signal(SIGILL, oldHandler);
+ return result;
+# endif
+#else
+ return false;
+#endif // CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE
+}
+
+static bool TrySHA2()
+{
+#if (CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE)
+# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
+ __try
+ {
+ static const uint32x4_t data = vdupq_n_u32(0);
+ static const uint32x4_t hash = vdupq_n_u32(0);
+
+ uint32x4_t r1 = vsha256hq_u32 (hash, hash, data);
+ uint32x4_t r2 = vsha256h2q_u32 (hash, hash, data);
+ uint32x4_t r3 = vsha256su0q_u32 (data, data);
+ uint32x4_t r4 = vsha256su1q_u32 (data, data, data);
+ CRYPTOPP_UNUSED(r1), CRYPTOPP_UNUSED(r2), CRYPTOPP_UNUSED(r3), CRYPTOPP_UNUSED(r4);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return false;
+ }
+ return true;
+# else
+ // longjmp and clobber warnings. Volatile is required.
+ // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
+ volatile bool result = true;
+
+ SigHandler oldHandler = signal(SIGILL, SigIllHandlerSHA2);
+ if (oldHandler == SIG_ERR)
+ result = false;
+
+ if (setjmp(s_jmpNoSHA2))
+ result = false;
+ else
+ {
+ static const uint32x4_t data = vdupq_n_u32(0);
+ static const uint32x4_t hash = vdupq_n_u32(0);
+
+ uint32x4_t r1 = vsha256hq_u32 (hash, hash, data);
+ uint32x4_t r2 = vsha256h2q_u32 (hash, hash, data);
+ uint32x4_t r3 = vsha256su0q_u32 (data, data);
+ uint32x4_t r4 = vsha256su1q_u32 (data, data, data);
+ CRYPTOPP_UNUSED(r1), CRYPTOPP_UNUSED(r2), CRYPTOPP_UNUSED(r3), CRYPTOPP_UNUSED(r4);
}
signal(SIGILL, oldHandler);
@@ -457,7 +564,9 @@ void DetectArmFeatures()
{
g_hasNEON = TryNEON();
g_hasCRC32 = TryCRC32();
- g_hasCrypto = TryCrypto();
+ g_hasAES = TryAES();
+ g_hasSHA1 = TrySHA1();
+ g_hasSHA2 = TrySHA2();
*((volatile bool*)&g_ArmDetectionDone) = true;
}
diff --git a/cpu.h b/cpu.h
index 7d0b4d7e..cbb80d9a 100644
--- a/cpu.h
+++ b/cpu.h
@@ -240,7 +240,7 @@ inline int GetCacheLineSize()
#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)
extern bool g_ArmDetectionDone;
-extern bool g_hasNEON, g_hasCRC32, g_hasCrypto;
+extern bool g_hasNEON, g_hasCRC32, g_hasAES, g_hasSHA1, g_hasSHA2;
void CRYPTOPP_API DetectArmFeatures();
//! \brief Determine if an ARM processor has Advanced SIMD available
@@ -271,19 +271,49 @@ inline bool HasCRC32()
return g_hasCRC32;
}
-//! \brief Determine if an ARM processor has Crypto available
-//! \returns true if the hardware is capable of Crypto at runtime, false otherwise.
-//! \details Crypto instructions provide access to the processor's AES, SHA-1, SHA-224 and SHA-256 intructions.
-//! They are provided by ARM C Language Extensions 2.0 (ACLE 2.0) and available under Aarch64
-//! (ARM-64) and Aarch32 (ARM-32) running on Aarch64 (i.e., an AArch32 execution environment).
+//! \brief Determine if an ARM processor has AES available
+//! \returns true if the hardware is capable of AES at runtime, false otherwise.
+//! \details AES is part of the Crypto extensions from ARM C Language Extensions 2.0 (ACLE 2.0)
+//! and available under Aarch64 (ARM-64) and Aarch32 (ARM-32) running on Aarch64 (i.e., an
+//! AArch32 execution environment).
//! \details Runtime support requires compile time support. When compiling with GCC, you may
//! need to compile with -march=armv8-a+crypto; while Apple requires
//! -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro.
-inline bool HasCrypto()
+inline bool HasAES()
{
if (!g_ArmDetectionDone)
DetectArmFeatures();
- return g_hasCrypto;
+ return g_hasAES;
+}
+
+//! \brief Determine if an ARM processor has SHA1 available
+//! \returns true if the hardware is capable of SHA1 at runtime, false otherwise.
+//! \details SHA1 is part of the Crypto extensions from ARM C Language Extensions 2.0 (ACLE 2.0)
+//! and available under Aarch64 (ARM-64) and Aarch32 (ARM-32) running on Aarch64 (i.e., an
+//! AArch32 execution environment).
+//! \details Runtime support requires compile time support. When compiling with GCC, you may
+//! need to compile with -march=armv8-a+crypto; while Apple requires
+//! -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro.
+inline bool HasSHA1()
+{
+ if (!g_ArmDetectionDone)
+ DetectArmFeatures();
+ return g_hasSHA1;
+}
+
+//! \brief Determine if an ARM processor has SHA2 available
+//! \returns true if the hardware is capable of SHA2 at runtime, false otherwise.
+//! \details SHA2 is part of the Crypto extensions from ARM C Language Extensions 2.0 (ACLE 2.0)
+//! and available under Aarch64 (ARM-64) and Aarch32 (ARM-32) running on Aarch64 (i.e., an
+//! AArch32 execution environment).
+//! \details Runtime support requires compile time support. When compiling with GCC, you may
+//! need to compile with -march=armv8-a+crypto; while Apple requires
+//! -arch arm64. Also see ARM's __ARM_FEATURE_CRYPTO preprocessor macro.
+inline bool HasSHA2()
+{
+ if (!g_ArmDetectionDone)
+ DetectArmFeatures();
+ return g_hasSHA2;
}
//! \brief Provides the cache line size at runtime
diff --git a/validat1.cpp b/validat1.cpp
index 72d68214..69713c28 100644
--- a/validat1.cpp
+++ b/validat1.cpp
@@ -311,6 +311,16 @@ bool TestSettings()
cout << "hasMMX == " << hasMMX << ", hasISSE == " << hasISSE << ", hasSSE2 == " << hasSSE2 << ", hasSSSE3 == " << hasSSE4 << ", hasSSE4 == " << hasSSSE3 << ", hasAESNI == " << HasAESNI() << ", hasRDRAND == " << HasRDRAND() << ", hasRDSEED == " << HasRDSEED() << ", hasCLMUL == " << HasCLMUL() << ", isP4 == " << isP4 << ", cacheLineSize == " << cacheLineSize;
cout << ", AESNI_INTRINSICS == " << CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE << endl;
+
+#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)
+ bool hasNEON = HasNEON();
+ bool hasCRC32 = HasCRC32();
+ bool hasAES = HasAES();
+ bool hasSHA1 = HasSHA1();
+ bool hasSHA2 = HasSHA2();
+
+ cout << "passed: ";
+ cout << "hasNEON == " << hasNEON << ", hasCRC32 == " << hasCRC32 << ", hasAES == " << hasAES << ", hasSHA1 == " << hasSHA1 << ", hasSHA2 == " << hasSHA2 << endl;
#endif
if (!pass)