Add ARMv8 CPU feature queries (GH #685)

CPU feature probes are still outstanding. They are going to be trickier because if CRYPTOPP_XXX_FEATURE_AVAILABLE
pull/687/head
Jeffrey Walton 2018-07-14 08:20:16 -04:00
parent 25abe71e69
commit d11a7b3436
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
3 changed files with 302 additions and 71 deletions

View File

@ -655,7 +655,7 @@ NAMESPACE_END
// not provide an ARM implementation. The Cryptogams implementation // not provide an ARM implementation. The Cryptogams implementation
// is about 2x faster than C/C++. Define this to use the Cryptogams // is about 2x faster than C/C++. Define this to use the Cryptogams
// AES implementation on GNU Linux systems. When defined, Crypto++ // AES implementation on GNU Linux systems. When defined, Crypto++
// will use aes-armv4.S. LLVM miscomiles aes-armv4.S so disable // will use aes-armv4.S. LLVM miscompiles aes-armv4.S so disable
// under Clang. See https://bugs.llvm.org/show_bug.cgi?id=38133. // under Clang. See https://bugs.llvm.org/show_bug.cgi?id=38133.
#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__arm__) && defined(__GNUC__) && !defined(__clang__) #if !defined(CRYPTOPP_DISABLE_ASM) && defined(__arm__) && defined(__GNUC__) && !defined(__clang__)
# define CRYPTOGAMS_ARM_AES 1 # define CRYPTOGAMS_ARM_AES 1

252
cpu.cpp
View File

@ -47,12 +47,14 @@
unsigned long int getauxval(unsigned long int) { return 0; } unsigned long int getauxval(unsigned long int) { return 0; }
#endif #endif
#if defined(__APPLE__) && (defined(__aarch64__) || defined(__POWERPC__)) #if defined(__APPLE__)
# include <sys/utsname.h> # include <sys/utsname.h>
#endif #endif
// The cpu-features header and source file are located in $ANDROID_NDK_ROOT/sources/android/cpufeatures // The cpu-features header and source file are located in
// setenv-android.sh will copy the header and source file into PWD and the makefile will build it in place. // "$ANDROID_NDK_ROOT/sources/android/cpufeatures".
// setenv-android.sh will copy the header and source file
// into PWD and the makefile will build it in place.
#if defined(__ANDROID__) #if defined(__ANDROID__)
# include "cpu-features.h" # include "cpu-features.h"
#endif #endif
@ -62,6 +64,58 @@ unsigned long int getauxval(unsigned long int) { return 0; }
# include <setjmp.h> # include <setjmp.h>
#endif #endif
ANONYMOUS_NAMESPACE_BEGIN
#if defined(__APPLE__)
enum {PowerMac=1, Mac, iPhone, iPod, iPad, AppleTV, AppleWatch};
void GetAppleMachineInfo(unsigned int& device, unsigned int& version)
{
device = version = 0;
struct utsname systemInfo;
systemInfo.machine[0] = '\0';
uname(&systemInfo);
std::string machine(systemInfo.machine);
if (machine.find("PowerMac") || machine.find("Power Macintosh"))
device = PowerMac;
else if (machine.find("Mac") || machine.find("Macintosh"))
device = Mac;
else if (machine.find("iPhone"))
device = iPhone;
else if (machine.find("iPod"))
device = iPod;
else if (machine.find("iPad"))
device = iPad;
else if (machine.find("AppleTV"))
device = AppleTV;
else if (machine.find("AppleWatch"))
device = AppleWatch;
std::string::size_type pos = machine.find_first_of("0123456789");
if (pos != std::string::npos)
version = std::atoi(machine.substr(pos).c_str());
}
// http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
bool IsAppleMachineARMv8(unsigned int device, unsigned int version)
{
if ((device == iPhone && version >= 6) ||
(device == iPad && version >= 4))
{
return true;
}
return false;
}
bool IsAppleMachineARMv84(unsigned int device, unsigned int version)
{
return false;
}
#endif // __APPLE__
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
@ -365,6 +419,10 @@ bool CRYPTOPP_SECTION_INIT g_hasCRC32 = false;
bool CRYPTOPP_SECTION_INIT g_hasAES = false; bool CRYPTOPP_SECTION_INIT g_hasAES = false;
bool CRYPTOPP_SECTION_INIT g_hasSHA1 = false; bool CRYPTOPP_SECTION_INIT g_hasSHA1 = false;
bool CRYPTOPP_SECTION_INIT g_hasSHA2 = false; bool CRYPTOPP_SECTION_INIT g_hasSHA2 = false;
bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
bool CRYPTOPP_SECTION_INIT g_hasSHA3 = false;
bool CRYPTOPP_SECTION_INIT g_hasSM3 = false;
bool CRYPTOPP_SECTION_INIT g_hasSM4 = false;
word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
// ARM does not have an unprivliged equivalent to CPUID on IA-32. We have to jump through some // ARM does not have an unprivliged equivalent to CPUID on IA-32. We have to jump through some
@ -386,8 +444,14 @@ extern bool CPU_ProbeCRC32();
extern bool CPU_ProbeAES(); extern bool CPU_ProbeAES();
extern bool CPU_ProbeSHA1(); extern bool CPU_ProbeSHA1();
extern bool CPU_ProbeSHA2(); extern bool CPU_ProbeSHA2();
extern bool CPU_ProbeSHA512();
extern bool CPU_ProbeSHA3();
extern bool CPU_ProbeSM3();
extern bool CPU_ProbeSM4();
extern bool CPU_ProbePMULL(); extern bool CPU_ProbePMULL();
#if CRYPTOPP_GETAUXV_AVAILABLE
#ifndef HWCAP_ARMv7 #ifndef HWCAP_ARMv7
# define HWCAP_ARMv7 (1 << 29) # define HWCAP_ARMv7 (1 << 29)
#endif #endif
@ -427,6 +491,21 @@ extern bool CPU_ProbePMULL();
#ifndef HWCAP2_SHA2 #ifndef HWCAP2_SHA2
# define HWCAP2_SHA2 (1 << 3) # define HWCAP2_SHA2 (1 << 3)
#endif #endif
// https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
#ifndef HWCAP_SHA3
# define HWCAP_SHA3 (1 << 17)
#endif
#ifndef HWCAP_SM3
# define HWCAP_SM3 (1 << 18)
#endif
#ifndef HWCAP_SM4
# define HWCAP_SM4 (1 << 19)
#endif
#ifndef HWCAP_SHA512
# define HWCAP_SHA512 (1 << 21)
#endif
#endif // CRYPTOPP_GETAUXV_AVAILABLE
inline bool CPU_QueryARMv7() inline bool CPU_QueryARMv7()
{ {
@ -536,20 +615,9 @@ inline bool CPU_QueryAES()
if ((getauxval(AT_HWCAP2) & HWCAP2_AES) != 0) if ((getauxval(AT_HWCAP2) & HWCAP2_AES) != 0)
return true; return true;
#elif defined(__APPLE__) && defined(__aarch64__) #elif defined(__APPLE__) && defined(__aarch64__)
// http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios unsigned int device, version;
struct utsname systemInfo; GetAppleMachineInfo(device, version);
systemInfo.machine[0] = '\0'; return IsAppleMachineARMv8(device, version);
uname(&systemInfo);
// The machine strings below are known ARM8 devices
std::string machine(systemInfo.machine);
if (machine.substr(0, 7) == "iPhone6" || machine.substr(0, 7) == "iPhone7" ||
machine.substr(0, 7) == "iPhone8" || machine.substr(0, 7) == "iPhone9" ||
machine.substr(0, 5) == "iPad4" || machine.substr(0, 5) == "iPad5" ||
machine.substr(0, 5) == "iPad6" || machine.substr(0, 5) == "iPad7")
{
return true;
}
#endif #endif
return false; return false;
} }
@ -571,20 +639,9 @@ inline bool CPU_QuerySHA1()
if ((getauxval(AT_HWCAP2) & HWCAP2_SHA1) != 0) if ((getauxval(AT_HWCAP2) & HWCAP2_SHA1) != 0)
return true; return true;
#elif defined(__APPLE__) && defined(__aarch64__) #elif defined(__APPLE__) && defined(__aarch64__)
// http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios unsigned int device, version;
struct utsname systemInfo; GetAppleMachineInfo(device, version);
systemInfo.machine[0] = '\0'; return IsAppleMachineARMv8(device, version);
uname(&systemInfo);
// The machine strings below are known ARM8 devices
std::string machine(systemInfo.machine);
if (machine.substr(0, 7) == "iPhone6" || machine.substr(0, 7) == "iPhone7" ||
machine.substr(0, 7) == "iPhone8" || machine.substr(0, 7) == "iPhone9" ||
machine.substr(0, 5) == "iPad4" || machine.substr(0, 5) == "iPad5" ||
machine.substr(0, 5) == "iPad6" || machine.substr(0, 5) == "iPad7")
{
return true;
}
#endif #endif
return false; return false;
} }
@ -606,20 +663,109 @@ inline bool CPU_QuerySHA2()
if ((getauxval(AT_HWCAP2) & HWCAP2_SHA2) != 0) if ((getauxval(AT_HWCAP2) & HWCAP2_SHA2) != 0)
return true; return true;
#elif defined(__APPLE__) && defined(__aarch64__) #elif defined(__APPLE__) && defined(__aarch64__)
// http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios unsigned int device, version;
struct utsname systemInfo; GetAppleMachineInfo(device, version);
systemInfo.machine[0] = '\0'; return IsAppleMachineARMv8(device, version);
uname(&systemInfo); #endif
return false;
// The machine strings below are known ARM8 devices
std::string machine(systemInfo.machine);
if (machine.substr(0, 7) == "iPhone6" || machine.substr(0, 7) == "iPhone7" ||
machine.substr(0, 7) == "iPhone8" || machine.substr(0, 7) == "iPhone9" ||
machine.substr(0, 5) == "iPad4" || machine.substr(0, 5) == "iPad5" ||
machine.substr(0, 5) == "iPad6" || machine.substr(0, 5) == "iPad7")
{
return true;
} }
inline bool CPU_QuerySHA512()
{
// Some ARMv8.4 features are disabled at the moment
#if defined(__ANDROID__) && defined(__aarch64__) && 0
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA512) != 0))
return true;
#elif defined(__ANDROID__) && defined(__aarch32__) && 0
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA512) != 0))
return true;
#elif defined(__linux__) && defined(__aarch64__)
if ((getauxval(AT_HWCAP) & HWCAP_SHA512) != 0)
return true;
#elif defined(__linux__) && defined(__aarch32__)
if ((getauxval(AT_HWCAP2) & HWCAP2_SHA512) != 0)
return true;
#elif defined(__APPLE__) && defined(__aarch64__) && 0
unsigned int device, version;
GetAppleMachineInfo(device, version);
return IsAppleMachineARMv84(device, version);
#endif
return false;
}
inline bool CPU_QuerySHA3()
{
// Some ARMv8.4 features are disabled at the moment
#if defined(__ANDROID__) && defined(__aarch64__) && 0
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA3) != 0))
return true;
#elif defined(__ANDROID__) && defined(__aarch32__) && 0
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA3) != 0))
return true;
#elif defined(__linux__) && defined(__aarch64__)
if ((getauxval(AT_HWCAP) & HWCAP_SHA3) != 0)
return true;
#elif defined(__linux__) && defined(__aarch32__)
if ((getauxval(AT_HWCAP2) & HWCAP2_SHA3) != 0)
return true;
#elif defined(__APPLE__) && defined(__aarch64__) && 0
unsigned int device, version;
GetAppleMachineInfo(device, version);
return IsAppleMachineARMv84(device, version);
#endif
return false;
}
inline bool CPU_QuerySM3()
{
// Some ARMv8.4 features are disabled at the moment
#if defined(__ANDROID__) && defined(__aarch64__) && 0
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM3) != 0))
return true;
#elif defined(__ANDROID__) && defined(__aarch32__) && 0
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM3) != 0))
return true;
#elif defined(__linux__) && defined(__aarch64__)
if ((getauxval(AT_HWCAP) & HWCAP_SM3) != 0)
return true;
#elif defined(__linux__) && defined(__aarch32__)
if ((getauxval(AT_HWCAP2) & HWCAP2_SM3) != 0)
return true;
#elif defined(__APPLE__) && defined(__aarch64__) && 0
unsigned int device, version;
GetAppleMachineInfo(device, version);
return IsAppleMachineARMv84(device, version);
#endif
return false;
}
inline bool CPU_QuerySM4()
{
// Some ARMv8.4 features are disabled at the moment
#if defined(__ANDROID__) && defined(__aarch64__) && 0
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM4) != 0))
return true;
#elif defined(__ANDROID__) && defined(__aarch32__) && 0
if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM4) != 0))
return true;
#elif defined(__linux__) && defined(__aarch64__)
if ((getauxval(AT_HWCAP) & HWCAP_SM4) != 0)
return true;
#elif defined(__linux__) && defined(__aarch32__)
if ((getauxval(AT_HWCAP2) & HWCAP2_SM4) != 0)
return true;
#elif defined(__APPLE__) && defined(__aarch64__) && 0
unsigned int device, version;
GetAppleMachineInfo(device, version);
return IsAppleMachineARMv84(device, version);
#endif #endif
return false; return false;
} }
@ -635,6 +781,10 @@ void DetectArmFeatures()
g_hasAES = CPU_QueryAES() || CPU_ProbeAES(); g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
g_hasSHA1 = CPU_QuerySHA1() || CPU_ProbeSHA1(); g_hasSHA1 = CPU_QuerySHA1() || CPU_ProbeSHA1();
g_hasSHA2 = CPU_QuerySHA2() || CPU_ProbeSHA2(); g_hasSHA2 = CPU_QuerySHA2() || CPU_ProbeSHA2();
g_hasSHA512 = CPU_QuerySHA512(); // || CPU_ProbeSHA512();
g_hasSHA3 = CPU_QuerySHA3(); // || CPU_ProbeSHA3();
g_hasSM3 = CPU_QuerySM3(); // || CPU_ProbeSM3();
g_hasSM4 = CPU_QuerySM4(); // || CPU_ProbeSM4();
#if defined(__linux__) && defined(_SC_LEVEL1_DCACHE_LINESIZE) #if defined(__linux__) && defined(_SC_LEVEL1_DCACHE_LINESIZE)
// Glibc does not implement on some platforms. The runtime returns 0 instead of error. // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
@ -689,17 +839,9 @@ inline bool CPU_QueryAltivec()
if (__power_vmx() != 0) if (__power_vmx() != 0)
return true; return true;
#elif defined(__APPLE__) && defined(__POWERPC__) #elif defined(__APPLE__) && defined(__POWERPC__)
// http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios unsigned int device, version;
struct utsname systemInfo; GetAppleMachineInfo(device, version);
systemInfo.machine[0] = '\0'; return device == PowerMac;
uname(&systemInfo);
// The machine strings below are known PPC machines
std::string machine(systemInfo.machine);
if (machine.substr(0, 15) == "Power Macintosh")
{
return true;
}
#endif #endif
return false; return false;
} }

