Crypto++ 8.2
Free C&
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#ifndef AT_HWCAP
34# define AT_HWCAP 16
35#endif
36#ifndef AT_HWCAP2
37# define AT_HWCAP2 26
38#endif
39unsigned long int getauxval(unsigned long int) { return 0; }
40#endif
41
42#if defined(__APPLE__)
43# include <sys/utsname.h>
44#endif
45
46// The cpu-features header and source file are located in
47// "$ANDROID_NDK_ROOT/sources/android/cpufeatures".
48// setenv-android.sh will copy the header and source file
49// into PWD and the makefile will build it in place.
50#if defined(__ANDROID__)
51# include "cpu-features.h"
52#endif
53
54#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
55# include <signal.h>
56# include <setjmp.h>
57#endif
58
59// Visual Studio 2008 and below is missing _xgetbv. See x64dll.asm for the body.
60#if defined(_MSC_VER) && _MSC_VER <= 1500 && defined(_M_X64)
61extern "C" unsigned long long __fastcall ExtendedControlRegister(unsigned int);
62#endif
63
64ANONYMOUS_NAMESPACE_BEGIN
65
66#if defined(__APPLE__)
67enum {PowerMac=1, Mac, iPhone, iPod, iPad, AppleTV, AppleWatch};
68void GetAppleMachineInfo(unsigned int& device, unsigned int& version)
69{
70 device = version = 0;
71
72 struct utsname systemInfo;
73 systemInfo.machine[0] = '\0';
74 uname(&systemInfo);
75
76 std::string machine(systemInfo.machine);
77 if (machine.find("PowerMac") != std::string::npos ||
78 machine.find("Power Macintosh") != std::string::npos)
79 device = PowerMac;
80 else if (machine.find("Mac") != std::string::npos ||
81 machine.find("Macintosh") != std::string::npos)
82 device = Mac;
83 else if (machine.find("iPhone") != std::string::npos)
84 device = iPhone;
85 else if (machine.find("iPod") != std::string::npos)
86 device = iPod;
87 else if (machine.find("iPad") != std::string::npos)
88 device = iPad;
89 else if (machine.find("AppleTV") != std::string::npos)
90 device = AppleTV;
91 else if (machine.find("AppleWatch") != std::string::npos)
92 device = AppleWatch;
93
94 std::string::size_type pos = machine.find_first_of("0123456789");
95 if (pos != std::string::npos)
96 version = std::atoi(machine.substr(pos).c_str());
97}
98
99// http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
100bool IsAppleMachineARMv8(unsigned int device, unsigned int version)
101{
102 if ((device == iPhone && version >= 6) ||
103 (device == iPad && version >= 4))
104 {
105 return true;
106 }
107 return false;
108}
109
110bool IsAppleMachineARMv84(unsigned int device, unsigned int version)
111{
112 return false;
113}
114#endif // __APPLE__
115
116ANONYMOUS_NAMESPACE_END
117
118NAMESPACE_BEGIN(CryptoPP)
119
120#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
121extern "C" {
122 typedef void (*SigHandler)(int);
123}
124
125extern "C"
126{
127 static jmp_buf s_jmpNoCPUID;
128 static void SigIllHandlerCPUID(int unused)
129 {
130 CRYPTOPP_UNUSED(unused);
131 longjmp(s_jmpNoCPUID, 1);
132 }
133}
134#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
135
136// *************************** IA-32 CPUs ***************************
137
138#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
139
140extern bool CPU_ProbeSSE2();
141
142#if _MSC_VER >= 1600
143
144inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
145{
146 __cpuidex((int *)output, func, subfunc);
147 return true;
148}
149
150#elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
151
152inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
153{
154 if (subfunc != 0)
155 return false;
156
157 __cpuid((int *)output, func);
158 return true;
159}
160
161#else
162
163// Borland/Embarcadero and Issue 498
164// cpu.cpp (131): E2211 Inline assembly not allowed in inline and template functions
165bool CpuId(word32 func, word32 subfunc, word32 output[4])
166{
167#if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) || defined(__BORLANDC__)
168 __try
169 {
170 // Borland/Embarcadero and Issue 500
171 // Local variables for cpuid output
172 word32 a, b, c, d;
173 __asm
174 {
175 mov eax, func
176 mov ecx, subfunc
177 cpuid
178 mov [a], eax
179 mov [b], ebx
180 mov [c], ecx
181 mov [d], edx
182 }
183 output[0] = a;
184 output[1] = b;
185 output[2] = c;
186 output[3] = d;
187 }
188 // GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION
189 __except (EXCEPTION_EXECUTE_HANDLER)
190 {
191 return false;
192 }
193
194 // func = 0 returns the highest basic function understood in EAX. If the CPU does
195 // not return non-0, then it is mostly useless. The code below converts basic
196 // function value to a true/false return value.
197 if(func == 0)
198 return output[0] != 0;
199
200 return true;
201#else
202 // longjmp and clobber warnings. Volatile is required.
203 // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
204 volatile bool result = true;
205
206 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
207 if (oldHandler == SIG_ERR)
208 return false;
209
210# ifndef __MINGW32__
211 volatile sigset_t oldMask;
212 if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask) != 0)
213 return false;
214# endif
215
216 if (setjmp(s_jmpNoCPUID))
217 result = false;
218 else
219 {
220 asm volatile
221 (
222 // save ebx in case -fPIC is being used
223 // TODO: this might need an early clobber on EDI.
224# if CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
225 "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
226# else
227 "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
228# endif
229 : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
230 : "a" (func), "c" (subfunc)
231 : "cc"
232 );
233 }
234
235# ifndef __MINGW32__
236 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
237# endif
238
239 signal(SIGILL, oldHandler);
240 return result;
241#endif
242}
243
244#endif
245
246bool CRYPTOPP_SECTION_INIT g_x86DetectionDone = false;
247bool CRYPTOPP_SECTION_INIT g_hasSSE2 = false;
248bool CRYPTOPP_SECTION_INIT g_hasSSSE3 = false;
249bool CRYPTOPP_SECTION_INIT g_hasSSE41 = false;
250bool CRYPTOPP_SECTION_INIT g_hasSSE42 = false;
251bool CRYPTOPP_SECTION_INIT g_hasAVX = false;
252bool CRYPTOPP_SECTION_INIT g_hasAVX2 = false;
253bool CRYPTOPP_SECTION_INIT g_hasAESNI = false;
254bool CRYPTOPP_SECTION_INIT g_hasCLMUL = false;
255bool CRYPTOPP_SECTION_INIT g_hasADX = false;
256bool CRYPTOPP_SECTION_INIT g_hasSHA = false;
257bool CRYPTOPP_SECTION_INIT g_hasRDRAND = false;
258bool CRYPTOPP_SECTION_INIT g_hasRDSEED = false;
259bool CRYPTOPP_SECTION_INIT g_isP4 = false;
260bool CRYPTOPP_SECTION_INIT g_hasPadlockRNG = false;
261bool CRYPTOPP_SECTION_INIT g_hasPadlockACE = false;
262bool CRYPTOPP_SECTION_INIT g_hasPadlockACE2 = false;
263bool CRYPTOPP_SECTION_INIT g_hasPadlockPHE = false;
264bool CRYPTOPP_SECTION_INIT g_hasPadlockPMM = false;
265word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
266
267static inline bool IsIntel(const word32 output[4])
268{
269 // This is the "GenuineIntel" string
270 return (output[1] /*EBX*/ == 0x756e6547) &&
271 (output[2] /*ECX*/ == 0x6c65746e) &&
272 (output[3] /*EDX*/ == 0x49656e69);
273}
274
275static inline bool IsAMD(const word32 output[4])
276{
277 // This is the "AuthenticAMD" string. Some early K5's can return "AMDisbetter!"
278 return (output[1] /*EBX*/ == 0x68747541) &&
279 (output[2] /*ECX*/ == 0x444D4163) &&
280 (output[3] /*EDX*/ == 0x69746E65);
281}
282
283static inline bool IsHygon(const word32 output[4])
284{
285 // This is the "HygonGenuine" string.
286 return (output[1] /*EBX*/ == 0x6f677948) &&
287 (output[2] /*ECX*/ == 0x656e6975) &&
288 (output[3] /*EDX*/ == 0x6e65476e);
289}
290
291static inline bool IsVIA(const word32 output[4])
292{
293 // This is the "CentaurHauls" string. Some non-PadLock's can return "VIA VIA VIA "
294 return (output[1] /*EBX*/ == 0x746e6543) &&
295 (output[2] /*ECX*/ == 0x736c7561) &&
296 (output[3] /*EDX*/ == 0x48727561);
297}
298
299void DetectX86Features()
300{
301 // Coverity finding CID 171239...
302 word32 cpuid0[4]={0}, cpuid1[4]={0}, cpuid2[4]={0};
303 if (!CpuId(0, 0, cpuid0))
304 return;
305 if (!CpuId(1, 0, cpuid1))
306 return;
307
308 // cpuid1[2] & (1 << 27) is XSAVE/XRESTORE and signals OS support for SSE; use it to avoid probes.
309 // See http://github.com/weidai11/cryptopp/issues/511 and http://stackoverflow.com/a/22521619/608639
310 if ((cpuid1[3] & (1 << 26)) != 0)
311 g_hasSSE2 = ((cpuid1[2] & (1 << 27)) != 0) || CPU_ProbeSSE2();
312
313 g_hasSSSE3 = g_hasSSE2 && ((cpuid1[2] & (1<< 9)) != 0);
314 g_hasSSE41 = g_hasSSE2 && ((cpuid1[2] & (1<<19)) != 0);
315 g_hasSSE42 = g_hasSSE2 && ((cpuid1[2] & (1<<20)) != 0);
316 g_hasAESNI = g_hasSSE2 && ((cpuid1[2] & (1<<25)) != 0);
317 g_hasCLMUL = g_hasSSE2 && ((cpuid1[2] & (1<< 1)) != 0);
318
319 // AVX is similar to SSE, but check both bits 27 (SSE) and 28 (AVX).
320 // https://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
321 CRYPTOPP_CONSTANT(YMM_FLAG = (3 << 1))
322 CRYPTOPP_CONSTANT(AVX_FLAG = (3 << 27))
323 if ((cpuid1[2] & AVX_FLAG) == AVX_FLAG)
324 {
325
326// Unable to perform the necessary tests
327#if defined(CRYPTOPP_DISABLE_ASM)
328 g_hasAVX = false;
329
330// GCC 4.1/Binutils 2.17 cannot consume xgetbv
331#elif defined(__GNUC__) || (__SUNPRO_CC >= 0x5100) || defined(__BORLANDC__)
332 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71659 and
333 // http://www.agner.org/optimize/vectorclass/read.php?i=65
334 word32 a=0, d=0;
335 __asm __volatile
336 (
337 // "xgetbv" : "=a"(a), "=d"(d) : "c"(0) :
338 ".byte 0x0f, 0x01, 0xd0" "\n\t"
339 : "=a"(a), "=d"(d) : "c"(0) : "cc"
340 );
341 word64 xcr0 = a | static_cast<word64>(d) << 32;
342 g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
343
344// Visual Studio 2010 and below lack xgetbv
345#elif defined(_MSC_VER) && _MSC_VER <= 1600 && defined(_M_IX86)
346 word32 a=0, d=0;
347 __asm {
348 push eax
349 push edx
350 push ecx
351 mov ecx, 0
352 _emit 0x0f
353 _emit 0x01
354 _emit 0xd0
355 mov a, eax
356 mov d, edx
357 pop ecx
358 pop edx
359 pop eax
360 }
361 word64 xcr0 = a | static_cast<word64>(d) << 32;
362 g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
363
364// Visual Studio 2008 and below lack xgetbv
365#elif defined(_MSC_VER) && _MSC_VER <= 1500 && defined(_M_X64)
366 word64 xcr0 = ExtendedControlRegister(0);
367 g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
368
369// Downlevel SunCC
370#elif defined(__SUNPRO_CC)
371 g_hasAVX = false;
372
373// _xgetbv is available
374#else
375 word64 xcr0 = _xgetbv(0);
376 g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
377#endif
378 }
379
380 if (IsIntel(cpuid0))
381 {
382 CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30))
383 CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18))
384 CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19))
385 CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29))
386 CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5))
387
388 g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
389 g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
390 g_hasRDRAND = (cpuid1[2] /*ECX*/ & RDRAND_FLAG) != 0;
391
392 if (cpuid0[0] /*EAX*/ >= 7)
393 {
394 if (CpuId(7, 0, cpuid2))
395 {
396 g_hasRDSEED = (cpuid2[1] /*EBX*/ & RDSEED_FLAG) != 0;
397 g_hasADX = (cpuid2[1] /*EBX*/ & ADX_FLAG) != 0;
398 g_hasSHA = (cpuid2[1] /*EBX*/ & SHA_FLAG) != 0;
399 g_hasAVX2 = (cpuid2[1] /*EBX*/ & AVX2_FLAG) != 0;
400 }
401 }
402 }
403 else if (IsAMD(cpuid0) || IsHygon(cpuid0))
404 {
405 CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30))
406 CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18))
407 CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19))
408 CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29))
409 CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5))
410
411 CpuId(0x80000005, 0, cpuid2);
412 g_cacheLineSize = GETBYTE(cpuid2[2], 0);
413 g_hasRDRAND = (cpuid1[2] /*ECX*/ & RDRAND_FLAG) != 0;
414
415 if (cpuid0[0] /*EAX*/ >= 7)
416 {
417 if (CpuId(7, 0, cpuid2))
418 {
419 g_hasRDSEED = (cpuid2[1] /*EBX*/ & RDSEED_FLAG) != 0;
420 g_hasADX = (cpuid2[1] /*EBX*/ & ADX_FLAG) != 0;
421 g_hasSHA = (cpuid2[1] /*EBX*/ & SHA_FLAG) != 0;
422 g_hasAVX2 = (cpuid2[1] /*EBX*/ & AVX2_FLAG) != 0;
423 }
424 }
425 }
426 else if (IsVIA(cpuid0))
427 {
428 CRYPTOPP_CONSTANT( RNG_FLAGS = (0x3 << 2))
429 CRYPTOPP_CONSTANT( ACE_FLAGS = (0x3 << 6))
430 CRYPTOPP_CONSTANT(ACE2_FLAGS = (0x3 << 8))
431 CRYPTOPP_CONSTANT( PHE_FLAGS = (0x3 << 10))
432 CRYPTOPP_CONSTANT( PMM_FLAGS = (0x3 << 12))
433
434 CpuId(0xC0000000, 0, cpuid2);
435 if (cpuid2[0] >= 0xC0000001)
436 {
437 // Extended features available
438 CpuId(0xC0000001, 0, cpuid2);
439 g_hasPadlockRNG = (cpuid2[3] /*EDX*/ & RNG_FLAGS) == RNG_FLAGS;
440 g_hasPadlockACE = (cpuid2[3] /*EDX*/ & ACE_FLAGS) == ACE_FLAGS;
441 g_hasPadlockACE2 = (cpuid2[3] /*EDX*/ & ACE2_FLAGS) == ACE2_FLAGS;
442 g_hasPadlockPHE = (cpuid2[3] /*EDX*/ & PHE_FLAGS) == PHE_FLAGS;
443 g_hasPadlockPMM = (cpuid2[3] /*EDX*/ & PMM_FLAGS) == PMM_FLAGS;
444 }
445 }
446
447 if (g_cacheLineSize == 0)
448 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
449
450 *const_cast<volatile bool*>(&g_x86DetectionDone) = true;
451}
452
453// *************************** ARM-32, Aarch32 and Aarch64 ***************************
454
455#elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8)
456
457bool CRYPTOPP_SECTION_INIT g_ArmDetectionDone = false;
458bool CRYPTOPP_SECTION_INIT g_hasARMv7 = false;
459bool CRYPTOPP_SECTION_INIT g_hasNEON = false;
460bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
461bool CRYPTOPP_SECTION_INIT g_hasCRC32 = false;
462bool CRYPTOPP_SECTION_INIT g_hasAES = false;
463bool CRYPTOPP_SECTION_INIT g_hasSHA1 = false;
464bool CRYPTOPP_SECTION_INIT g_hasSHA2 = false;
465bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
466bool CRYPTOPP_SECTION_INIT g_hasSHA3 = false;
467bool CRYPTOPP_SECTION_INIT g_hasSM3 = false;
468bool CRYPTOPP_SECTION_INIT g_hasSM4 = false;
469word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
470
471// ARM does not have an unprivliged equivalent to CPUID on IA-32. We have to jump through some
472// hoops to detect features on a wide array of platforms. Our strategy is two part. First,
473// attempt to *Query* the OS for a feature, like using getauxval on Linux. If that fails,
474// then *Probe* the cpu executing an instruction and an observe a SIGILL if unsupported.
475// The probes are in source files where compilation options like -march=armv8-a+crc make
476// intrinsics available. They are expensive when compared to a standard OS feature query.
477// Always perform the feature quesry first. For Linux see
478// http://sourceware.org/ml/libc-help/2017-08/msg00012.html
479// Avoid probes on Apple platforms because Apple's signal handling for SIGILLs appears broken.
480// We are trying to figure out a way to feature test without probes. Also see
481// http://stackoverflow.com/a/11197770/608639 and
482// http://gist.github.com/erkanyildiz/390a480f27e86f8cd6ba
483
484extern bool CPU_ProbeARMv7();
485extern bool CPU_ProbeNEON();
486extern bool CPU_ProbeCRC32();
487extern bool CPU_ProbeAES();
488extern bool CPU_ProbeSHA1();
489extern bool CPU_ProbeSHA2();
490extern bool CPU_ProbeSHA512();
491extern bool CPU_ProbeSHA3();
492extern bool CPU_ProbeSM3();
493extern bool CPU_ProbeSM4();
494extern bool CPU_ProbePMULL();
495
496// https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
497#ifndef HWCAP_ARMv7
498# define HWCAP_ARMv7 (1 << 29)
499#endif
500#ifndef HWCAP_ASIMD
501# define HWCAP_ASIMD (1 << 1)
502#endif
503#ifndef HWCAP_ARM_NEON
504# define HWCAP_ARM_NEON 4096
505#endif
506#ifndef HWCAP_CRC32
507# define HWCAP_CRC32 (1 << 7)
508#endif
509#ifndef HWCAP2_CRC32
510# define HWCAP2_CRC32 (1 << 4)
511#endif
512#ifndef HWCAP_PMULL
513# define HWCAP_PMULL (1 << 4)
514#endif
515#ifndef HWCAP2_PMULL
516# define HWCAP2_PMULL (1 << 1)
517#endif
518#ifndef HWCAP_AES
519# define HWCAP_AES (1 << 3)
520#endif
521#ifndef HWCAP2_AES
522# define HWCAP2_AES (1 << 0)
523#endif
524#ifndef HWCAP_SHA1
525# define HWCAP_SHA1 (1 << 5)
526#endif
527#ifndef HWCAP_SHA2
528# define HWCAP_SHA2 (1 << 6)
529#endif
530#ifndef HWCAP2_SHA1
531# define HWCAP2_SHA1 (1 << 2)
532#endif
533#ifndef HWCAP2_SHA2
534# define HWCAP2_SHA2 (1 << 3)
535#endif
536#ifndef HWCAP_SHA3
537# define HWCAP_SHA3 (1 << 17)
538#endif
539#ifndef HWCAP_SM3
540# define HWCAP_SM3 (1 << 18)
541#endif
542#ifndef HWCAP_SM4
543# define HWCAP_SM4 (1 << 19)
544#endif
545#ifndef HWCAP_SHA512
546# define HWCAP_SHA512 (1 << 21)
547#endif
548
549inline bool CPU_QueryARMv7()
550{
551#if defined(__aarch32__) || defined(__aarch64__)
552 // ARMv7 or above
553 return true;
554#elif defined(__ANDROID__) && defined(__arm__)
555 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
556 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0))
557 return true;
558#elif defined(__linux__) && defined(__arm__)
559 if ((getauxval(AT_HWCAP) & HWCAP_ARMv7) != 0)
560 return true;
561#elif defined(__APPLE__) && defined(__arm__)
562 // Apple hardware is ARMv7 or above.
563 return true;
564#endif
565 return false;
566}
567
568inline bool CPU_QueryNEON()
569{
570#if defined(__ANDROID__) && defined(__aarch64__)
571 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
572 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_ASIMD) != 0))
573 return true;
574#elif defined(__ANDROID__) && defined(__arm__)
575 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
576 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0))
577 return true;
578#elif defined(__linux__) && defined(__aarch64__)
579 if ((getauxval(AT_HWCAP) & HWCAP_ASIMD) != 0)
580 return true;
581#elif defined(__linux__) && defined(__aarch32__)
582 if ((getauxval(AT_HWCAP2) & HWCAP2_ASIMD) != 0)
583 return true;
584#elif defined(__linux__) && defined(__arm__)
585 if ((getauxval(AT_HWCAP) & HWCAP_ARM_NEON) != 0)
586 return true;
587#elif defined(__APPLE__) && defined(__aarch64__)
588 // Core feature set for Aarch32 and Aarch64.
589 return true;
590#endif
591 return false;
592}
593
594inline bool CPU_QueryCRC32()
595{
596#if defined(__ANDROID__) && defined(__aarch64__)
597 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
598 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_CRC32) != 0))
599 return true;
600#elif defined(__ANDROID__) && defined(__aarch32__)
601 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
602 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_CRC32) != 0))
603 return true;
604#elif defined(__linux__) && defined(__aarch64__)
605 if ((getauxval(AT_HWCAP) & HWCAP_CRC32) != 0)
606 return true;
607#elif defined(__linux__) && defined(__aarch32__)
608 if ((getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0)
609 return true;
610#elif defined(__APPLE__) && defined(__aarch64__)
611 // No compiler support. CRC intrinsics result in a failed compiled.
612 return false;
613#endif
614 return false;
615}
616
617inline bool CPU_QueryPMULL()
618{
619#if defined(__ANDROID__) && defined(__aarch64__)
620 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
621 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_PMULL) != 0))
622 return true;
623#elif defined(__ANDROID__) && defined(__aarch32__)
624 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
625 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_PMULL) != 0))
626 return true;
627#elif defined(__linux__) && defined(__aarch64__)
628 if ((getauxval(AT_HWCAP) & HWCAP_PMULL) != 0)
629 return true;
630#elif defined(__linux__) && defined(__aarch32__)
631 if ((getauxval(AT_HWCAP2) & HWCAP2_PMULL) != 0)
632 return true;
633#elif defined(__APPLE__) && defined(__aarch64__)
634 // No compiler support. PMULL intrinsics result in a failed compiled.
635 return false;
636#endif
637 return false;
638}
639
640inline bool CPU_QueryAES()
641{
642#if defined(__ANDROID__) && defined(__aarch64__)
643 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
644 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES) != 0))
645 return true;
646#elif defined(__ANDROID__) && defined(__aarch32__)
647 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
648 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES) != 0))
649 return true;
650#elif defined(__linux__) && defined(__aarch64__)
651 if ((getauxval(AT_HWCAP) & HWCAP_AES) != 0)
652 return true;
653#elif defined(__linux__) && defined(__aarch32__)
654 if ((getauxval(AT_HWCAP2) & HWCAP2_AES) != 0)
655 return true;
656#elif defined(__APPLE__) && defined(__aarch64__)
657 unsigned int device, version;
658 GetAppleMachineInfo(device, version);
659 return IsAppleMachineARMv8(device, version);
660#endif
661 return false;
662}
663
664inline bool CPU_QuerySHA1()
665{
666#if defined(__ANDROID__) && defined(__aarch64__)
667 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
668 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA1) != 0))
669 return true;
670#elif defined(__ANDROID__) && defined(__aarch32__)
671 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
672 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA1) != 0))
673 return true;
674#elif defined(__linux__) && defined(__aarch64__)
675 if ((getauxval(AT_HWCAP) & HWCAP_SHA1) != 0)
676 return true;
677#elif defined(__linux__) && defined(__aarch32__)
678 if ((getauxval(AT_HWCAP2) & HWCAP2_SHA1) != 0)
679 return true;
680#elif defined(__APPLE__) && defined(__aarch64__)
681 unsigned int device, version;
682 GetAppleMachineInfo(device, version);
683 return IsAppleMachineARMv8(device, version);
684#endif
685 return false;
686}
687
688inline bool CPU_QuerySHA2()
689{
690#if defined(__ANDROID__) && defined(__aarch64__)
691 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
692 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA2) != 0))
693 return true;
694#elif defined(__ANDROID__) && defined(__aarch32__)
695 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
696 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA2) != 0))
697 return true;
698#elif defined(__linux__) && defined(__aarch64__)
699 if ((getauxval(AT_HWCAP) & HWCAP_SHA2) != 0)
700 return true;
701#elif defined(__linux__) && defined(__aarch32__)
702 if ((getauxval(AT_HWCAP2) & HWCAP2_SHA2) != 0)
703 return true;
704#elif defined(__APPLE__) && defined(__aarch64__)
705 unsigned int device, version;
706 GetAppleMachineInfo(device, version);
707 return IsAppleMachineARMv8(device, version);
708#endif
709 return false;
710}
711
712inline bool CPU_QuerySHA512()
713{
714// Some ARMv8.4 features are disabled at the moment
715#if defined(__ANDROID__) && defined(__aarch64__) && 0
716 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
717 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA512) != 0))
718 return true;
719#elif defined(__ANDROID__) && defined(__aarch32__) && 0
720 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
721 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA512) != 0))
722 return true;
723#elif defined(__linux__) && defined(__aarch64__)
724 if ((getauxval(AT_HWCAP) & HWCAP_SHA512) != 0)
725 return true;
726#elif defined(__linux__) && defined(__aarch32__)
727 if ((getauxval(AT_HWCAP2) & HWCAP2_SHA512) != 0)
728 return true;
729#elif defined(__APPLE__) && defined(__aarch64__) && 0
730 unsigned int device, version;
731 GetAppleMachineInfo(device, version);
732 return IsAppleMachineARMv84(device, version);
733#endif
734 return false;
735}
736
737inline bool CPU_QuerySHA3()
738{
739// Some ARMv8.4 features are disabled at the moment
740#if defined(__ANDROID__) && defined(__aarch64__) && 0
741 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
742 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA3) != 0))
743 return true;
744#elif defined(__ANDROID__) && defined(__aarch32__) && 0
745 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
746 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA3) != 0))
747 return true;
748#elif defined(__linux__) && defined(__aarch64__)
749 if ((getauxval(AT_HWCAP) & HWCAP_SHA3) != 0)
750 return true;
751#elif defined(__linux__) && defined(__aarch32__)
752 if ((getauxval(AT_HWCAP2) & HWCAP2_SHA3) != 0)
753 return true;
754#elif defined(__APPLE__) && defined(__aarch64__) && 0
755 unsigned int device, version;
756 GetAppleMachineInfo(device, version);
757 return IsAppleMachineARMv84(device, version);
758#endif
759 return false;
760}
761
762inline bool CPU_QuerySM3()
763{
764// Some ARMv8.4 features are disabled at the moment
765#if defined(__ANDROID__) && defined(__aarch64__) && 0
766 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
767 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM3) != 0))
768 return true;
769#elif defined(__ANDROID__) && defined(__aarch32__) && 0
770 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
771 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM3) != 0))
772 return true;
773#elif defined(__linux__) && defined(__aarch64__)
774 if ((getauxval(AT_HWCAP) & HWCAP_SM3) != 0)
775 return true;
776#elif defined(__linux__) && defined(__aarch32__)
777 if ((getauxval(AT_HWCAP2) & HWCAP2_SM3) != 0)
778 return true;
779#elif defined(__APPLE__) && defined(__aarch64__) && 0
780 unsigned int device, version;
781 GetAppleMachineInfo(device, version);
782 return IsAppleMachineARMv84(device, version);
783#endif
784 return false;
785}
786
787inline bool CPU_QuerySM4()
788{
789// Some ARMv8.4 features are disabled at the moment
790#if defined(__ANDROID__) && defined(__aarch64__) && 0
791 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
792 ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM4) != 0))
793 return true;
794#elif defined(__ANDROID__) && defined(__aarch32__) && 0
795 if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
796 ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM4) != 0))
797 return true;
798#elif defined(__linux__) && defined(__aarch64__)
799 if ((getauxval(AT_HWCAP) & HWCAP_SM4) != 0)
800 return true;
801#elif defined(__linux__) && defined(__aarch32__)
802 if ((getauxval(AT_HWCAP2) & HWCAP2_SM4) != 0)
803 return true;
804#elif defined(__APPLE__) && defined(__aarch64__) && 0
805 unsigned int device, version;
806 GetAppleMachineInfo(device, version);
807 return IsAppleMachineARMv84(device, version);
808#endif
809 return false;
810}
811
812void DetectArmFeatures()
813{
814 // The CPU_ProbeXXX's return false for OSes which
815 // can't tolerate SIGILL-based probes
816 g_hasARMv7 = CPU_QueryARMv7() || CPU_ProbeARMv7();
817 g_hasNEON = CPU_QueryNEON() || CPU_ProbeNEON();
818 g_hasCRC32 = CPU_QueryCRC32() || CPU_ProbeCRC32();
819 g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
820 g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
821 g_hasSHA1 = CPU_QuerySHA1() || CPU_ProbeSHA1();
822 g_hasSHA2 = CPU_QuerySHA2() || CPU_ProbeSHA2();
823 g_hasSHA512 = CPU_QuerySHA512(); // || CPU_ProbeSHA512();
824 g_hasSHA3 = CPU_QuerySHA3(); // || CPU_ProbeSHA3();
825 g_hasSM3 = CPU_QuerySM3(); // || CPU_ProbeSM3();
826 g_hasSM4 = CPU_QuerySM4(); // || CPU_ProbeSM4();
827
828#if defined(__linux__) && defined(_SC_LEVEL1_DCACHE_LINESIZE)
829 // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
830 // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
831 int cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
832 if (cacheLineSize > 0)
833 g_cacheLineSize = cacheLineSize;
834#endif
835
836 *const_cast<volatile bool*>(&g_ArmDetectionDone) = true;
837}
838
839// *************************** PowerPC and PowerPC64 ***************************
840
841#elif (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
842
843bool CRYPTOPP_SECTION_INIT g_PowerpcDetectionDone = false;
844bool CRYPTOPP_SECTION_INIT g_hasAltivec = false;
845bool CRYPTOPP_SECTION_INIT g_hasPower7 = false;
846bool CRYPTOPP_SECTION_INIT g_hasPower8 = false;
847bool CRYPTOPP_SECTION_INIT g_hasPower9 = false;
848bool CRYPTOPP_SECTION_INIT g_hasAES = false;
849bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
850bool CRYPTOPP_SECTION_INIT g_hasSHA256 = false;
851bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
852bool CRYPTOPP_SECTION_INIT g_hasDARN = false;
853word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
854
855extern bool CPU_ProbeAltivec();
856extern bool CPU_ProbePower7();
857extern bool CPU_ProbePower8();
858extern bool CPU_ProbePower9();
859extern bool CPU_ProbeAES();
860extern bool CPU_ProbePMULL();
861extern bool CPU_ProbeSHA256();
862extern bool CPU_ProbeSHA512();
863extern bool CPU_ProbeDARN();
864
865// Linux define values from 64-Bit ELF V2 ABI Specification.
866// http://openpowerfoundation.org/wp-content/uploads/resources/leabi/content/ch_preface.html
867#ifndef PPC_FEATURE_HAS_ALTIVEC
868# define PPC_FEATURE_HAS_ALTIVEC 0x10000000
869#endif
870#ifndef PPC_FEATURE_ARCH_2_06
871# define PPC_FEATURE_ARCH_2_06 0x00000100
872#endif
873#ifndef PPC_FEATURE2_ARCH_2_07
874# define PPC_FEATURE2_ARCH_2_07 0x80000000
875#endif
876#ifndef PPC_FEATURE2_ARCH_3_00
877# define PPC_FEATURE2_ARCH_3_00 0x00800000
878#endif
879#ifndef PPC_FEATURE2_VEC_CRYPTO
880# define PPC_FEATURE2_VEC_CRYPTO 0x02000000
881#endif
882
883// AIX defines. We used to just call __power_7_andup()
884// and friends but at Power9, too many compilers were
885// missing __power_9_andup(). Instead we switched to
886// a pattern similar to OpenSSL caps testing.
887#ifndef __power_6_andup
888# define __power_6_andup() __power_set(0xffffffffU<<14)
889#endif
890#ifndef __power_7_andup
891# define __power_7_andup() __power_set(0xffffffffU<<15)
892#endif
893#ifndef __power_8_andup
894# define __power_8_andup() __power_set(0xffffffffU<<16)
895#endif
896#ifndef __power_9_andup
897# define __power_9_andup() __power_set(0xffffffffU<<17)
898#endif
899
900// AIX first supported Altivec at Power6, though it
901// was available much earlier for other vendors.
902inline bool CPU_QueryAltivec()
903{
904#if defined(__linux__)
905 if ((getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC) != 0)
906 return true;
907#elif defined(_AIX)
908 if (__power_6_andup() != 0)
909 return true;
910#elif defined(__APPLE__) && defined(__POWERPC__)
911 unsigned int device, version;
912 GetAppleMachineInfo(device, version);
913 return device == PowerMac;
914#endif
915 return false;
916}
917
918inline bool CPU_QueryPower7()
919{
920 // Power7 and ISA 2.06
921#if defined(__linux__)
922 if ((getauxval(AT_HWCAP) & PPC_FEATURE_ARCH_2_06) != 0)
923 return true;
924#elif defined(_AIX)
925 if (__power_7_andup() != 0)
926 return true;
927#endif
928 return false;
929}
930
931inline bool CPU_QueryPower8()
932{
933 // Power8 and ISA 2.07 provide in-core crypto.
934#if defined(__linux__)
935 if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07) != 0)
936 return true;
937#elif defined(_AIX)
938 if (__power_8_andup() != 0)
939 return true;
940#endif
941 return false;
942}
943
944inline bool CPU_QueryPower9()
945{
946 // Power9 and ISA 3.0.
947#if defined(__linux__)
948 if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
949 return true;
950#elif defined(_AIX)
951 if (__power_9_andup() != 0)
952 return true;
953#endif
954 return false;
955}
956
957inline bool CPU_QueryAES()
958{
959 // Power8 and ISA 2.07 provide in-core crypto. Glibc
960 // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
961#if defined(__linux__)
962 if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
963 return true;
964#elif defined(_AIX)
965 if (__power_8_andup() != 0)
966 return true;
967#endif
968 return false;
969}
970
971inline bool CPU_QueryPMULL()
972{
973 // Power8 and ISA 2.07 provide in-core crypto. Glibc
974 // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
975#if defined(__linux__)
976 if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
977 return true;
978#elif defined(_AIX)
979 if (__power_8_andup() != 0)
980 return true;
981#endif
982 return false;
983}
984
985inline bool CPU_QuerySHA256()
986{
987 // Power8 and ISA 2.07 provide in-core crypto. Glibc
988 // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
989#if defined(__linux__)
990 if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
991 return true;
992#elif defined(_AIX)
993 if (__power_8_andup() != 0)
994 return true;
995#endif
996 return false;
997}
998inline bool CPU_QuerySHA512()
999{
1000 // Power8 and ISA 2.07 provide in-core crypto. Glibc
1001 // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1002#if defined(__linux__)
1003 if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1004 return true;
1005#elif defined(_AIX)
1006 if (__power_8_andup() != 0)
1007 return true;
1008#endif
1009 return false;
1010}
1011
1012// Power9 random number generator
1013inline bool CPU_QueryDARN()
1014{
1015 // Power9 and ISA 3.0 provide DARN.
1016#if defined(__linux__)
1017 if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
1018 return true;
1019#elif defined(_AIX)
1020 if (__power_9_andup() != 0)
1021 return true;
1022#endif
1023 return false;
1024}
1025
1026void DetectPowerpcFeatures()
1027{
1028 // The CPU_ProbeXXX's return false for OSes which
1029 // can't tolerate SIGILL-based probes, like Apple
1030 g_hasAltivec = CPU_QueryAltivec() || CPU_ProbeAltivec();
1031 g_hasPower7 = CPU_QueryPower7() || CPU_ProbePower7();
1032 g_hasPower8 = CPU_QueryPower8() || CPU_ProbePower8();
1033 g_hasPower9 = CPU_QueryPower9() || CPU_ProbePower9();
1034 g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
1035 g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
1036 g_hasSHA256 = CPU_QuerySHA256() || CPU_ProbeSHA256();
1037 g_hasSHA512 = CPU_QuerySHA512() || CPU_ProbeSHA512();
1038 g_hasDARN = CPU_QueryDARN() || CPU_ProbeDARN();
1039
1040#if defined(_AIX) && defined(SC_L1C_DLS)
1041 // /usr/include/sys/systemcfg.h
1042 int cacheLineSize = getsystemcfg(SC_L1C_DLS);
1043 if (cacheLineSize > 0)
1044 g_cacheLineSize = cacheLineSize;
1045#elif defined(__linux__) && defined(_SC_LEVEL1_DCACHE_LINESIZE)
1046 // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
1047 // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
1048 int cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
1049 if (cacheLineSize > 0)
1050 g_cacheLineSize = cacheLineSize;
1051#endif
1052
1053 *const_cast<volatile bool*>(&g_PowerpcDetectionDone) = true;
1054}
1055
1056#endif
1057NAMESPACE_END
1058
1059// *************************** C++ Static Initialization ***************************
1060
1061ANONYMOUS_NAMESPACE_BEGIN
1062
1063class InitCpu
1064{
1065public:
1066 InitCpu()
1067 {
1068#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
1069 CryptoPP::DetectX86Features();
1070#elif CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8
1071 CryptoPP::DetectArmFeatures();
1072#elif CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64
1073 CryptoPP::DetectPowerpcFeatures();
1074#endif
1075 }
1076};
1077
1078// This is not really needed because HasSSE() and friends can dynamically initialize.
1079// Everything depends on CPU features so we initialize it once at load time.
1080// Dynamic initialization will be used if init priorities are not available.
1081
1082#if HAVE_GCC_INIT_PRIORITY
1083 const InitCpu s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 10))) = InitCpu();
1084#elif HAVE_MSC_INIT_PRIORITY
1085 #pragma warning(disable: 4075)
1086 #pragma init_seg(".CRT$XCU")
1087 const InitCpu s_init;
1088 #pragma warning(default: 4075)
1089#elif HAVE_XLC_INIT_PRIORITY
1090 // XLC needs constant, not a define
1091 #pragma priority(270)
1092 const InitCpu s_init;
1093#else
1094 const InitCpu s_init;
1095#endif
1096
1097ANONYMOUS_NAMESPACE_END
1098
1099#endif // CRYPTOPP_IMPORTS
Library configuration file.
Functions for CPU features and intrinsics.
Utility functions for the Crypto++ library.
Crypto++ library namespace.
Precompiled header file.
Common C++ header files.