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