121
cpu.h
View File

@ -342,7 +342,7 @@ inline int GetCacheLineSize()
// Hide from Doxygen // Hide from Doxygen
#ifndef CRYPTOPP_DOXYGEN_PROCESSING #ifndef CRYPTOPP_DOXYGEN_PROCESSING
extern bool g_ArmDetectionDone; extern bool g_ArmDetectionDone;
extern bool g_hasARMv7, g_hasNEON, g_hasPMULL, g_hasCRC32, g_hasAES, g_hasSHA1, g_hasSHA2; extern bool g_hasARMv7, g_hasNEON, g_hasPMULL, g_hasCRC32, g_hasAES, g_hasSHA1, g_hasSHA2, g_hasSHA512, g_hasSHA3, g_hasSM3, g_hasSM4;
void CRYPTOPP_API DetectArmFeatures(); void CRYPTOPP_API DetectArmFeatures();
#endif // CRYPTOPP_DOXYGEN_PROCESSING #endif // CRYPTOPP_DOXYGEN_PROCESSING
@ -352,6 +352,7 @@ void CRYPTOPP_API DetectArmFeatures();
/// \brief Determine if an ARM processor is ARMv7 or above /// \brief Determine if an ARM processor is ARMv7 or above
/// \returns true if the hardware is ARMv7 or above, false otherwise. /// \returns true if the hardware is ARMv7 or above, false otherwise.
/// \details Some AES code requires ARMv7 or above /// \details Some AES code requires ARMv7 or above
/// \since Crypto++ 7.1
/// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms /// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms
inline bool HasARMv7() inline bool HasARMv7()
{ {
@ -371,6 +372,7 @@ inline bool HasARMv7()
/// \details Runtime support requires compile time support. When compiling with GCC, you may /// \details Runtime support requires compile time support. When compiling with GCC, you may
/// need to compile with <tt>-mfpu=neon</tt> (32-bit) or <tt>-march=armv8-a</tt> /// need to compile with <tt>-mfpu=neon</tt> (32-bit) or <tt>-march=armv8-a</tt>
/// (64-bit). Also see ARM's <tt>__ARM_NEON</tt> preprocessor macro. /// (64-bit). Also see ARM's <tt>__ARM_NEON</tt> preprocessor macro.
/// \since Crypto++ 5.6.4
/// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms /// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms
inline bool HasNEON() inline bool HasNEON()
{ {
@ -385,12 +387,14 @@ inline bool HasNEON()
} }
/// \brief Determine if an ARM processor provides Polynomial Multiplication /// \brief Determine if an ARM processor provides Polynomial Multiplication
/// \returns true if the hardware is capable of polynomial multiplications at runtime, false otherwise. /// \returns true if the hardware is capable of polynomial multiplications at runtime,
/// false otherwise.
/// \details The multiplication instructions are available under Aarch32 and Aarch64. /// \details The multiplication instructions are available under Aarch32 and Aarch64.
/// \details Runtime support requires compile time support. When compiling with GCC, you may /// \details Runtime support requires compile time support. When compiling with GCC,
/// need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires /// you may need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires
/// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro. /// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
/// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms /// \since Crypto++ 5.6.4
/// \note This function is only available on Aarch32 and Aarch64 platforms
inline bool HasPMULL() inline bool HasPMULL()
{ {
#if defined(__aarch32__) || defined(__aarch64__) #if defined(__aarch32__) || defined(__aarch64__)
@ -404,12 +408,14 @@ inline bool HasPMULL()
/// \brief Determine if an ARM processor has CRC32 available /// \brief Determine if an ARM processor has CRC32 available
/// \returns true if the hardware is capable of CRC32 at runtime, false otherwise. /// \returns true if the hardware is capable of CRC32 at runtime, false otherwise.
/// \details CRC32 instructions provide access to the processor's CRC-32 and CRC-32C instructions. /// \details CRC32 instructions provide access to the processor's CRC-32 and CRC-32C
/// They are provided by ARM C Language Extensions 2.0 (ACLE 2.0) and available under Aarch32 and Aarch64. /// instructions. They are provided by ARM C Language Extensions 2.0 (ACLE 2.0) and
/// \details Runtime support requires compile time support. When compiling with GCC, you may /// available under Aarch32 and Aarch64.
/// need to compile with <tt>-march=armv8-a+crc</tt>; while Apple requires /// \details Runtime support requires compile time support. When compiling with GCC,
/// you may need to compile with <tt>-march=armv8-a+crc</tt>; while Apple requires
/// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRC32</tt> preprocessor macro. /// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRC32</tt> preprocessor macro.
/// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms /// \since Crypto++ 5.6.4
/// \note This function is only available on Aarch32 and Aarch64 platforms
inline bool HasCRC32() inline bool HasCRC32()
{ {
#if defined(__aarch32__) || defined(__aarch64__) #if defined(__aarch32__) || defined(__aarch64__)
@ -428,7 +434,8 @@ inline bool HasCRC32()
/// \details Runtime support requires compile time support. When compiling with GCC, you may /// \details Runtime support requires compile time support. When compiling with GCC, you may
/// need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires /// need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires
/// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro. /// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
/// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms /// \since Crypto++ 5.6.4
/// \note This function is only available on Aarch32 and Aarch64 platforms
inline bool HasAES() inline bool HasAES()
{ {
#if defined(__aarch32__) || defined(__aarch64__) #if defined(__aarch32__) || defined(__aarch64__)
@ -447,7 +454,8 @@ inline bool HasAES()
/// \details Runtime support requires compile time support. When compiling with GCC, you may /// \details Runtime support requires compile time support. When compiling with GCC, you may
/// need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires /// need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires
/// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro. /// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
/// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms /// \since Crypto++ 5.6.4
/// \note This function is only available on Aarch32 and Aarch64 platforms
inline bool HasSHA1() inline bool HasSHA1()
{ {
#if defined(__aarch32__) || defined(__aarch64__) #if defined(__aarch32__) || defined(__aarch64__)
@ -459,14 +467,15 @@ inline bool HasSHA1()
#endif #endif
} }
/// \brief Determine if an ARM processor has SHA2 available /// \brief Determine if an ARM processor has SHA256 available
/// \returns true if the hardware is capable of SHA2 at runtime, false otherwise. /// \returns true if the hardware is capable of SHA256 at runtime, false otherwise.
/// \details SHA2 is part of the optional Crypto extensions on Aarch32 and Aarch64. They are /// \details SHA256 is part of the optional Crypto extensions on Aarch32 and Aarch64. They are
/// accessed using ARM C Language Extensions 2.0 (ACLE 2.0). /// accessed using ARM C Language Extensions 2.0 (ACLE 2.0).
/// \details Runtime support requires compile time support. When compiling with GCC, you may /// \details Runtime support requires compile time support. When compiling with GCC, you may
/// need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires /// need to compile with <tt>-march=armv8-a+crypto</tt>; while Apple requires
/// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro. /// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
/// \note This function is only available on ARM-32, Aarch32 and Aarch64 platforms /// \since Crypto++ 5.6.4
/// \note This function is only available on Aarch32 and Aarch64 platforms
inline bool HasSHA2() inline bool HasSHA2()
{ {
#if defined(__aarch32__) || defined(__aarch64__) #if defined(__aarch32__) || defined(__aarch64__)
@ -478,6 +487,86 @@ inline bool HasSHA2()
#endif #endif
} }
/// \brief Determine if an ARM processor has SHA512 available
/// \returns true if the hardware is capable of SHA512 at runtime, false otherwise.
/// \details SHA512 is part of the ARMv8.4 Crypto extensions on Aarch32 and Aarch64. They
/// are accessed using ARM C Language Extensions 2.0 (ACLE 2.0).
/// \details Runtime support requires compile time support. When compiling with GCC, you
/// may need to compile with <tt>-march=armv8.4-a+crypto</tt>; while Apple requires
/// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
/// \since Crypto++ 7.1
/// \note This function is only available on Aarch32 and Aarch64 platforms
inline bool HasSHA512()
{
#if defined(__aarch32__) || defined(__aarch64__)
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasSHA512;
#else
return false;
#endif
}
/// \brief Determine if an ARM processor has SHA3 available
/// \returns true if the hardware is capable of SHA3 at runtime, false otherwise.
/// \details SHA3 is part of the ARMv8.4 Crypto extensions on Aarch32 and Aarch64. They
/// are accessed using ARM C Language Extensions 2.0 (ACLE 2.0).
/// \details Runtime support requires compile time support. When compiling with GCC, you
/// may need to compile with <tt>-march=armv8.4-a+crypto</tt>; while Apple requires
/// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
/// \since Crypto++ 7.1
/// \note This function is only available on Aarch32 and Aarch64 platforms
inline bool HasSHA3()
{
#if defined(__aarch32__) || defined(__aarch64__)
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasSHA3;
#else
return false;
#endif
}
/// \brief Determine if an ARM processor has SM3 available
/// \returns true if the hardware is capable of SM3 at runtime, false otherwise.
/// \details SM3 is part of the ARMv8.4 Crypto extensions on Aarch32 and Aarch64. They
/// are accessed using ARM C Language Extensions 2.0 (ACLE 2.0).
/// \details Runtime support requires compile time support. When compiling with GCC, you
/// may need to compile with <tt>-march=armv8.4-a+crypto</tt>; while Apple requires
/// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
/// \since Crypto++ 7.1
/// \note This function is only available on Aarch32 and Aarch64 platforms
inline bool HasSM3()
{
#if defined(__aarch32__) || defined(__aarch64__)
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasSM3;
#else
return false;
#endif
}
/// \brief Determine if an ARM processor has SM4 available
/// \returns true if the hardware is capable of SM4 at runtime, false otherwise.
/// \details SM4 is part of the ARMv8.4 Crypto extensions on Aarch32 and Aarch64. They
/// are accessed using ARM C Language Extensions 2.0 (ACLE 2.0).
/// \details Runtime support requires compile time support. When compiling with GCC, you
/// may need to compile with <tt>-march=armv8.4-a+crypto</tt>; while Apple requires
/// <tt>-arch arm64</tt>. Also see ARM's <tt>__ARM_FEATURE_CRYPTO</tt> preprocessor macro.
/// \since Crypto++ 7.1
/// \note This function is only available on Aarch32 and Aarch64 platforms
inline bool HasSM4()
{
#if defined(__aarch32__) || defined(__aarch64__)
if (!g_ArmDetectionDone)
DetectArmFeatures();
return g_hasSM4;
#else
return false;
#endif
}
//@} //@}
#endif // CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64 #endif // CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64