Crypto++  6.1
Free C++ class library of cryptographic schemes
cpu.cpp
1 // cpu.cpp - originally written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "config.h"
5 
6 #ifndef EXCEPTION_EXECUTE_HANDLER
7 # define EXCEPTION_EXECUTE_HANDLER 1
8 #endif
9 
10 #ifndef CRYPTOPP_IMPORTS
11 
12 #include "cpu.h"
13 #include "misc.h"
14 #include "stdcpp.h"
15 
16 #ifdef _AIX
17 # include <sys/systemcfg.h>
18 #endif
19 
20 #ifdef __linux__
21 # include <unistd.h>
22 #endif
23 
24 // Capability queries, requires Glibc 2.16, http://lwn.net/Articles/519085/
25 // CRYPTOPP_GLIBC_VERSION not used because config.h is missing <feature.h>
26 #if (((__GLIBC__ * 100) + __GLIBC_MINOR__) >= 216)
27 # define CRYPTOPP_GETAUXV_AVAILABLE 1
28 #endif
29 
30 #if CRYPTOPP_GETAUXV_AVAILABLE
31 # include <sys/auxv.h>
32 #else
33 unsigned long int getauxval(unsigned long int) { return 0; }
34 #endif
35 
36 #if defined(__APPLE__) && (defined(__aarch64__) || defined(__POWERPC__))
37 # include <sys/utsname.h>
38 #endif
39 
40 // The cpu-features header and source file are located in $ANDROID_NDK_ROOT/sources/android/cpufeatures
41 // setenv-android.sh will copy the header and source file into PWD and the makefile will build it in place.
42 #if defined(__ANDROID__)
43 # include "cpu-features.h"
44 #endif
45 
46 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
47 # include <signal.h>
48 # include <setjmp.h>
49 #endif
50 
51 NAMESPACE_BEGIN(CryptoPP)
52 
53 #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
54 extern "C" {
55  typedef void (*SigHandler)(int);
56 };
57 
58 extern "C"
59 {
60  static jmp_buf s_jmpNoCPUID;
61  static void SigIllHandlerCPUID(int unused)
62  {
63  CRYPTOPP_UNUSED(unused);
64  longjmp(s_jmpNoCPUID, 1);
65  }
66 }
67 #endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
68 
69 // *************************** IA-32 CPUs ***************************
70 
71 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
72 
73 extern bool CPU_ProbeSSE2();
74 
75 #if _MSC_VER >= 1500
76 
77 inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
78 {
79  __cpuidex((int *)output, func, subfunc);
80  return true;
81 }
82 
83 #elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
84 
85 inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
86 {
87  if (subfunc != 0)
88  return false;
89 
90  __cpuid((int *)output, func);
91  return true;
92 }
93 
94 #else
95 
96 // Borland/Embarcadero and Issue 498
97 // cpu.cpp (131): E2211 Inline assembly not allowed in inline and template functions
98 bool CpuId(word32 func, word32 subfunc, word32 output[4])
99 {
100 #if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) || defined(__BORLANDC__)
101  __try
102  {
103  // Borland/Embarcadero and Issue 500
104  // Local variables for cpuid output
105  word32 a, b, c, d;
106  __asm
107  {
108  mov eax, func
109  mov ecx, subfunc
110  cpuid
111  mov [a], eax
112  mov [b], ebx
113  mov [c], ecx
114  mov [d], edx
115  }
116  output[0] = a;
117  output[1] = b;
118  output[2] = c;
119  output[3] = d;
120  }
121  // GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION
122  __except (EXCEPTION_EXECUTE_HANDLER)
123  {
124  return false;
125  }
126 
127  // func = 0 returns the highest basic function understood in EAX. If the CPU does
128  // not return non-0, then it is mostly useless. The code below converts basic
129  // function value to a true/false return value.
130  if(func == 0)
131  return output[0] != 0;
132 
133  return true;
134 #else
135  // longjmp and clobber warnings. Volatile is required.
136  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
137  volatile bool result = true;
138 
139  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
140  if (oldHandler == SIG_ERR)
141  return false;
142 
143 # ifndef __MINGW32__
144  volatile sigset_t oldMask;
145  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask) != 0)
146  return false;
147 # endif
148 
149  if (setjmp(s_jmpNoCPUID))
150  result = false;
151  else
152  {
153  asm volatile
154  (
155  // save ebx in case -fPIC is being used
156  // TODO: this might need an early clobber on EDI.
157 # if CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
158  "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
159 # else
160  "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
161 # endif
162  : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
163  : "a" (func), "c" (subfunc)
164  : "cc"
165  );
166  }
167 
168 # ifndef __MINGW32__
169  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
170 # endif
171 
172  signal(SIGILL, oldHandler);
173  return result;
174 #endif
175 }
176 
177 #endif
178 
179 bool CRYPTOPP_SECTION_INIT g_x86DetectionDone = false;
180 bool CRYPTOPP_SECTION_INIT CRYPTOPP_SECTION_INIT g_hasSSE2 = false, CRYPTOPP_SECTION_INIT g_hasSSSE3 = false;
181 bool CRYPTOPP_SECTION_INIT g_hasSSE41 = false, CRYPTOPP_SECTION_INIT g_hasSSE42 = false;
182 bool CRYPTOPP_SECTION_INIT g_hasAESNI = false, CRYPTOPP_SECTION_INIT g_hasCLMUL = false;
183 bool CRYPTOPP_SECTION_INIT g_hasADX = false, CRYPTOPP_SECTION_INIT g_hasSHA = false;
184 bool CRYPTOPP_SECTION_INIT g_hasRDRAND = false, CRYPTOPP_SECTION_INIT g_hasRDSEED = false, CRYPTOPP_SECTION_INIT g_isP4 = false;
185 bool CRYPTOPP_SECTION_INIT g_hasPadlockRNG = false, CRYPTOPP_SECTION_INIT g_hasPadlockACE = false, CRYPTOPP_SECTION_INIT g_hasPadlockACE2 = false;
186 bool CRYPTOPP_SECTION_INIT g_hasPadlockPHE = false, CRYPTOPP_SECTION_INIT g_hasPadlockPMM = false;
187 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
188 
189 static inline bool IsIntel(const word32 output[4])
190 {
191  // This is the "GenuineIntel" string
192  return (output[1] /*EBX*/ == 0x756e6547) &&
193  (output[2] /*ECX*/ == 0x6c65746e) &&
194  (output[3] /*EDX*/ == 0x49656e69);
195 }
196 
197 static inline bool IsAMD(const word32 output[4])
198 {
199  // This is the "AuthenticAMD" string. Some early K5's can return "AMDisbetter!"
200  return (output[1] /*EBX*/ == 0x68747541) &&
201  (output[2] /*ECX*/ == 0x444D4163) &&
202  (output[3] /*EDX*/ == 0x69746E65);
203 }
204 
205 static inline bool IsVIA(const word32 output[4])
206 {
207  // This is the "CentaurHauls" string. Some non-PadLock's can return "VIA VIA VIA "
208  return (output[1] /*EBX*/ == 0x746e6543) &&
209  (output[2] /*ECX*/ == 0x736c7561) &&
210  (output[3] /*EDX*/ == 0x48727561);
211 }
212 
213 void DetectX86Features()
214 {
215  // Coverity finding CID 171239...
216  word32 cpuid0[4]={0}, cpuid1[4]={0}, cpuid2[4]={0};
217  if (!CpuId(0, 0, cpuid0))
218  return;
219  if (!CpuId(1, 0, cpuid1))
220  return;
221 
222  // cpuid1[2] & (1 << 27) is XSAVE/XRESTORE and signals OS support for SSE; use it to avoid probes.
223  // See http://github.com/weidai11/cryptopp/issues/511 and http://stackoverflow.com/a/22521619/608639
224  if ((cpuid1[3] & (1 << 26)) != 0)
225  g_hasSSE2 = ((cpuid1[2] & (1 << 27)) != 0) || CPU_ProbeSSE2();
226 
227  g_hasSSSE3 = g_hasSSE2 && ((cpuid1[2] & (1<< 9)) != 0);
228  g_hasSSE41 = g_hasSSE2 && ((cpuid1[2] & (1<<19)) != 0);
229  g_hasSSE42 = g_hasSSE2 && ((cpuid1[2] & (1<<20)) != 0);
230  g_hasAESNI = g_hasSSE2 && ((cpuid1[2] & (1<<25)) != 0);
231  g_hasCLMUL = g_hasSSE2 && ((cpuid1[2] & (1<< 1)) != 0);
232 
233  if (IsIntel(cpuid0))
234  {
235  CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30))
236  CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18))
237  CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19))
238  CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29))
239 
240  g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
241  g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
242  g_hasRDRAND = (cpuid1[2] /*ECX*/ & RDRAND_FLAG) != 0;
243 
244  if (cpuid0[0] /*EAX*/ >= 7)
245  {
246  if (CpuId(7, 0, cpuid2))
247  {
248  g_hasRDSEED = (cpuid2[1] /*EBX*/ & RDSEED_FLAG) != 0;
249  g_hasADX = (cpuid2[1] /*EBX*/ & ADX_FLAG) != 0;
250  g_hasSHA = (cpuid2[1] /*EBX*/ & SHA_FLAG) != 0;
251  }
252  }
253  }
254  else if (IsAMD(cpuid0))
255  {
256  CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30))
257  CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18))
258  CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19))
259  CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29))
260 
261  CpuId(0x80000005, 0, cpuid2);
262  g_cacheLineSize = GETBYTE(cpuid2[2], 0);
263  g_hasRDRAND = (cpuid1[2] /*ECX*/ & RDRAND_FLAG) != 0;
264 
265  if (cpuid0[0] /*EAX*/ >= 7)
266  {
267  if (CpuId(7, 0, cpuid2))
268  {
269  g_hasRDSEED = (cpuid2[1] /*EBX*/ & RDSEED_FLAG) != 0;
270  g_hasADX = (cpuid2[1] /*EBX*/ & ADX_FLAG) != 0;
271  g_hasSHA = (cpuid2[1] /*EBX*/ & SHA_FLAG) != 0;
272  }
273  }
274  }
275  else if (IsVIA(cpuid0))
276  {
277  CRYPTOPP_CONSTANT( RNG_FLAGS = (0x3 << 2))
278  CRYPTOPP_CONSTANT( ACE_FLAGS = (0x3 << 6))
279  CRYPTOPP_CONSTANT(ACE2_FLAGS = (0x3 << 8))
280  CRYPTOPP_CONSTANT( PHE_FLAGS = (0x3 << 10))
281  CRYPTOPP_CONSTANT( PMM_FLAGS = (0x3 << 12))
282 
283  CpuId(0xC0000000, 0, cpuid2);
284  if (cpuid2[0] >= 0xC0000001)
285  {
286  // Extended features available
287  CpuId(0xC0000001, 0, cpuid2);
288  g_hasPadlockRNG = (cpuid2[3] /*EDX*/ & RNG_FLAGS) != 0;
289  g_hasPadlockACE = (cpuid2[3] /*EDX*/ & ACE_FLAGS) != 0;
290  g_hasPadlockACE2 = (cpuid2[3] /*EDX*/ & ACE2_FLAGS) != 0;
291  g_hasPadlockPHE = (cpuid2[3] /*EDX*/ & PHE_FLAGS) != 0;
292  g_hasPadlockPMM = (cpuid2[3] /*EDX*/ & PMM_FLAGS) != 0;
293  }
294  }
295 
296  if (!g_cacheLineSize)
297  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
298 
299  *const_cast<volatile bool*>(&g_x86DetectionDone) = true;
300 }
301 
302 // *************************** ARM-32, Aarch32 and Aarch64 ***************************
303 
304 #elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)
305 
306 bool CRYPTOPP_SECTION_INIT g_ArmDetectionDone = false;
307 bool CRYPTOPP_SECTION_INIT g_hasNEON = false, CRYPTOPP_SECTION_INIT g_hasPMULL = false, CRYPTOPP_SECTION_INIT g_hasCRC32 = false;
308 bool CRYPTOPP_SECTION_INIT g_hasAES = false, CRYPTOPP_SECTION_INIT g_hasSHA1 = false, CRYPTOPP_SECTION_INIT g_hasSHA2 = false;
309 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
310 
311 // ARM does not have an unprivliged equivalent to CPUID on IA-32. We have to jump through some
312 // hoops to detect features on a wide array of platforms. Our strategy is two part. First,
313 // attempt to *Query* the OS for a feature, like using getauxval on Linux. If that fails,
314 // then *Probe* the cpu executing an instruction and an observe a SIGILL if unsupported.
315 // The probes are in source files where compilation options like -march=armv8-a+crc make
316 // intrinsics available. They are expensive when compared to a standard OS feature query.
317 // Always perform the feature quesry first. For Linux see
318 // http://sourceware.org/ml/libc-help/2017-08/msg00012.html
319 // Avoid probes on Apple platforms because Apple's signal handling for SIGILLs appears broken.
320 // We are trying to figure out a way to feature test without probes. Also see
321 // http://stackoverflow.com/a/11197770/608639 and
322 // http://gist.github.com/erkanyildiz/390a480f27e86f8cd6ba
323 
324 extern bool CPU_ProbeNEON();
325 extern bool CPU_ProbeCRC32();
326 extern bool CPU_ProbeAES();
327 extern bool CPU_ProbeSHA1();
328 extern bool CPU_ProbeSHA2();
329 extern bool CPU_ProbePMULL();
330 
331 #ifndef HWCAP_ASIMD
332 # define HWCAP_ASIMD (1 << 1)
333 #endif
334 #ifndef HWCAP_ARM_NEON
335 # define HWCAP_ARM_NEON 4096
336 #endif
337 #ifndef HWCAP_CRC32
338 # define HWCAP_CRC32 (1 << 7)
339 #endif
340 #ifndef HWCAP2_CRC32
341 # define HWCAP2_CRC32 (1 << 4)
342 #endif
343 #ifndef HWCAP_PMULL
344 # define HWCAP_PMULL (1 << 4)
345 #endif
346 #ifndef HWCAP2_PMULL
347 # define HWCAP2_PMULL (1 << 1)
348 #endif
349 #ifndef HWCAP_AES
350 # define HWCAP_AES (1 << 3)
351 #endif
352 #ifndef HWCAP2_AES
353 # define HWCAP2_AES (1 << 0)
354 #endif
355 #ifndef HWCAP_SHA1
356 # define HWCAP_SHA1 (1 << 5)
357 #endif
358 #ifndef HWCAP_SHA2
359 # define HWCAP_SHA2 (1 << 6)
360 #endif
361 #ifndef HWCAP2_SHA1
362 # define HWCAP2_SHA1 (1 << 2)
363 #endif
364 #ifndef HWCAP2_SHA2
365 # define HWCAP2_SHA2 (1 << 3)
366 #endif
367 
368 inline bool CPU_QueryNEON()
369 {
370 #if defined(__ANDROID__) && defined(__aarch64__)
371  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) &&
372  (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_ASIMD))
373  return true;
374 #elif defined(__ANDROID__) && defined(__arm__)
375  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) &&
376  (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON))
377  return true;
378 #elif defined(__linux__) && defined(__aarch64__)
379  if (getauxval(AT_HWCAP) & HWCAP_ASIMD)
380  return true;
381 #elif defined(__linux__) && defined(__aarch32__)
382  if (getauxval(AT_HWCAP2) & HWCAP2_ASIMD)
383  return true;
384 #elif defined(__linux__) && defined(__arm__)
385  if (getauxval(AT_HWCAP) & HWCAP_ARM_NEON)
386  return true;
387 #elif defined(__APPLE__) && defined(__aarch64__)
388  // Core feature set for Aarch32 and Aarch64.
389  return true;
390 #endif
391  return false;
392 }
393 
394 inline bool CPU_QueryCRC32()
395 {
396 #if defined(__ANDROID__) && defined(__aarch64__)
397  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) &&
398  (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_CRC32))
399  return true;
400 #elif defined(__ANDROID__) && defined(__aarch32__)
401  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) &&
402  (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_CRC32))
403  return true;
404 #elif defined(__linux__) && defined(__aarch64__)
405  if (getauxval(AT_HWCAP) & HWCAP_CRC32)
406  return true;
407 #elif defined(__linux__) && defined(__aarch32__)
408  if (getauxval(AT_HWCAP2) & HWCAP2_CRC32)
409  return true;
410 #elif defined(__APPLE__) && defined(__aarch64__)
411  // No compiler support. CRC intrinsics result in a failed compiled.
412  return false;
413 #endif
414  return false;
415 }
416 
417 inline bool CPU_QueryPMULL()
418 {
419 #if defined(__ANDROID__) && defined(__aarch64__)
420  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) &&
421  (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_PMULL))
422  return true;
423 #elif defined(__ANDROID__) && defined(__aarch32__)
424  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) &&
425  (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_PMULL))
426  return true;
427 #elif defined(__linux__) && defined(__aarch64__)
428  if (getauxval(AT_HWCAP) & HWCAP_PMULL)
429  return true;
430 #elif defined(__linux__) && defined(__aarch32__)
431  if (getauxval(AT_HWCAP2) & HWCAP2_PMULL)
432  return true;
433 #elif defined(__APPLE__) && defined(__aarch64__)
434  // No compiler support. PMULL intrinsics result in a failed compiled.
435  return false;
436 #endif
437  return false;
438 }
439 
440 inline bool CPU_QueryAES()
441 {
442 #if defined(__ANDROID__) && defined(__aarch64__)
443  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) &&
444  (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES))
445  return true;
446 #elif defined(__ANDROID__) && defined(__aarch32__)
447  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) &&
448  (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES))
449  return true;
450 #elif defined(__linux__) && defined(__aarch64__)
451  if (getauxval(AT_HWCAP) & HWCAP_AES)
452  return true;
453 #elif defined(__linux__) && defined(__aarch32__)
454  if (getauxval(AT_HWCAP2) & HWCAP2_AES)
455  return true;
456 #elif defined(__APPLE__) && defined(__aarch64__)
457  // http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
458  struct utsname systemInfo;
459  systemInfo.machine[0] = '\0';
460  uname(&systemInfo);
461 
462  // The machine strings below are known ARM8 devices
463  std::string machine(systemInfo.machine);
464  if (machine.substr(0, 7) == "iPhone6" || machine.substr(0, 7) == "iPhone7" ||
465  machine.substr(0, 7) == "iPhone8" || machine.substr(0, 7) == "iPhone9" ||
466  machine.substr(0, 5) == "iPad4" || machine.substr(0, 5) == "iPad5" ||
467  machine.substr(0, 5) == "iPad6" || machine.substr(0, 5) == "iPad7")
468  {
469  return true;
470  }
471 #endif
472  return false;
473 }
474 
475 inline bool CPU_QuerySHA1()
476 {
477 #if defined(__ANDROID__) && defined(__aarch64__)
478  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) &&
479  (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA1))
480  return true;
481 #elif defined(__ANDROID__) && defined(__aarch32__)
482  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) &&
483  (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA1))
484  return true;
485 #elif defined(__linux__) && defined(__aarch64__)
486  if (getauxval(AT_HWCAP) & HWCAP_SHA1)
487  return true;
488 #elif defined(__linux__) && defined(__aarch32__)
489  if (getauxval(AT_HWCAP2) & HWCAP2_SHA1)
490  return true;
491 #elif defined(__APPLE__) && defined(__aarch64__)
492  // http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
493  struct utsname systemInfo;
494  systemInfo.machine[0] = '\0';
495  uname(&systemInfo);
496 
497  // The machine strings below are known ARM8 devices
498  std::string machine(systemInfo.machine);
499  if (machine.substr(0, 7) == "iPhone6" || machine.substr(0, 7) == "iPhone7" ||
500  machine.substr(0, 7) == "iPhone8" || machine.substr(0, 7) == "iPhone9" ||
501  machine.substr(0, 5) == "iPad4" || machine.substr(0, 5) == "iPad5" ||
502  machine.substr(0, 5) == "iPad6" || machine.substr(0, 5) == "iPad7")
503  {
504  return true;
505  }
506 #endif
507  return false;
508 }
509 
510 inline bool CPU_QuerySHA2()
511 {
512 #if defined(__ANDROID__) && defined(__aarch64__)
513  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) &&
514  (android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA2))
515  return true;
516 #elif defined(__ANDROID__) && defined(__aarch32__)
517  if ((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) &&
518  (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA2))
519  return true;
520 #elif defined(__linux__) && defined(__aarch64__)
521  if (getauxval(AT_HWCAP) & HWCAP_SHA2)
522  return true;
523 #elif defined(__linux__) && defined(__aarch32__)
524  if (getauxval(AT_HWCAP2) & HWCAP2_SHA2)
525  return true;
526 #elif defined(__APPLE__) && defined(__aarch64__)
527  // http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
528  struct utsname systemInfo;
529  systemInfo.machine[0] = '\0';
530  uname(&systemInfo);
531 
532  // The machine strings below are known ARM8 devices
533  std::string machine(systemInfo.machine);
534  if (machine.substr(0, 7) == "iPhone6" || machine.substr(0, 7) == "iPhone7" ||
535  machine.substr(0, 7) == "iPhone8" || machine.substr(0, 7) == "iPhone9" ||
536  machine.substr(0, 5) == "iPad4" || machine.substr(0, 5) == "iPad5" ||
537  machine.substr(0, 5) == "iPad6" || machine.substr(0, 5) == "iPad7")
538  {
539  return true;
540  }
541 #endif
542  return false;
543 }
544 
545 void DetectArmFeatures()
546 {
547  // The CPU_ProbeXXX's return false for OSes which
548  // can't tolerate SIGILL-based probes
549  g_hasNEON = CPU_QueryNEON() || CPU_ProbeNEON();
550  g_hasCRC32 = CPU_QueryCRC32() || CPU_ProbeCRC32();
551  g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
552  g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
553  g_hasSHA1 = CPU_QuerySHA1() || CPU_ProbeSHA1();
554  g_hasSHA2 = CPU_QuerySHA2() || CPU_ProbeSHA2();
555 
556 #if defined(__linux__) && defined(_SC_LEVEL1_DCACHE_LINESIZE)
557  g_cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
558 #endif
559 
560  if (!g_cacheLineSize)
561  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
562 
563  *const_cast<volatile bool*>(&g_ArmDetectionDone) = true;
564 }
565 
566 // *************************** PowerPC and PowerPC64 ***************************
567 
568 #elif (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
569 
570 bool CRYPTOPP_SECTION_INIT g_PowerpcDetectionDone = false;
571 bool CRYPTOPP_SECTION_INIT g_hasAltivec = false, CRYPTOPP_SECTION_INIT g_hasPower7 = false, CRYPTOPP_SECTION_INIT g_hasPower8 = false;
572 bool CRYPTOPP_SECTION_INIT g_hasAES = false, CRYPTOPP_SECTION_INIT g_hasSHA256 = false, CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
573 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
574 
575 extern bool CPU_ProbeAltivec();
576 extern bool CPU_ProbePower7();
577 extern bool CPU_ProbePower8();
578 extern bool CPU_ProbeAES();
579 extern bool CPU_ProbeSHA256();
580 extern bool CPU_ProbeSHA512();
581 
582 #ifndef PPC_FEATURE_HAS_ALTIVEC
583 # define PPC_FEATURE_HAS_ALTIVEC 0x10000000
584 #endif
585 #ifndef PPC_FEATURE_ARCH_2_06
586 # define PPC_FEATURE_ARCH_2_06 0x00000100
587 #endif
588 #ifndef PPC_FEATURE2_ARCH_2_07
589 # define PPC_FEATURE2_ARCH_2_07 0x80000000
590 #endif
591 #ifndef PPC_FEATURE2_VEC_CRYPTO
592 # define PPC_FEATURE2_VEC_CRYPTO 0x02000000
593 #endif
594 
595 inline bool CPU_QueryAltivec()
596 {
597 #if defined(__linux__)
598  if (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC)
599  return true;
600 #elif defined(__APPLE__) && defined(__POWERPC__)
601  // http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
602  struct utsname systemInfo;
603  systemInfo.machine[0] = '\0';
604  uname(&systemInfo);
605 
606  // The machine strings below are known PPC machines
607  std::string machine(systemInfo.machine);
608  if (machine.substr(0, 15) == "Power Macintosh")
609  {
610  return true;
611  }
612 #endif
613  return false;
614 }
615 
616 inline bool CPU_QueryPower7()
617 {
618  // Power7 and ISA 2.06
619 #if defined(__linux__)
620  if (getauxval(AT_HWCAP2) & PPC_FEATURE_ARCH_2_06)
621  return true;
622 #endif
623  return false;
624 }
625 
626 inline bool CPU_QueryPower8()
627 {
628  // Power8 and ISA 2.07 provide in-core crypto.
629 #if defined(__linux__)
630  if (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07)
631  return true;
632 #endif
633  return false;
634 }
635 
636 inline bool CPU_QueryAES()
637 {
638  // Power8 and ISA 2.07 provide in-core crypto. Glibc
639  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
640 #if defined(__linux__)
641  if (getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO)
642  return true;
643  //if (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07)
644  // return true;
645 #endif
646  return false;
647 }
648 
649 inline bool CPU_QuerySHA256()
650 {
651  // Power8 and ISA 2.07 provide in-core crypto. Glibc
652  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
653 #if defined(__linux__)
654  if (getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO)
655  return true;
656  //if (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07)
657  // return true;
658 #endif
659  return false;
660 }
661 inline bool CPU_QuerySHA512()
662 {
663  // Power8 and ISA 2.07 provide in-core crypto. Glibc
664  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
665 #if defined(__linux__)
666  if (getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO)
667  return true;
668  //if (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07)
669  // return true;
670 #endif
671  return false;
672 }
673 
674 void DetectPowerpcFeatures()
675 {
676  // The CPU_ProbeXXX's return false for OSes which
677  // can't tolerate SIGILL-based probes, like Apple
678  g_hasAltivec = CPU_QueryAltivec() || CPU_ProbeAltivec();
679  g_hasPower7 = CPU_QueryPower7() || CPU_ProbePower7();
680  g_hasPower8 = CPU_QueryPower8() || CPU_ProbePower8();
681  //g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
682  g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
683  g_hasSHA256 = CPU_QuerySHA256() || CPU_ProbeSHA256();
684  g_hasSHA512 = CPU_QuerySHA512() || CPU_ProbeSHA512();
685 
686 #if defined(_AIX)
687  // /usr/include/sys/systemcfg.h
688  g_cacheLineSize = getsystemcfg(SC_L1C_DLS);
689 #elif defined(__linux__) && defined(_SC_LEVEL1_DCACHE_LINESIZE)
690  // GCC112 CentOS 7 returns 0?
691  g_cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
692 #endif
693 
694  if (g_cacheLineSize <= 0)
695  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
696 
697  *const_cast<volatile bool*>(&g_PowerpcDetectionDone) = true;
698 }
699 
700 #endif
701 NAMESPACE_END
702 
703 // *************************** C++ Static Initialization ***************************
704 
705 ANONYMOUS_NAMESPACE_BEGIN
706 
707 class InitCpu
708 {
709 public:
710  InitCpu()
711  {
712 #if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
713  CryptoPP::DetectX86Features();
714 #elif CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64
715  CryptoPP::DetectArmFeatures();
716 #elif CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64
717  CryptoPP::DetectPowerpcFeatures();
718 #endif
719  }
720 };
721 
722 // This is not really needed because HasSSE() and friends can dynamically initialize.
723 // Everything depends on CPU features so we initialize it once at load time.
724 // Dynamic initialization will be used if init priorities are not available.
725 
726 #if HAVE_GCC_INIT_PRIORITY
727  const InitCpu s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 10))) = InitCpu();
728 #elif HAVE_MSC_INIT_PRIORITY
729  #pragma warning(disable: 4075)
730  #pragma init_seg(".CRT$XCU")
731  const InitCpu s_init;
732  #pragma warning(default: 4075)
733 #else
734  const InitCpu s_init;
735 #endif
736 
737 ANONYMOUS_NAMESPACE_END
738 
739 #endif // CRYPTOPP_IMPORTS
Utility functions for the Crypto++ library.
Library configuration file.
Common C++ header files.
Precompiled header file.
Functions for CPU features and intrinsics.
Crypto++ library namespace.