Crypto++ 8.9
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
53unsigned 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)
85extern "C" unsigned long long __fastcall XGETBV64(unsigned int);
86extern "C" unsigned long long __fastcall CPUID64(unsigned int, unsigned int, unsigned int*);
87#endif
88
89#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
90extern "C" {
91 typedef void (*SigHandler)(int);
92}
93
94extern "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
104ANONYMOUS_NAMESPACE_BEGIN
105
106#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
107
108using CryptoPP::word32;
109
110inline 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
118inline 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
130inline 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
138inline 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
155class AppleMachineInfo
156{
157public:
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 {
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
289private:
290 unsigned int m_device, m_version, m_arch;
291};
292
293void 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
307inline 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
318inline 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
329inline 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
340inline 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
353ANONYMOUS_NAMESPACE_END
354
355NAMESPACE_BEGIN(CryptoPP)
356
357// *************************** IA-32 CPUs ***************************
358
359#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
360
361bool CRYPTOPP_SECTION_INIT g_x86DetectionDone = false;
362bool CRYPTOPP_SECTION_INIT g_hasSSE2 = false;
363bool CRYPTOPP_SECTION_INIT g_hasSSSE3 = false;
364bool CRYPTOPP_SECTION_INIT g_hasSSE41 = false;
365bool CRYPTOPP_SECTION_INIT g_hasSSE42 = false;
366bool CRYPTOPP_SECTION_INIT g_hasAESNI = false;
367bool CRYPTOPP_SECTION_INIT g_hasCLMUL = false;
368bool CRYPTOPP_SECTION_INIT g_hasMOVBE = false;
369bool CRYPTOPP_SECTION_INIT g_hasAVX = false;
370bool CRYPTOPP_SECTION_INIT g_hasAVX2 = false;
371bool CRYPTOPP_SECTION_INIT g_hasADX = false;
372bool CRYPTOPP_SECTION_INIT g_hasSHA = false;
373bool CRYPTOPP_SECTION_INIT g_hasRDRAND = false;
374bool CRYPTOPP_SECTION_INIT g_hasRDSEED = false;
375bool CRYPTOPP_SECTION_INIT g_isP4 = false;
376bool CRYPTOPP_SECTION_INIT g_hasPadlockRNG = false;
377bool CRYPTOPP_SECTION_INIT g_hasPadlockACE = false;
378bool CRYPTOPP_SECTION_INIT g_hasPadlockACE2 = false;
379bool CRYPTOPP_SECTION_INIT g_hasPadlockPHE = false;
380bool CRYPTOPP_SECTION_INIT g_hasPadlockPMM = false;
382
383// For Solaris 11
384extern 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.
389word64 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
447bool 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
536void 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
718done:
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
738bool CRYPTOPP_SECTION_INIT g_ArmDetectionDone = false;
739bool CRYPTOPP_SECTION_INIT g_hasARMv7 = false;
740bool CRYPTOPP_SECTION_INIT g_hasNEON = false;
741bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
742bool CRYPTOPP_SECTION_INIT g_hasCRC32 = false;
743bool CRYPTOPP_SECTION_INIT g_hasAES = false;
744bool CRYPTOPP_SECTION_INIT g_hasSHA1 = false;
745bool CRYPTOPP_SECTION_INIT g_hasSHA2 = false;
746bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
747bool CRYPTOPP_SECTION_INIT g_hasSHA3 = false;
748bool CRYPTOPP_SECTION_INIT g_hasSM3 = false;
749bool 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
766extern bool CPU_ProbeARMv7();
767extern bool CPU_ProbeNEON();
768extern bool CPU_ProbeCRC32();
769extern bool CPU_ProbeAES();
770extern bool CPU_ProbeSHA1();
771extern bool CPU_ProbeSHA256();
772extern bool CPU_ProbeSHA512();
773extern bool CPU_ProbeSHA3();
774extern bool CPU_ProbeSM3();
775extern bool CPU_ProbeSM4();
776extern 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
832inline 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
852inline 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
883inline 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
910inline 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
937inline 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
964inline 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
991inline 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
1019inline 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
1050inline 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
1081inline 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
1104inline 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
1126void 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
1164bool CRYPTOPP_SECTION_INIT g_PowerPcDetectionDone = false;
1165bool CRYPTOPP_SECTION_INIT g_hasAltivec = false;
1166bool CRYPTOPP_SECTION_INIT g_hasPower7 = false;
1167bool CRYPTOPP_SECTION_INIT g_hasPower8 = false;
1168bool CRYPTOPP_SECTION_INIT g_hasPower9 = false;
1169bool CRYPTOPP_SECTION_INIT g_hasAES = false;
1170bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
1171bool CRYPTOPP_SECTION_INIT g_hasSHA256 = false;
1172bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
1173bool CRYPTOPP_SECTION_INIT g_hasDARN = false;
1175
1176extern bool CPU_ProbeAltivec();
1177extern bool CPU_ProbePower7();
1178extern bool CPU_ProbePower8();
1179extern bool CPU_ProbePower9();
1180extern bool CPU_ProbeAES();
1181extern bool CPU_ProbePMULL();
1182extern bool CPU_ProbeSHA256();
1183extern bool CPU_ProbeSHA512();
1184extern 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.
1205inline 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
1226inline 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
1244inline 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
1262inline 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
1280inline 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
1299inline 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
1318inline 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}
1336inline 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
1356inline 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
1375void 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
1419NAMESPACE_END
1420
1421// *************************** C++ Static Initialization ***************************
1422
1423ANONYMOUS_NAMESPACE_BEGIN
1424
1425class InitCpu
1426{
1427public:
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
1459ANONYMOUS_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