Crypto++  8.8
Free C++ class library of cryptographic schemes
cpu.cpp
1 // cpu.cpp - originally written and placed in the public domain by Wei Dai
2 // modified by Jeffrey Walton and the community over the years.
3 
4 #include "pch.h"
5 #include "config.h"
6 
7 #ifndef EXCEPTION_EXECUTE_HANDLER
8 # define EXCEPTION_EXECUTE_HANDLER 1
9 #endif
10 
11 #ifndef CRYPTOPP_IMPORTS
12 
13 #include "cpu.h"
14 #include "misc.h"
15 #include "stdcpp.h"
16 
17 // For _xgetbv on Microsoft 32-bit and 64-bit Intel platforms
18 // https://github.com/weidai11/cryptopp/issues/972
19 #if (CRYPTOPP_MSC_VERSION >= 1600) && (defined(_M_IX86) || defined(_M_X64))
20 # include <immintrin.h>
21 #endif
22 
23 // For IsProcessorFeaturePresent on Microsoft Arm64 platforms,
24 // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent
25 #if defined(_WIN32) && defined(_M_ARM64)
26 # include <Windows.h>
27 # include <processthreadsapi.h>
28 #endif
29 
30 #ifdef _AIX
31 # include <sys/systemcfg.h>
32 #endif
33 
34 #ifdef __linux__
35 # include <unistd.h>
36 #endif
37 
38 // Capability queries, requires Glibc 2.16, http://lwn.net/Articles/519085/
39 // CRYPTOPP_GLIBC_VERSION not used because config.h is missing <feature.h>
40 #if (((__GLIBC__ * 100) + __GLIBC_MINOR__) >= 216)
41 # define CRYPTOPP_GETAUXV_AVAILABLE 1
42 #endif
43 
44 #if CRYPTOPP_GETAUXV_AVAILABLE
45 # include <sys/auxv.h>
46 #else
47 #ifndef AT_HWCAP
48 # define AT_HWCAP 16
49 #endif
50 #ifndef AT_HWCAP2
51 # define AT_HWCAP2 26
52 #endif
53 unsigned long int getauxval(unsigned long int) { return 0; }
54 #endif
55 
56 #if defined(__APPLE__)
57 # include <sys/utsname.h>
58 # include <sys/sysctl.h>
59 #endif
60 
61 // FreeBSD headers are giving us trouble...
62 // https://github.com/weidai11/cryptopp/pull/1029
63 #if defined(__FreeBSD__)
64 # include <sys/auxv.h>
65 # include <sys/elf_common.h>
66 #endif
67 
68 // The cpu-features header and source file are located in
69 // "$ANDROID_NDK_ROOT/sources/android/cpufeatures".
70 // setenv-android.sh will copy the header and source file
71 // into PWD and the makefile will build it in place.
72 #if defined(__ANDROID__)
73 # include "cpu-features.h"
74 #endif
75 
76 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
77 # include <signal.h>
78 # include <setjmp.h>
79 #endif
80 
81 // Required by Visual Studio 2008 and below and Clang on Windows.
82 // Use it for all MSVC-compatible compilers.
83 // XGETBV64 and CPUID64 are in x64dll.asm.
84 #if defined(_M_X64) && defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
85 extern "C" unsigned long long __fastcall XGETBV64(unsigned int);
86 extern "C" unsigned long long __fastcall CPUID64(unsigned int, unsigned int, unsigned int*);
87 #endif
88 
89 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
90 extern "C" {
91  typedef void (*SigHandler)(int);
92 }
93 
94 extern "C"
95 {
96  static jmp_buf s_jmpNoCPUID;
97  static void SigIllHandler(int)
98  {
99  longjmp(s_jmpNoCPUID, 1);
100  }
101 }
102 #endif // CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
103 
104 ANONYMOUS_NAMESPACE_BEGIN
105 
106 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
107 
108 using CryptoPP::word32;
109 
110 inline bool IsIntel(const word32 output[4])
111 {
112  // This is the "GenuineIntel" string
113  return (output[1] /*EBX*/ == 0x756e6547) &&
114  (output[2] /*ECX*/ == 0x6c65746e) &&
115  (output[3] /*EDX*/ == 0x49656e69);
116 }
117 
118 inline bool IsAMD(const word32 output[4])
119 {
120  // This is the "AuthenticAMD" string.
121  return ((output[1] /*EBX*/ == 0x68747541) &&
122  (output[2] /*ECX*/ == 0x444D4163) &&
123  (output[3] /*EDX*/ == 0x69746E65)) ||
124  // Early K5's can return "AMDisbetter!"
125  ((output[1] /*EBX*/ == 0x69444d41) &&
126  (output[2] /*ECX*/ == 0x74656273) &&
127  (output[3] /*EDX*/ == 0x21726574));
128 }
129 
130 inline bool IsHygon(const word32 output[4])
131 {
132  // This is the "HygonGenuine" string.
133  return (output[1] /*EBX*/ == 0x6f677948) &&
134  (output[2] /*ECX*/ == 0x656e6975) &&
135  (output[3] /*EDX*/ == 0x6e65476e);
136 }
137 
138 inline bool IsVIA(const word32 output[4])
139 {
140  // This is the "CentaurHauls" string.
141  return ((output[1] /*EBX*/ == 0x746e6543) &&
142  (output[2] /*ECX*/ == 0x736c7561) &&
143  (output[3] /*EDX*/ == 0x48727561)) ||
144  // Some non-PadLock's return "VIA VIA VIA "
145  ((output[1] /*EBX*/ == 0x32414956) &&
146  (output[2] /*ECX*/ == 0x32414956) &&
147  (output[3] /*EDX*/ == 0x32414956));
148 }
149 
150 #endif // X86, X32 and X64
151 
152 #if defined(__APPLE__)
153 
154 // http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
155 class AppleMachineInfo
156 {
157 public:
158  enum { PowerMac=1, Mac, iPhone, iPod, iPad, AppleTV, AppleWatch };
159  enum { PowerPC=1, I386, I686, X86_64, ARM32, ARMV8, ARMV82, ARMV83 };
160 
161  AppleMachineInfo() : m_device(0), m_version(0), m_arch(0)
162  {
163  struct utsname systemInfo;
164  systemInfo.machine[0] = '\0';
165  uname(&systemInfo);
166 
167  std::string machine(systemInfo.machine);
168 
169  std::string::size_type pos = machine.find_first_of("0123456789");
170  if (pos != std::string::npos)
171  m_version = std::atoi(machine.substr(pos).c_str());
172 
173  if (machine.find("iPhone") != std::string::npos)
174  {
175  m_device = iPhone;
176  if (m_version >= 6) { m_arch = ARMV8; }
177  else { m_arch = ARM32; }
178  }
179  else if (machine.find("iPod") != std::string::npos)
180  {
181  m_device = iPod;
182  if (m_version >= 6) { m_arch = ARMV8; }
183  else { m_arch = ARM32; }
184  }
185  else if (machine.find("iPad") != std::string::npos)
186  {
187  m_device = iPad;
188  if (m_version >= 5) { m_arch = ARMV8; }
189  else { m_arch = ARM32; }
190  }
191  else if (machine.find("PowerMac") != std::string::npos ||
192  machine.find("Power Macintosh") != std::string::npos)
193  {
194  m_device = PowerMac;
195  m_arch = PowerPC;
196  }
197  else if (machine.find("Mac") != std::string::npos ||
198  machine.find("Macintosh") != std::string::npos)
199  {
200 #if defined(__x86_64) || defined(__amd64)
201  m_device = Mac;
202  m_arch = X86_64;
203 #elif defined(__i386)
204  m_device = Mac;
205  m_arch = I386;
206 #elif defined(__i686)
207  m_device = Mac;
208  m_arch = I686;
209 #else
210  // Should never get here
211  m_device = Mac;
212  m_arch = 0;
213 #endif
214  }
215  else if (machine.find("AppleTV") != std::string::npos)
216  {
217  m_device = AppleTV;
218  if (m_version >= 4) { m_arch = ARMV8; }
219  else { m_arch = ARM32; }
220  }
221  else if (machine.find("AppleWatch") != std::string::npos)
222  {
223  m_device = AppleWatch;
224  if (m_version >= 4) { m_arch = ARMV8; }
225  else { m_arch = ARM32; }
226  }
227  else if (machine.find("arm64") != std::string::npos)
228  {
229  // M1 machine?
230  std::string brand;
231  size_t size = 32;
232 
233  // Supply an oversized buffer, and avoid
234  // an extra call to sysctlbyname.
235  brand.resize(size);
236  if (sysctlbyname("machdep.cpu.brand_string", &brand[0], &size, NULL, 0) == 0 && size > 0)
237  {
238  if (brand[size-1] == '\0')
239  size--;
240  brand.resize(size);
241  }
242 
243  if (brand == "Apple M1")
244  {
245  m_device = Mac;
246  m_arch = ARMV82;
247  }
248  else
249  {
250  // ???
251  m_device = 0;
252  m_arch = ARMV8;
253  }
254  }
255  else
256  {
257  CRYPTOPP_ASSERT(0);
258  }
259  }
260 
261  unsigned int Device() const {
262  return m_device;
263  }
264 
265  unsigned int Version() const {
266  return m_version;
267  }
268 
269  unsigned int Arch() const {
270  return m_arch;
271  }
272 
273  bool IsARM32() const {
274  return m_arch == ARM32;
275  }
276 
277  bool IsARMv8() const {
278  return m_arch >= ARMV8;
279  }
280 
281  bool IsARMv82() const {
282  return m_arch >= ARMV82;
283  }
284 
285  bool IsARMv83() const {
286  return m_arch >= ARMV83;
287  }
288 
289 private:
290  unsigned int m_device, m_version, m_arch;
291 };
292 
293 void GetAppleMachineInfo(unsigned int& device, unsigned int& version, unsigned int& arch)
294 {
295 #if CRYPTOPP_CXX11_STATIC_INIT
296  static const AppleMachineInfo info;
297 #else
298  using CryptoPP::Singleton;
299  const AppleMachineInfo& info = Singleton<AppleMachineInfo>().Ref();
300 #endif
301 
302  device = info.Device();
303  version = info.Version();
304  arch = info.Arch();
305 }
306 
307 inline bool IsAppleMachineARM32()
308 {
309  static unsigned int arch;
310  if (arch == 0)
311  {
312  unsigned int unused;
313  GetAppleMachineInfo(unused, unused, arch);
314  }
315  return arch == AppleMachineInfo::ARM32;
316 }
317 
318 inline bool IsAppleMachineARMv8()
319 {
320  static unsigned int arch;
321  if (arch == 0)
322  {
323  unsigned int unused;
324  GetAppleMachineInfo(unused, unused, arch);
325  }
326  return arch >= AppleMachineInfo::ARMV8;
327 }
328 
329 inline bool IsAppleMachineARMv82()
330 {
331  static unsigned int arch;
332  if (arch == 0)
333  {
334  unsigned int unused;
335  GetAppleMachineInfo(unused, unused, arch);
336  }
337  return arch >= AppleMachineInfo::ARMV82;
338 }
339 
340 inline bool IsAppleMachineARMv83()
341 {
342  static unsigned int arch;
343  if (arch == 0)
344  {
345  unsigned int unused;
346  GetAppleMachineInfo(unused, unused, arch);
347  }
348  return arch >= AppleMachineInfo::ARMV83;
349 }
350 
351 #endif // __APPLE__
352 
353 ANONYMOUS_NAMESPACE_END
354 
355 NAMESPACE_BEGIN(CryptoPP)
356 
357 // *************************** IA-32 CPUs ***************************
358 
359 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
360 
361 bool CRYPTOPP_SECTION_INIT g_x86DetectionDone = false;
362 bool CRYPTOPP_SECTION_INIT g_hasSSE2 = false;
363 bool CRYPTOPP_SECTION_INIT g_hasSSSE3 = false;
364 bool CRYPTOPP_SECTION_INIT g_hasSSE41 = false;
365 bool CRYPTOPP_SECTION_INIT g_hasSSE42 = false;
366 bool CRYPTOPP_SECTION_INIT g_hasAESNI = false;
367 bool CRYPTOPP_SECTION_INIT g_hasCLMUL = false;
368 bool CRYPTOPP_SECTION_INIT g_hasMOVBE = false;
369 bool CRYPTOPP_SECTION_INIT g_hasAVX = false;
370 bool CRYPTOPP_SECTION_INIT g_hasAVX2 = false;
371 bool CRYPTOPP_SECTION_INIT g_hasADX = false;
372 bool CRYPTOPP_SECTION_INIT g_hasSHA = false;
373 bool CRYPTOPP_SECTION_INIT g_hasRDRAND = false;
374 bool CRYPTOPP_SECTION_INIT g_hasRDSEED = false;
375 bool CRYPTOPP_SECTION_INIT g_isP4 = false;
376 bool CRYPTOPP_SECTION_INIT g_hasPadlockRNG = false;
377 bool CRYPTOPP_SECTION_INIT g_hasPadlockACE = false;
378 bool CRYPTOPP_SECTION_INIT g_hasPadlockACE2 = false;
379 bool CRYPTOPP_SECTION_INIT g_hasPadlockPHE = false;
380 bool CRYPTOPP_SECTION_INIT g_hasPadlockPMM = false;
382 
383 // For Solaris 11
384 extern bool CPU_ProbeSSE2();
385 
386 // xcr0 is available when xgetbv is present.
387 // The intrinsic is broke on GCC 8.1 and earlier. Also see
388 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684.
389 word64 XGetBV(word32 num)
390 {
391 // Required by Visual Studio 2008 and below and Clang on Windows.
392 // Use it for all MSVC-compatible compilers.
393 #if defined(_M_X64) && defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
394 
395  return XGETBV64(num);
396 
397 // Required by Visual Studio 2008 and below and Clang on Windows.
398 // Use it for all MSVC-compatible compilers.
399 #elif defined(_M_IX86) && defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
400 
401  word32 a=0, d=0;
402  __asm {
403  push eax
404  push edx
405  push ecx
406  mov ecx, num
407  _emit 0x0f
408  _emit 0x01
409  _emit 0xd0
410  mov a, eax
411  mov d, edx
412  pop ecx
413  pop edx
414  pop eax
415  }
416  return (static_cast<word64>(d) << 32) | a;
417 
418 // GCC 4.4 and above
419 #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
420 
421  word32 a=0, d=0;
422  __asm__
423  (
424  "xgetbv" : "=a"(a), "=d"(d) : "c"(num) : "cc"
425  );
426  return (static_cast<word64>(d) << 32) | a;
427 
428 // Remainder of GCC and compatibles.
429 #elif defined(__GNUC__) || defined(__clang__) || defined(__SUNPRO_CC)
430 
431  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71659 and
432  // http://www.agner.org/optimize/vectorclass/read.php?i=65
433  word32 a=0, d=0;
434  __asm__
435  (
436  ".byte 0x0f, 0x01, 0xd0" "\n\t"
437  : "=a"(a), "=d"(d) : "c"(num) : "cc"
438  );
439  return (static_cast<word64>(d) << 32) | a;
440 #else
441  # error "Need an xgetbv function"
442 #endif
443 }
444 
445 // No inline due to Borland/Embarcadero and Issue 498
446 // cpu.cpp (131): E2211 Inline assembly not allowed in inline and template functions
447 bool CpuId(word32 func, word32 subfunc, word32 output[4])
448 {
449 // Required by Visual Studio 2008 and below and Clang on Windows.
450 // Use it for all MSVC-compatible compilers.
451 #if defined(_M_X64) && defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
452 
453  CPUID64(func, subfunc, output);
454  return true;
455 
456 // Required by Visual Studio 2008 and below and Clang on Windows.
457 // Use it for all MSVC-compatible compilers.
458 #elif defined(_M_IX86) && defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
459 
460  __try
461  {
462  // Borland/Embarcadero and Issue 500
463  // Local variables for cpuid output
464  word32 a, b, c, d;
465  __asm
466  {
467  push ebx
468  mov eax, func
469  mov ecx, subfunc
470  cpuid
471  mov [a], eax
472  mov [b], ebx
473  mov [c], ecx
474  mov [d], edx
475  pop ebx
476  }
477  output[0] = a;
478  output[1] = b;
479  output[2] = c;
480  output[3] = d;
481  }
482  __except (EXCEPTION_EXECUTE_HANDLER)
483  {
484  return false;
485  }
486 
487  return true;
488 
489 // Linux, Unix, OS X, Solaris, Cygwin, MinGW
490 #else
491 
492  // longjmp and clobber warnings. Volatile is required.
493  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
494  volatile bool result = true;
495 
496  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
497  if (oldHandler == SIG_ERR)
498  return false;
499 
500 # ifndef __MINGW32__
501  volatile sigset_t oldMask;
502  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask) != 0)
503  {
504  signal(SIGILL, oldHandler);
505  return false;
506  }
507 # endif
508 
509  if (setjmp(s_jmpNoCPUID))
510  result = false;
511  else
512  {
513  asm volatile
514  (
515  // save ebx in case -fPIC is being used
516 # if CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
517  "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
518 # else
519  "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
520 # endif
521  : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
522  : "a" (func), "c" (subfunc)
523  : "cc"
524  );
525  }
526 
527 # ifndef __MINGW32__
528  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
529 # endif
530 
531  signal(SIGILL, oldHandler);
532  return result;
533 #endif
534 }
535 
536 void DetectX86Features()
537 {
538  // Coverity finding CID 171239. Initialize arrays.
539  // Indexes: EAX=0, EBX=1, ECX=2, EDX=3
540  word32 cpuid0[4]={0}, cpuid1[4]={0}, cpuid2[4]={0};
541 
542 #if defined(CRYPTOPP_DISABLE_ASM)
543  // Not available
544  goto done;
545 #else
546  if (!CpuId(0, 0, cpuid0))
547  goto done;
548  if (!CpuId(1, 0, cpuid1))
549  goto done;
550 #endif
551 
552  CRYPTOPP_CONSTANT(EAX_REG = 0);
553  CRYPTOPP_CONSTANT(EBX_REG = 1);
554  CRYPTOPP_CONSTANT(ECX_REG = 2);
555  CRYPTOPP_CONSTANT(EDX_REG = 3);
556 
557  CRYPTOPP_CONSTANT(MMX_FLAG = (1 << 24)); // EDX
558  CRYPTOPP_CONSTANT(SSE_FLAG = (1 << 25)); // EDX
559  CRYPTOPP_CONSTANT(SSE2_FLAG = (1 << 26)); // EDX
560 
561  CRYPTOPP_CONSTANT(SSE3_FLAG = (1 << 0)); // ECX
562  CRYPTOPP_CONSTANT(SSSE3_FLAG = (1 << 9)); // ECX
563  CRYPTOPP_CONSTANT(SSE41_FLAG = (1 << 19)); // ECX
564  CRYPTOPP_CONSTANT(SSE42_FLAG = (1 << 20)); // ECX
565  CRYPTOPP_CONSTANT(MOVBE_FLAG = (1 << 22)); // ECX
566  CRYPTOPP_CONSTANT(AESNI_FLAG = (1 << 25)); // ECX
567  CRYPTOPP_CONSTANT(CLMUL_FLAG = (1 << 1)); // ECX
568 
569  CRYPTOPP_CONSTANT(XSAVE_FLAG = (1 << 26)); // ECX
570  CRYPTOPP_CONSTANT(OSXSAVE_FLAG = (1 << 27)); // ECX
571 
572  CRYPTOPP_CONSTANT(AVX_FLAG = (3 << 27)); // ECX
573  CRYPTOPP_CONSTANT(YMM_FLAG = (3 << 1)); // CR0
574 
575  // x86_64 machines don't check some flags because SSE2
576  // is part of the core instruction set architecture
577  CRYPTOPP_UNUSED(MMX_FLAG); CRYPTOPP_UNUSED(SSE_FLAG);
578  CRYPTOPP_UNUSED(SSE2_FLAG); CRYPTOPP_UNUSED(SSE3_FLAG);
579  CRYPTOPP_UNUSED(XSAVE_FLAG);
580 
581 #if (CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
582  // 64-bit core instruction set includes SSE2. Just check
583  // the OS enabled SSE2 support using OSXSAVE.
584  g_hasSSE2 = (cpuid1[ECX_REG] & OSXSAVE_FLAG) != 0;
585 #else
586  // Check the processor supports SSE2. Then use OSXSAVE to
587  // signal OS support for SSE2 to avoid probes.
588  // Also see http://stackoverflow.com/a/22521619/608639
589  // and http://github.com/weidai11/cryptopp/issues/511.
590  if ((cpuid1[EDX_REG] & SSE2_FLAG) == SSE2_FLAG)
591  g_hasSSE2 = (cpuid1[ECX_REG] & XSAVE_FLAG) != 0 &&
592  (cpuid1[ECX_REG] & OSXSAVE_FLAG) != 0;
593 #endif
594 
595 #if defined(__sun)
596  // Solaris 11 i86pc does not signal SSE support using
597  // OSXSAVE. We need to probe for SSE support.
598  if (g_hasSSE2 == false)
599  g_hasSSE2 = CPU_ProbeSSE2();
600 #endif
601 
602  if (g_hasSSE2 == false)
603  goto done;
604 
605  g_hasSSSE3 = (cpuid1[ECX_REG] & SSSE3_FLAG) != 0;
606  g_hasSSE41 = (cpuid1[ECX_REG] & SSE41_FLAG) != 0;
607  g_hasSSE42 = (cpuid1[ECX_REG] & SSE42_FLAG) != 0;
608  g_hasMOVBE = (cpuid1[ECX_REG] & MOVBE_FLAG) != 0;
609  g_hasAESNI = (cpuid1[ECX_REG] & AESNI_FLAG) != 0;
610  g_hasCLMUL = (cpuid1[ECX_REG] & CLMUL_FLAG) != 0;
611 
612  // AVX is similar to SSE. Check if AVX is available on the cpu, then
613  // check if the OS enabled XSAVE/XRESTORE for the extended registers.
614  // https://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
615  if ((cpuid1[ECX_REG] & AVX_FLAG) == AVX_FLAG)
616  {
617  word64 xcr0 = XGetBV(0);
618  g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
619  }
620 
621  if (IsIntel(cpuid0))
622  {
623  CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30));
624  CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18));
625  CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19));
626  CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29));
627  CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5));
628 
629  g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
630  g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
631  g_hasRDRAND = (cpuid1[ECX_REG] & RDRAND_FLAG) != 0;
632 
633  if (cpuid0[EAX_REG] >= 7)
634  {
635  if (CpuId(7, 0, cpuid2))
636  {
637  g_hasRDSEED = (cpuid2[EBX_REG] & RDSEED_FLAG) != 0;
638  g_hasADX = (cpuid2[EBX_REG] & ADX_FLAG) != 0;
639  g_hasSHA = (cpuid2[EBX_REG] & SHA_FLAG) != 0;
640  g_hasAVX2 = (cpuid2[EBX_REG] & AVX2_FLAG) != 0;
641  }
642  }
643  }
644  else if (IsAMD(cpuid0) || IsHygon(cpuid0))
645  {
646  CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30));
647  CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18));
648  CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19));
649  CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29));
650  CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5));
651 
652  CpuId(0x80000005, 0, cpuid2);
653  g_cacheLineSize = GETBYTE(cpuid2[ECX_REG], 0);
654  g_hasRDRAND = (cpuid1[ECX_REG] & RDRAND_FLAG) != 0;
655 
656  if (cpuid0[EAX_REG] >= 7)
657  {
658  if (CpuId(7, 0, cpuid2))
659  {
660  g_hasRDSEED = (cpuid2[EBX_REG] & RDSEED_FLAG) != 0;
661  g_hasADX = (cpuid2[EBX_REG] & ADX_FLAG) != 0;
662  g_hasSHA = (cpuid2[EBX_REG] & SHA_FLAG) != 0;
663  g_hasAVX2 = (cpuid2[EBX_REG] & AVX2_FLAG) != 0;
664  }
665  }
666 
667  // Unconditionally disable RDRAND and RDSEED on AMD cpu's with family 15h or 16h.
668  // See Crypto++ Issue 924, https://github.com/weidai11/cryptopp/issues/924,
669  // Clear RDRAND CPUID bit on AMD family 15h/16h, https://lore.kernel.org/patchwork/patch/1115413/,
670  // and AMD CPUID Specification, https://www.amd.com/system/files/TechDocs/25481.pdf
671  {
672  CRYPTOPP_CONSTANT(FAMILY_BASE_FLAG = (0x0f << 8));
673  CRYPTOPP_CONSTANT(FAMILY_EXT_FLAG = (0xff << 20));
674 
675  word32 family = (cpuid1[0] & FAMILY_BASE_FLAG) >> 8;
676  if (family == 0xf)
677  family += (cpuid1[0] & FAMILY_EXT_FLAG) >> 20;
678  if (family == 0x15 || family == 0x16)
679  {
680  g_hasRDRAND = false;
681  g_hasRDSEED = false;
682  }
683  }
684  }
685  else if (IsVIA(cpuid0))
686  {
687  // Two bits: available and enabled
688  CRYPTOPP_CONSTANT( RNG_FLAGS = (0x3 << 2));
689  CRYPTOPP_CONSTANT( ACE_FLAGS = (0x3 << 6));
690  CRYPTOPP_CONSTANT(ACE2_FLAGS = (0x3 << 8));
691  CRYPTOPP_CONSTANT( PHE_FLAGS = (0x3 << 10));
692  CRYPTOPP_CONSTANT( PMM_FLAGS = (0x3 << 12));
693 
694  CpuId(0xC0000000, 0, cpuid2);
695  word32 extendedFeatures = cpuid2[0];
696 
697  if (extendedFeatures >= 0xC0000001)
698  {
699  CpuId(0xC0000001, 0, cpuid2);
700  g_hasPadlockRNG = (cpuid2[EDX_REG] & RNG_FLAGS) != 0;
701  g_hasPadlockACE = (cpuid2[EDX_REG] & ACE_FLAGS) != 0;
702  g_hasPadlockACE2 = (cpuid2[EDX_REG] & ACE2_FLAGS) != 0;
703  g_hasPadlockPHE = (cpuid2[EDX_REG] & PHE_FLAGS) != 0;
704  g_hasPadlockPMM = (cpuid2[EDX_REG] & PMM_FLAGS) != 0;
705  }
706 
707  if (extendedFeatures >= 0xC0000005)
708  {
709  CpuId(0xC0000005, 0, cpuid2);
710  g_cacheLineSize = GETBYTE(cpuid2[ECX_REG], 0);
711  }
712  }
713 
714  // Keep AVX2 in sync with OS support for AVX. AVX tests both
715  // cpu support and OS support, while AVX2 only tests cpu support.
716  g_hasAVX2 &= g_hasAVX;
717 
718 done:
719 
720 #if defined(_SC_LEVEL1_DCACHE_LINESIZE)
721  // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
722  // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
723  int cacheLineSize = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
724  if (g_cacheLineSize == 0 && cacheLineSize > 0)
725  g_cacheLineSize = cacheLineSize;
726 #endif
727 
728  if (g_cacheLineSize == 0)
729  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
730 
731  *const_cast<volatile bool*>(&g_x86DetectionDone) = true;
732 }
733 
734 // *************************** ARM-32, Aarch32 and Aarch64 ***************************
735 
736 #elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8)
737 
738 bool CRYPTOPP_SECTION_INIT g_ArmDetectionDone = false;
739 bool CRYPTOPP_SECTION_INIT g_hasARMv7 = false;
740 bool CRYPTOPP_SECTION_INIT g_hasNEON = false;
741 bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
742 bool CRYPTOPP_SECTION_INIT g_hasCRC32 = false;
743 bool CRYPTOPP_SECTION_INIT g_hasAES = false;
744 bool CRYPTOPP_SECTION_INIT g_hasSHA1 = false;
745 bool CRYPTOPP_SECTION_INIT g_hasSHA2 = false;
746 bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
747 bool CRYPTOPP_SECTION_INIT g_hasSHA3 = false;
748 bool CRYPTOPP_SECTION_INIT g_hasSM3 = false;
749 bool CRYPTOPP_SECTION_INIT g_hasSM4 = false;
751 
752 // ARM does not have an unprivileged equivalent to CPUID on IA-32. We have to
753 // jump through some hoops to detect features on a wide array of platforms.
754 // Our strategy is two part. First, attempt to *Query* the OS for a feature,
755 // like using getauxval on Linux. If that fails, then *Probe* the cpu
756 // executing an instruction and an observe a SIGILL if unsupported. The probes
757 // are in source files where compilation options like -march=armv8-a+crc make
758 // intrinsics available. They are expensive when compared to a standard OS
759 // feature query. Always perform the feature query first. For Linux see
760 // http://sourceware.org/ml/libc-help/2017-08/msg00012.html
761 // Avoid probes on Apple platforms because Apple's signal handling for SIGILLs
762 // appears broken. We are trying to figure out a way to feature test without
763 // probes. Also see http://stackoverflow.com/a/11197770/608639 and
764 // http://gist.github.com/erkanyildiz/390a480f27e86f8cd6ba.
765 
766 extern bool CPU_ProbeARMv7();
767 extern bool CPU_ProbeNEON();
768 extern bool CPU_ProbeCRC32();
769 extern bool CPU_ProbeAES();
770 extern bool CPU_ProbeSHA1();
771 extern bool CPU_ProbeSHA256();
772 extern bool CPU_ProbeSHA512();
773 extern bool CPU_ProbeSHA3();
774 extern bool CPU_ProbeSM3();
775 extern bool CPU_ProbeSM4();
776 extern bool CPU_ProbePMULL();
777 
778 // https://github.com/torvalds/linux/blob/master/arch/arm/include/uapi/asm/hwcap.h
779 // https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
780 #ifndef HWCAP_ARMv7
781 # define HWCAP_ARMv7 (1 << 29)
782 #endif
783 #ifndef HWCAP_ASIMD
784 # define HWCAP_ASIMD (1 << 1)
785 #endif
786 #ifndef HWCAP_NEON
787 # define HWCAP_NEON (1 << 12)
788 #endif
789 #ifndef HWCAP_CRC32
790 # define HWCAP_CRC32 (1 << 7)
791 #endif
792 #ifndef HWCAP2_CRC32
793 # define HWCAP2_CRC32 (1 << 4)
794 #endif
795 #ifndef HWCAP_PMULL
796 # define HWCAP_PMULL (1 << 4)
797 #endif
798 #ifndef HWCAP2_PMULL
799 # define HWCAP2_PMULL (1 << 1)
800 #endif
801 #ifndef HWCAP_AES
802 # define HWCAP_AES (1 << 3)
803 #endif
804 #ifndef HWCAP2_AES
805 # define HWCAP2_AES (1 << 0)
806 #endif
807 #ifndef HWCAP_SHA1
808 # define HWCAP_SHA1 (1 << 5)
809 #endif
810 #ifndef HWCAP_SHA2
811 # define HWCAP_SHA2 (1 << 6)
812 #endif
813 #ifndef HWCAP2_SHA1
814 # define HWCAP2_SHA1 (1 << 2)
815 #endif
816 #ifndef HWCAP2_SHA2
817 # define HWCAP2_SHA2 (1 << 3)
818 #endif
819 #ifndef HWCAP_SHA3
820 # define HWCAP_SHA3 (1 << 17)
821 #endif
822 #ifndef HWCAP_SM3
823 # define HWCAP_SM3 (1 << 18)
824 #endif
825 #ifndef HWCAP_SM4
826 # define HWCAP_SM4 (1 << 19)
827 #endif
828 #ifndef HWCAP_SHA512
829 # define HWCAP_SHA512 (1 << 21)
830 #endif
831 
832 inline bool CPU_QueryARMv7()
833 {
834 #if defined(__ANDROID__) && defined(__arm__)
835  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
836  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0))
837  return true;
838 #elif defined(__linux__) && defined(__arm__)
839  if ((getauxval(AT_HWCAP) & HWCAP_ARMv7) != 0 ||
840  (getauxval(AT_HWCAP) & HWCAP_NEON) != 0)
841  return true;
842 #elif defined(__APPLE__) && defined(__arm__)
843  // Apple hardware is ARMv7 or above.
844  return true;
845 #elif defined(_WIN32) && defined(_M_ARM64)
846  // Windows 10 ARM64 is only supported on Armv8a and above
847  return true;
848 #endif
849  return false;
850 }
851 
852 inline bool CPU_QueryNEON()
853 {
854 #if defined(__ANDROID__) && defined(__aarch64__)
855  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
856  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_ASIMD) != 0))
857  return true;
858 #elif defined(__ANDROID__) && defined(__arm__)
859  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
860  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0))
861  return true;
862 #elif defined(__linux__) && defined(__aarch64__)
863  if ((getauxval(AT_HWCAP) & HWCAP_ASIMD) != 0)
864  return true;
865 #elif defined(__linux__) && defined(__aarch32__)
866  if ((getauxval(AT_HWCAP2) & HWCAP2_ASIMD) != 0)
867  return true;
868 #elif defined(__linux__) && defined(__arm__)
869  if ((getauxval(AT_HWCAP) & HWCAP_NEON) != 0)
870  return true;
871 #elif defined(__APPLE__) && defined(__aarch64__)
872  // Core feature set for Aarch32 and Aarch64.
873  if (IsAppleMachineARMv8())
874  return true;
875 #elif defined(_WIN32) && defined(_M_ARM64)
876  // Windows 10 ARM64 is only supported on Armv8a and above
877  if (IsProcessorFeaturePresent(PF_ARM_V8_INSTRUCTIONS_AVAILABLE) != 0)
878  return true;
879 #endif
880  return false;
881 }
882 
883 inline bool CPU_QueryCRC32()
884 {
885 #if defined(__ANDROID__) && defined(__aarch64__)
886  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
887  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_CRC32) != 0))
888  return true;
889 #elif defined(__ANDROID__) && defined(__aarch32__)
890  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
891  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_CRC32) != 0))
892  return true;
893 #elif defined(__linux__) && defined(__aarch64__)
894  if ((getauxval(AT_HWCAP) & HWCAP_CRC32) != 0)
895  return true;
896 #elif defined(__linux__) && defined(__aarch32__)
897  if ((getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0)
898  return true;
899 #elif defined(__APPLE__) && defined(__aarch64__)
900  // M1 processor
901  if (IsAppleMachineARMv82())
902  return true;
903 #elif defined(_WIN32) && defined(_M_ARM64)
904  if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0)
905  return true;
906 #endif
907  return false;
908 }
909 
910 inline bool CPU_QueryPMULL()
911 {
912 #if defined(__ANDROID__) && defined(__aarch64__)
913  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
914  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_PMULL) != 0))
915  return true;
916 #elif defined(__ANDROID__) && defined(__aarch32__)
917  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
918  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_PMULL) != 0))
919  return true;
920 #elif defined(__linux__) && defined(__aarch64__)
921  if ((getauxval(AT_HWCAP) & HWCAP_PMULL) != 0)
922  return true;
923 #elif defined(__linux__) && defined(__aarch32__)
924  if ((getauxval(AT_HWCAP2) & HWCAP2_PMULL) != 0)
925  return true;
926 #elif defined(__APPLE__) && defined(__aarch64__)
927  // M1 processor
928  if (IsAppleMachineARMv82())
929  return true;
930 #elif defined(_WIN32) && defined(_M_ARM64)
931  if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
932  return true;
933 #endif
934  return false;
935 }
936 
937 inline bool CPU_QueryAES()
938 {
939 #if defined(__ANDROID__) && defined(__aarch64__)
940  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
941  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES) != 0))
942  return true;
943 #elif defined(__ANDROID__) && defined(__aarch32__)
944  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
945  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES) != 0))
946  return true;
947 #elif defined(__linux__) && defined(__aarch64__)
948  if ((getauxval(AT_HWCAP) & HWCAP_AES) != 0)
949  return true;
950 #elif defined(__linux__) && defined(__aarch32__)
951  if ((getauxval(AT_HWCAP2) & HWCAP2_AES) != 0)
952  return true;
953 #elif defined(__APPLE__) && defined(__aarch64__)
954  // M1 processor
955  if (IsAppleMachineARMv82())
956  return true;
957 #elif defined(_WIN32) && defined(_M_ARM64)
958  if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
959  return true;
960 #endif
961  return false;
962 }
963 
964 inline bool CPU_QuerySHA1()
965 {
966 #if defined(__ANDROID__) && defined(__aarch64__)
967  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
968  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA1) != 0))
969  return true;
970 #elif defined(__ANDROID__) && defined(__aarch32__)
971  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
972  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA1) != 0))
973  return true;
974 #elif defined(__linux__) && defined(__aarch64__)
975  if ((getauxval(AT_HWCAP) & HWCAP_SHA1) != 0)
976  return true;
977 #elif defined(__linux__) && defined(__aarch32__)
978  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA1) != 0)
979  return true;
980 #elif defined(__APPLE__) && defined(__aarch64__)
981  // M1 processor
982  if (IsAppleMachineARMv82())
983  return true;
984 #elif defined(_WIN32) && defined(_M_ARM64)
985  if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
986  return true;
987 #endif
988  return false;
989 }
990 
991 inline bool CPU_QuerySHA256()
992 {
993 #if defined(__ANDROID__) && defined(__aarch64__)
994  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
995  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA2) != 0))
996  return true;
997 #elif defined(__ANDROID__) && defined(__aarch32__)
998  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
999  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA2) != 0))
1000  return true;
1001 #elif defined(__linux__) && defined(__aarch64__)
1002  if ((getauxval(AT_HWCAP) & HWCAP_SHA2) != 0)
1003  return true;
1004 #elif defined(__linux__) && defined(__aarch32__)
1005  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA2) != 0)
1006  return true;
1007 #elif defined(__APPLE__) && defined(__aarch64__)
1008  // M1 processor
1009  if (IsAppleMachineARMv82())
1010  return true;
1011 #elif defined(_WIN32) && defined(_M_ARM64)
1012  if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
1013  return true;
1014 #endif
1015  return false;
1016 }
1017 
1018 // Some ARMv8.2 features are disabled at the moment
1019 inline bool CPU_QuerySHA3()
1020 {
1021  // According to the ARM manual, SHA3 depends upon SHA1 and SHA2.
1022  // If SHA1 and SHA2 are not present, then SHA3 and SHA512 are
1023  // not present. Also see Arm A64 Instruction Set Architecture,
1024  // https://developer.arm.com/documentation/ddi0596/2020-12/
1025  if (!g_hasSHA1 || !g_hasSHA2) { return false; }
1026 
1027 #if defined(__ANDROID__) && defined(__aarch64__) && 0
1028  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
1029  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA3) != 0))
1030  return true;
1031 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
1032  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
1033  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA3) != 0))
1034  return true;
1035 #elif defined(__linux__) && defined(__aarch64__)
1036  if ((getauxval(AT_HWCAP) & HWCAP_SHA3) != 0)
1037  return true;
1038 #elif defined(__linux__) && defined(__aarch32__)
1039  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA3) != 0)
1040  return true;
1041 #elif defined(__APPLE__) && defined(__aarch64__)
1042  // M1 processor
1043  if (IsAppleMachineARMv82())
1044  return true;
1045 #endif
1046  return false;
1047 }
1048 
1049 // Some ARMv8.2 features are disabled at the moment
1050 inline bool CPU_QuerySHA512()
1051 {
1052  // According to the ARM manual, SHA512 depends upon SHA1 and SHA2.
1053  // If SHA1 and SHA2 are not present, then SHA3 and SHA512 are
1054  // not present. Also see Arm A64 Instruction Set Architecture,
1055  // https://developer.arm.com/documentation/ddi0596/2020-12/
1056  if (!g_hasSHA1 || !g_hasSHA2) { return false; }
1057 
1058 #if defined(__ANDROID__) && defined(__aarch64__) && 0
1059  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
1060  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA512) != 0))
1061  return true;
1062 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
1063  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
1064  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA512) != 0))
1065  return true;
1066 #elif defined(__linux__) && defined(__aarch64__)
1067  if ((getauxval(AT_HWCAP) & HWCAP_SHA512) != 0)
1068  return true;
1069 #elif defined(__linux__) && defined(__aarch32__)
1070  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA512) != 0)
1071  return true;
1072 #elif defined(__APPLE__) && defined(__aarch64__)
1073  // M1 processor
1074  if (IsAppleMachineARMv82())
1075  return true;
1076 #endif
1077  return false;
1078 }
1079 
1080 // Some ARMv8.2 features are disabled at the moment
1081 inline bool CPU_QuerySM3()
1082 {
1083 #if defined(__ANDROID__) && defined(__aarch64__) && 0
1084  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
1085  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM3) != 0))
1086  return true;
1087 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
1088  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
1089  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM3) != 0))
1090  return true;
1091 #elif defined(__linux__) && defined(__aarch64__)
1092  if ((getauxval(AT_HWCAP) & HWCAP_SM3) != 0)
1093  return true;
1094 #elif defined(__linux__) && defined(__aarch32__)
1095  if ((getauxval(AT_HWCAP2) & HWCAP2_SM3) != 0)
1096  return true;
1097 #elif defined(__APPLE__) && defined(__aarch64__) && 0
1098  // No Apple support yet.
1099 #endif
1100  return false;
1101 }
1102 
1103 // Some ARMv8.2 features are disabled at the moment
1104 inline bool CPU_QuerySM4()
1105 {
1106 #if defined(__ANDROID__) && defined(__aarch64__) && 0
1107  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
1108  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM4) != 0))
1109  return true;
1110 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
1111  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
1112  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM4) != 0))
1113  return true;
1114 #elif defined(__linux__) && defined(__aarch64__)
1115  if ((getauxval(AT_HWCAP) & HWCAP_SM4) != 0)
1116  return true;
1117 #elif defined(__linux__) && defined(__aarch32__)
1118  if ((getauxval(AT_HWCAP2) & HWCAP2_SM4) != 0)
1119  return true;
1120 #elif defined(__APPLE__) && defined(__aarch64__) && 0
1121  // No Apple support yet.
1122 #endif
1123  return false;
1124 }
1125 
1126 void DetectArmFeatures()
1127 {
1128 #ifndef CRYPTOPP_DISABLE_ASM
1129 
1130  // The CPU_ProbeXXX's return false for OSes which
1131  // can't tolerate SIGILL-based probes
1132  g_hasARMv7 = CPU_QueryARMv7() || CPU_ProbeARMv7();
1133  g_hasNEON = CPU_QueryNEON() || CPU_ProbeNEON();
1134  g_hasCRC32 = CPU_QueryCRC32() || CPU_ProbeCRC32();
1135  g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
1136  g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
1137  g_hasSHA1 = CPU_QuerySHA1() || CPU_ProbeSHA1();
1138  g_hasSHA2 = CPU_QuerySHA256() || CPU_ProbeSHA256();
1139  g_hasSHA512 = CPU_QuerySHA512(); // || CPU_ProbeSHA512();
1140  g_hasSHA3 = CPU_QuerySHA3(); // || CPU_ProbeSHA3();
1141  g_hasSM3 = CPU_QuerySM3(); // || CPU_ProbeSM3();
1142  g_hasSM4 = CPU_QuerySM4(); // || CPU_ProbeSM4();
1143 
1144 #if defined(_SC_LEVEL1_DCACHE_LINESIZE)
1145  // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
1146  // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
1147  int cacheLineSize = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
1148  if (cacheLineSize > 0)
1149  g_cacheLineSize = cacheLineSize;
1150 #endif
1151 
1152  if (g_cacheLineSize == 0)
1153  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
1154 
1155 #endif // CRYPTOPP_DISABLE_ASM
1156 
1157  *const_cast<volatile bool*>(&g_ArmDetectionDone) = true;
1158 }
1159 
1160 // *************************** PowerPC and PowerPC64 ***************************
1161 
1162 #elif (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
1163 
1164 bool CRYPTOPP_SECTION_INIT g_PowerPcDetectionDone = false;
1165 bool CRYPTOPP_SECTION_INIT g_hasAltivec = false;
1166 bool CRYPTOPP_SECTION_INIT g_hasPower7 = false;
1167 bool CRYPTOPP_SECTION_INIT g_hasPower8 = false;
1168 bool CRYPTOPP_SECTION_INIT g_hasPower9 = false;
1169 bool CRYPTOPP_SECTION_INIT g_hasAES = false;
1170 bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
1171 bool CRYPTOPP_SECTION_INIT g_hasSHA256 = false;
1172 bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
1173 bool CRYPTOPP_SECTION_INIT g_hasDARN = false;
1175 
1176 extern bool CPU_ProbeAltivec();
1177 extern bool CPU_ProbePower7();
1178 extern bool CPU_ProbePower8();
1179 extern bool CPU_ProbePower9();
1180 extern bool CPU_ProbeAES();
1181 extern bool CPU_ProbePMULL();
1182 extern bool CPU_ProbeSHA256();
1183 extern bool CPU_ProbeSHA512();
1184 extern bool CPU_ProbeDARN();
1185 
1186 // AIX defines. We used to just call __power_7_andup()
1187 // and friends but at Power9, too many compilers were
1188 // missing __power_9_andup(). Instead we switched to
1189 // a pattern similar to OpenSSL caps testing.
1190 #ifndef __power_6_andup
1191 # define __power_6_andup() __power_set(0xffffffffU<<14)
1192 #endif
1193 #ifndef __power_7_andup
1194 # define __power_7_andup() __power_set(0xffffffffU<<15)
1195 #endif
1196 #ifndef __power_8_andup
1197 # define __power_8_andup() __power_set(0xffffffffU<<16)
1198 #endif
1199 #ifndef __power_9_andup
1200 # define __power_9_andup() __power_set(0xffffffffU<<17)
1201 #endif
1202 
1203 // AIX first supported Altivec at Power6, though it
1204 // was available much earlier for other vendors.
1205 inline bool CPU_QueryAltivec()
1206 {
1207 #if defined(__linux__) && defined(PPC_FEATURE_HAS_ALTIVEC)
1208  if ((getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC) != 0)
1209  return true;
1210 #elif defined(_AIX)
1211  if (__power_6_andup() != 0)
1212  return true;
1213 #elif defined(__APPLE__) && defined(__POWERPC__)
1214  unsigned int unused, arch;
1215  GetAppleMachineInfo(unused, unused, arch);
1216  return arch == AppleMachineInfo::PowerMac;
1217 #elif defined(__FreeBSD__) && defined(PPC_FEATURE_HAS_ALTIVEC)
1218  unsigned long cpufeatures;
1219  if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)) == 0)
1220  if ((cpufeatures & PPC_FEATURE_HAS_ALTIVEC) != 0)
1221  return true;
1222 #endif
1223  return false;
1224 }
1225 
1226 inline bool CPU_QueryPower7()
1227 {
1228  // Power7 and ISA 2.06
1229 #if defined(__linux__) && defined(PPC_FEATURE_ARCH_2_06)
1230  if ((getauxval(AT_HWCAP) & PPC_FEATURE_ARCH_2_06) != 0)
1231  return true;
1232 #elif defined(_AIX)
1233  if (__power_7_andup() != 0)
1234  return true;
1235 #elif defined(__FreeBSD__) && defined(PPC_FEATURE_ARCH_2_06)
1236  unsigned long cpufeatures;
1237  if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)) == 0)
1238  if ((cpufeatures & PPC_FEATURE_ARCH_2_06) != 0)
1239  return true;
1240 #endif
1241  return false;
1242 }
1243 
1244 inline bool CPU_QueryPower8()
1245 {
1246  // Power8 and ISA 2.07 provide in-core crypto.
1247 #if defined(__linux__) && defined(PPC_FEATURE2_ARCH_2_07)
1248  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07) != 0)
1249  return true;
1250 #elif defined(_AIX)
1251  if (__power_8_andup() != 0)
1252  return true;
1253 #elif defined(__FreeBSD__) && defined(PPC_FEATURE2_ARCH_2_07)
1254  unsigned long cpufeatures;
1255  if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)) == 0)
1256  if ((cpufeatures & PPC_FEATURE_ARCH_2_07) != 0)
1257  return true;
1258 #endif
1259  return false;
1260 }
1261 
1262 inline bool CPU_QueryPower9()
1263 {
1264  // Power9 and ISA 3.0.
1265 #if defined(__linux__) && defined(PPC_FEATURE2_ARCH_3_00)
1266  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
1267  return true;
1268 #elif defined(_AIX)
1269  if (__power_9_andup() != 0)
1270  return true;
1271 #elif defined(__FreeBSD__) && defined(PPC_FEATURE2_ARCH_3_00)
1272  unsigned long cpufeatures;
1273  if (elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)) == 0)
1274  if ((cpufeatures & PPC_FEATURE_ARCH2_3_00) != 0)
1275  return true;
1276 #endif
1277  return false;
1278 }
1279 
1280 inline bool CPU_QueryAES()
1281 {
1282  // Power8 and ISA 2.07 provide in-core crypto. Glibc
1283  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1284 #if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO)
1285  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1286  return true;
1287 #elif defined(_AIX)
1288  if (__power_8_andup() != 0)
1289  return true;
1290 #elif defined(__FreeBSD__) && defined(PPC_FEATURE2_HAS_VEC_CRYPTO)
1291  unsigned long cpufeatures;
1292  if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0)
1293  if ((cpufeatures & PPC_FEATURE2_HAS_VEC_CRYPTO != 0)
1294  return true;
1295 #endif
1296  return false;
1297 }
1298 
1299 inline bool CPU_QueryPMULL()
1300 {
1301  // Power8 and ISA 2.07 provide in-core crypto. Glibc
1302  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1303 #if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO)
1304  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1305  return true;
1306 #elif defined(_AIX)
1307  if (__power_8_andup() != 0)
1308  return true;
1309 #elif defined(__FreeBSD__) && defined(PPC_FEATURE2_HAS_VEC_CRYPTO)
1310  unsigned long cpufeatures;
1311  if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0)
1312  if ((cpufeatures & PPC_FEATURE2_HAS_VEC_CRYPTO != 0)
1313  return true;
1314 #endif
1315  return false;
1316 }
1317 
1318 inline bool CPU_QuerySHA256()
1319 {
1320  // Power8 and ISA 2.07 provide in-core crypto. Glibc
1321  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1322 #if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO)
1323  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1324  return true;
1325 #elif defined(_AIX)
1326  if (__power_8_andup() != 0)
1327  return true;
1328 #elif defined(__FreeBSD__) && defined(PPC_FEATURE2_HAS_VEC_CRYPTO)
1329  unsigned long cpufeatures;
1330  if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0)
1331  if ((cpufeatures & PPC_FEATURE2_HAS_VEC_CRYPTO != 0)
1332  return true;
1333 #endif
1334  return false;
1335 }
1336 inline bool CPU_QuerySHA512()
1337 {
1338  // Power8 and ISA 2.07 provide in-core crypto. Glibc
1339  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1340 #if defined(__linux__) && defined(PPC_FEATURE2_VEC_CRYPTO)
1341  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1342  return true;
1343 #elif defined(_AIX)
1344  if (__power_8_andup() != 0)
1345  return true;
1346 #elif defined(__FreeBSD__) && defined(PPC_FEATURE2_HAS_VEC_CRYPTO)
1347  unsigned long cpufeatures;
1348  if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0)
1349  if ((cpufeatures & PPC_FEATURE2_HAS_VEC_CRYPTO != 0)
1350  return true;
1351 #endif
1352  return false;
1353 }
1354 
1355 // Power9 random number generator
1356 inline bool CPU_QueryDARN()
1357 {
1358  // Power9 and ISA 3.0 provide DARN. It looks like
1359  // Glibc offers PPC_FEATURE2_DARN.
1360 #if defined(__linux__) && defined(PPC_FEATURE2_ARCH_3_00)
1361  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
1362  return true;
1363 #elif defined(_AIX)
1364  if (__power_9_andup() != 0)
1365  return true;
1366 #elif defined(__FreeBSD__) && defined(PPC_FEATURE2_ARCH_3_00)
1367  unsigned long cpufeatures;
1368  if (elf_aux_info(AT_HWCAP2, &cpufeatures, sizeof(cpufeatures)) == 0)
1369  if ((cpufeatures & PPC_FEATURE2_ARCH_3_00) != 0)
1370  return true;
1371 #endif
1372  return false;
1373 }
1374 
1375 void DetectPowerPcFeatures()
1376 {
1377  // GCC 10 is giving us trouble in CPU_ProbePower9() and CPU_ProbeDARN().
1378  // GCC is generating POWER9 instructions on POWER8 for ppc_power9.cpp.
1379  // The compiler idiots did not think through the consequences of
1380  // requiring us to use -mcpu=power9 to unlock the ISA. Epic fail.
1381  // https://github.com/weidai11/cryptopp/issues/986
1382 
1383 #ifndef CRYPTOPP_DISABLE_ASM
1384 
1385  // The CPU_ProbeXXX's return false for OSes which
1386  // can't tolerate SIGILL-based probes, like Apple
1387  g_hasAltivec = CPU_QueryAltivec() || CPU_ProbeAltivec();
1388  g_hasPower7 = CPU_QueryPower7() || CPU_ProbePower7();
1389  g_hasPower8 = CPU_QueryPower8() || CPU_ProbePower8();
1390  g_hasPower9 = CPU_QueryPower9() || CPU_ProbePower9();
1391  g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
1392  g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
1393  g_hasSHA256 = CPU_QuerySHA256() || CPU_ProbeSHA256();
1394  g_hasSHA512 = CPU_QuerySHA512() || CPU_ProbeSHA512();
1395  g_hasDARN = CPU_QueryDARN() || CPU_ProbeDARN();
1396 
1397 #if defined(_AIX) && defined(SC_L1C_DLS)
1398  // /usr/include/sys/systemcfg.h
1399  int cacheLineSize = getsystemcfg(SC_L1C_DLS);
1400  if (cacheLineSize > 0)
1401  g_cacheLineSize = cacheLineSize;
1402 #elif defined(_SC_LEVEL1_DCACHE_LINESIZE)
1403  // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
1404  // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
1405  int cacheLineSize = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
1406  if (cacheLineSize > 0)
1407  g_cacheLineSize = cacheLineSize;
1408 #endif
1409 
1410  if (g_cacheLineSize == 0)
1411  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
1412 
1413 #endif // CRYPTOPP_DISABLE_ASM
1414 
1415  *const_cast<volatile bool*>(&g_PowerPcDetectionDone) = true;
1416 }
1417 
1418 #endif
1419 NAMESPACE_END
1420 
1421 // *************************** C++ Static Initialization ***************************
1422 
1423 ANONYMOUS_NAMESPACE_BEGIN
1424 
1425 class InitCpu
1426 {
1427 public:
1428  InitCpu()
1429  {
1430 #if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
1431  CryptoPP::DetectX86Features();
1432 #elif CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8
1433  CryptoPP::DetectArmFeatures();
1434 #elif CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64
1435  CryptoPP::DetectPowerPcFeatures();
1436 #endif
1437  }
1438 };
1439 
1440 // This is not really needed because HasSSE() and friends can dynamically initialize.
1441 // Everything depends on CPU features so we initialize it once at load time.
1442 // Dynamic initialization will be used if init priorities are not available.
1443 
1444 #if HAVE_GCC_INIT_PRIORITY
1445  const InitCpu s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 10))) = InitCpu();
1446 #elif HAVE_MSC_INIT_PRIORITY
1447  #pragma warning(disable: 4075)
1448  #pragma init_seg(".CRT$XCU")
1449  const InitCpu s_init;
1450  #pragma warning(default: 4075)
1451 #elif HAVE_XLC_INIT_PRIORITY
1452  // XLC needs constant, not a define
1453  #pragma priority(270)
1454  const InitCpu s_init;
1455 #else
1456  const InitCpu s_init;
1457 #endif
1458 
1459 ANONYMOUS_NAMESPACE_END
1460 
1461 #endif // CRYPTOPP_IMPORTS
Restricts the instantiation of a class to one static object without locks.
Definition: misc.h:309
const T & Ref(...) const
Return a reference to the inner Singleton object.
Definition: misc.h:329
Library configuration file.
#define CRYPTOPP_L1_CACHE_LINE_SIZE
L1 data cache line size.
Definition: config_cpu.h:147
#define CRYPTOPP_SECTION_INIT
Initialized data section.
Definition: config_cpu.h:168
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
unsigned long long word64
64-bit unsigned datatype
Definition: config_int.h:101
Functions for CPU features and intrinsics.
Utility functions for the Crypto++ library.
Crypto++ library namespace.
const char * Version()
int
Definition: argnames.h:18
Precompiled header file.
Common C++ header files.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68