6 #ifndef EXCEPTION_EXECUTE_HANDLER 7 # define EXCEPTION_EXECUTE_HANDLER 1 10 #ifndef CRYPTOPP_IMPORTS 16 #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 21 #if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 22 #include <emmintrin.h> 27 #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 29 typedef void (*SigHandler)(int);
31 #endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 33 #ifdef CRYPTOPP_CPUID_AVAILABLE 35 #if _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64 37 bool CpuId(word32 input, word32 output[4])
39 __cpuid((
int *)output, input);
45 #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 48 static jmp_buf s_jmpNoCPUID;
49 static void SigIllHandlerCPUID(
int)
51 longjmp(s_jmpNoCPUID, 1);
54 static jmp_buf s_jmpNoSSE2;
55 static void SigIllHandlerSSE2(
int)
57 longjmp(s_jmpNoSSE2, 1);
62 bool CpuId(word32 input, word32 output[4])
64 #if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) 80 __except (EXCEPTION_EXECUTE_HANDLER)
93 volatile bool result =
true;
95 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
96 if (oldHandler == SIG_ERR)
100 volatile sigset_t oldMask;
101 if (sigprocmask(0, NULL, (sigset_t*)&oldMask))
105 if (setjmp(s_jmpNoCPUID))
113 # if CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64 114 "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx" 116 "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" 118 :
"=a" (output[0]),
"=D" (output[1]),
"=c" (output[2]),
"=d" (output[3])
119 :
"a" (input),
"c" (0)
124 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULL);
127 signal(SIGILL, oldHandler);
134 static bool TrySSE2()
136 #if CRYPTOPP_BOOL_X64 138 #elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) 141 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 143 #elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 144 __m128i x = _mm_setzero_si128();
145 return _mm_cvtsi128_si32(x) == 0;
149 __except (EXCEPTION_EXECUTE_HANDLER)
157 volatile bool result =
true;
159 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
160 if (oldHandler == SIG_ERR)
164 volatile sigset_t oldMask;
165 if (sigprocmask(0, NULL, (sigset_t*)&oldMask))
169 if (setjmp(s_jmpNoSSE2))
173 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 174 __asm __volatile (
"por %xmm0, %xmm0");
175 #elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 176 __m128i x = _mm_setzero_si128();
177 result = _mm_cvtsi128_si32(x) == 0;
182 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULL);
185 signal(SIGILL, oldHandler);
190 bool CRYPTOPP_SECTION_INIT g_x86DetectionDone =
false;
191 bool CRYPTOPP_SECTION_INIT g_hasMMX =
false, CRYPTOPP_SECTION_INIT g_hasISSE =
false, CRYPTOPP_SECTION_INIT g_hasSSE2 =
false, CRYPTOPP_SECTION_INIT g_hasSSSE3 =
false;
192 bool CRYPTOPP_SECTION_INIT g_hasSSE4 =
false, CRYPTOPP_SECTION_INIT g_hasAESNI =
false, CRYPTOPP_SECTION_INIT g_hasCLMUL =
false, CRYPTOPP_SECTION_INIT g_isP4 =
false;
193 bool CRYPTOPP_SECTION_INIT g_hasRDRAND =
false, CRYPTOPP_SECTION_INIT g_hasRDSEED =
false;
194 bool CRYPTOPP_SECTION_INIT g_hasPadlockRNG =
false, CRYPTOPP_SECTION_INIT g_hasPadlockACE =
false, CRYPTOPP_SECTION_INIT g_hasPadlockACE2 =
false;
195 bool CRYPTOPP_SECTION_INIT g_hasPadlockPHE =
false, CRYPTOPP_SECTION_INIT g_hasPadlockPMM =
false;
196 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
198 static inline bool IsIntel(
const word32 output[4])
201 return (output[1] == 0x756e6547) &&
202 (output[2] == 0x6c65746e) &&
203 (output[3] == 0x49656e69);
206 static inline bool IsAMD(
const word32 output[4])
209 return (output[1] == 0x68747541) &&
210 (output[2] == 0x444D4163) &&
211 (output[3] == 0x69746E65);
214 static inline bool IsVIA(
const word32 output[4])
217 return (output[1] == 0x746e6543) &&
218 (output[2] == 0x736c7561) &&
219 (output[3] == 0x48727561);
222 #if HAVE_GCC_CONSTRUCTOR1 223 void __attribute__ ((constructor (CRYPTOPP_INIT_PRIORITY + 50))) DetectX86Features()
224 #elif HAVE_GCC_CONSTRUCTOR0 225 void __attribute__ ((constructor)) DetectX86Features()
227 void DetectX86Features()
230 word32 cpuid[4], cpuid1[4];
231 if (!CpuId(0, cpuid))
233 if (!CpuId(1, cpuid1))
236 g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
237 if ((cpuid1[3] & (1 << 26)) != 0)
238 g_hasSSE2 = TrySSE2();
239 g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
240 g_hasSSE4 = g_hasSSE2 && ((cpuid1[2] & (1<<19)) && (cpuid1[2] & (1<<20)));
241 g_hasAESNI = g_hasSSE2 && (cpuid1[2] & (1<<25));
242 g_hasCLMUL = g_hasSSE2 && (cpuid1[2] & (1<<1));
244 if ((cpuid1[3] & (1 << 25)) != 0)
249 CpuId(0x080000000, cpuid2);
250 if (cpuid2[0] >= 0x080000001)
252 CpuId(0x080000001, cpuid2);
253 g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
259 static const unsigned int RDRAND_FLAG = (1 << 30);
260 static const unsigned int RDSEED_FLAG = (1 << 18);
262 g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
263 g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
264 g_hasRDRAND = !!(cpuid1[2] & RDRAND_FLAG);
269 if (CpuId(7, cpuid3))
270 g_hasRDSEED = !!(cpuid3[1] & RDSEED_FLAG);
273 else if (IsAMD(cpuid))
275 static const unsigned int RDRAND_FLAG = (1 << 30);
278 g_hasRDRAND = !!(cpuid[2] & RDRAND_FLAG);
280 CpuId(0x80000005, cpuid);
281 g_cacheLineSize = GETBYTE(cpuid[2], 0);
283 else if (IsVIA(cpuid))
285 static const unsigned int RNG_FLAGS = (0x3 << 2);
286 static const unsigned int ACE_FLAGS = (0x3 << 6);
287 static const unsigned int ACE2_FLAGS = (0x3 << 8);
288 static const unsigned int PHE_FLAGS = (0x3 << 10);
289 static const unsigned int PMM_FLAGS = (0x3 << 12);
291 CpuId(0xC0000000, cpuid);
292 if (cpuid[0] >= 0xC0000001)
295 CpuId(0xC0000001, cpuid);
296 g_hasPadlockRNG = !!(cpuid[3] & RNG_FLAGS);
297 g_hasPadlockACE = !!(cpuid[3] & ACE_FLAGS);
298 g_hasPadlockACE2 = !!(cpuid[3] & ACE2_FLAGS);
299 g_hasPadlockPHE = !!(cpuid[3] & PHE_FLAGS);
300 g_hasPadlockPMM = !!(cpuid[3] & PMM_FLAGS);
304 if (!g_cacheLineSize)
305 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
307 *((
volatile bool*)&g_x86DetectionDone) =
true;
310 #elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64) 326 bool CRYPTOPP_SECTION_INIT g_ArmDetectionDone =
false;
327 bool CRYPTOPP_SECTION_INIT g_hasNEON =
false, CRYPTOPP_SECTION_INIT g_hasPMULL =
false, CRYPTOPP_SECTION_INIT g_hasCRC32 =
false;
328 bool CRYPTOPP_SECTION_INIT g_hasAES =
false, CRYPTOPP_SECTION_INIT g_hasSHA1 =
false, CRYPTOPP_SECTION_INIT g_hasSHA2 =
false;
329 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
331 #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 334 static jmp_buf s_jmpNoNEON;
335 static void SigIllHandlerNEON(
int)
337 longjmp(s_jmpNoNEON, 1);
340 static jmp_buf s_jmpNoPMULL;
341 static void SigIllHandlerPMULL(
int)
343 longjmp(s_jmpNoPMULL, 1);
346 static jmp_buf s_jmpNoCRC32;
347 static void SigIllHandlerCRC32(
int)
349 longjmp(s_jmpNoCRC32, 1);
352 static jmp_buf s_jmpNoAES;
353 static void SigIllHandlerAES(
int)
355 longjmp(s_jmpNoAES, 1);
358 static jmp_buf s_jmpNoSHA1;
359 static void SigIllHandlerSHA1(
int)
361 longjmp(s_jmpNoSHA1, 1);
364 static jmp_buf s_jmpNoSHA2;
365 static void SigIllHandlerSHA2(
int)
367 longjmp(s_jmpNoSHA2, 1);
370 #endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY 372 static bool TryNEON()
374 #if (CRYPTOPP_BOOL_NEON_INTRINSICS_AVAILABLE) 375 # if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) 376 volatile bool result =
true;
379 uint32_t v1[4] = {1,1,1,1};
380 uint32x4_t x1 = vld1q_u32(v1);
381 uint64_t v2[2] = {1,1};
382 uint64x2_t x2 = vld1q_u64(v2);
384 uint32x4_t x3 = vdupq_n_u32(2);
385 x3 = vsetq_lane_u32(vgetq_lane_u32(x1,0),x3,0);
386 x3 = vsetq_lane_u32(vgetq_lane_u32(x1,3),x3,3);
387 uint64x2_t x4 = vdupq_n_u64(2);
388 x4 = vsetq_lane_u64(vgetq_lane_u64(x2,0),x4,0);
389 x4 = vsetq_lane_u64(vgetq_lane_u64(x2,1),x4,1);
391 result = !!(vgetq_lane_u32(x3,0) | vgetq_lane_u64(x4,1));
393 __except (EXCEPTION_EXECUTE_HANDLER)
401 volatile bool result =
true;
403 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerNEON);
404 if (oldHandler == SIG_ERR)
407 volatile sigset_t oldMask;
408 if (sigprocmask(0, NULL, (sigset_t*)&oldMask))
411 if (setjmp(s_jmpNoNEON))
415 uint32_t v1[4] = {1,1,1,1};
416 uint32x4_t x1 = vld1q_u32(v1);
417 uint64_t v2[2] = {1,1};
418 uint64x2_t x2 = vld1q_u64(v2);
420 uint32x4_t x3 = {0,0,0,0};
421 x3 = vsetq_lane_u32(vgetq_lane_u32(x1,0),x3,0);
422 x3 = vsetq_lane_u32(vgetq_lane_u32(x1,3),x3,3);
423 uint64x2_t x4 = {0,0};
424 x4 = vsetq_lane_u64(vgetq_lane_u64(x2,0),x4,0);
425 x4 = vsetq_lane_u64(vgetq_lane_u64(x2,1),x4,1);
428 result = !!(vgetq_lane_u32(x3,0) | vgetq_lane_u64(x4,1));
431 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULL);
432 signal(SIGILL, oldHandler);
437 #endif // CRYPTOPP_BOOL_NEON_INTRINSICS_AVAILABLE 440 static bool TryPMULL()
442 #if (CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE) 443 # if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) 444 volatile bool result =
true;
447 const poly64_t a1={2}, b1={3};
448 const poly64x2_t a2={4,5}, b2={6,7};
449 const poly64x2_t a3={0x8080808080808080,0xa0a0a0a0a0a0a0a0}, b3={0xc0c0c0c0c0c0c0c0, 0xe0e0e0e0e0e0e0e0};
451 const poly128_t r1 = vmull_p64(a1, b1);
452 const poly128_t r2 = vmull_high_p64(a2, b2);
453 const poly128_t r3 = vmull_high_p64(a3, b3);
456 const uint64x2_t& t1 = vreinterpretq_u64_p128(r1);
457 const uint64x2_t& t2 = vreinterpretq_u64_p128(r2);
458 const uint64x2_t& t3 = vreinterpretq_u64_p128(r3);
460 result = !!(vgetq_lane_u64(t1,0) == 0x06 && vgetq_lane_u64(t1,1) == 0x00 && vgetq_lane_u64(t2,0) == 0x1b &&
461 vgetq_lane_u64(t2,1) == 0x00 && vgetq_lane_u64(t3,0) == 0x6c006c006c006c00 && vgetq_lane_u64(t3,1) == 0x6c006c006c006c00);
463 __except (EXCEPTION_EXECUTE_HANDLER)
471 volatile bool result =
true;
473 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerPMULL);
474 if (oldHandler == SIG_ERR)
477 volatile sigset_t oldMask;
478 if (sigprocmask(0, NULL, (sigset_t*)&oldMask))
481 if (setjmp(s_jmpNoPMULL))
485 const poly64_t a1={2}, b1={3};
486 const poly64x2_t a2={4,5}, b2={6,7};
487 const poly64x2_t a3={0x8080808080808080,0xa0a0a0a0a0a0a0a0}, b3={0xc0c0c0c0c0c0c0c0, 0xe0e0e0e0e0e0e0e0};
489 const poly128_t r1 = vmull_p64(a1, b1);
490 const poly128_t r2 = vmull_high_p64(a2, b2);
491 const poly128_t r3 = vmull_high_p64(a3, b3);
494 const uint64x2_t& t1 = (uint64x2_t)(r1);
495 const uint64x2_t& t2 = (uint64x2_t)(r2);
496 const uint64x2_t& t3 = (uint64x2_t)(r3);
498 result = !!(vgetq_lane_u64(t1,0) == 0x06 && vgetq_lane_u64(t1,1) == 0x00 && vgetq_lane_u64(t2,0) == 0x1b &&
499 vgetq_lane_u64(t2,1) == 0x00 && vgetq_lane_u64(t3,0) == 0x6c006c006c006c00 && vgetq_lane_u64(t3,1) == 0x6c006c006c006c00);
502 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULL);
503 signal(SIGILL, oldHandler);
508 #endif // CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE 511 static bool TryCRC32()
513 #if (CRYPTOPP_BOOL_ARM_CRC32_INTRINSICS_AVAILABLE) 514 # if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) 515 volatile bool result =
true;
518 word32 w=0, x=1; word16 y=2; byte z=3;
525 __except (EXCEPTION_EXECUTE_HANDLER)
533 volatile bool result =
true;
535 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerCRC32);
536 if (oldHandler == SIG_ERR)
539 volatile sigset_t oldMask;
540 if (sigprocmask(0, NULL, (sigset_t*)&oldMask))
543 if (setjmp(s_jmpNoCRC32))
547 word32 w=0, x=1; word16 y=2; byte z=3;
556 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULL);
557 signal(SIGILL, oldHandler);
562 #endif // CRYPTOPP_BOOL_ARM_CRC32_INTRINSICS_AVAILABLE 567 #if (CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE) 568 # if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) 569 volatile bool result =
true;
573 uint8x16_t data = vdupq_n_u8(0), key = vdupq_n_u8(0);
574 uint8x16_t r1 = vaeseq_u8(data, key);
575 uint8x16_t r2 = vaesdq_u8(data, key);
577 result = !!(vgetq_lane_u8(r1,0) | vgetq_lane_u8(r2,7));
579 __except (EXCEPTION_EXECUTE_HANDLER)
587 volatile bool result =
true;
589 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerAES);
590 if (oldHandler == SIG_ERR)
593 volatile sigset_t oldMask;
594 if (sigprocmask(0, NULL, (sigset_t*)&oldMask))
597 if (setjmp(s_jmpNoAES))
601 uint8x16_t data = vdupq_n_u8(0), key = vdupq_n_u8(0);
602 uint8x16_t r1 = vaeseq_u8(data, key);
603 uint8x16_t r2 = vaesdq_u8(data, key);
606 result = !!(vgetq_lane_u8(r1,0) | vgetq_lane_u8(r2,7));
609 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULL);
610 signal(SIGILL, oldHandler);
615 #endif // CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE 618 static bool TrySHA1()
620 #if (CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE) 621 # if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) 622 volatile bool result =
true;
625 uint32x4_t data1 = {1,2,3,4}, data2 = {5,6,7,8}, data3 = {9,10,11,12};
627 uint32x4_t r1 = vsha1cq_u32 (data1, 0, data2);
628 uint32x4_t r2 = vsha1mq_u32 (data1, 0, data2);
629 uint32x4_t r3 = vsha1pq_u32 (data1, 0, data2);
630 uint32x4_t r4 = vsha1su0q_u32 (data1, data2, data3);
631 uint32x4_t r5 = vsha1su1q_u32 (data1, data2);
633 result = !!(vgetq_lane_u32(r1,0) | vgetq_lane_u32(r2,1) | vgetq_lane_u32(r3,2) | vgetq_lane_u32(r4,3) | vgetq_lane_u32(r5,0));
635 __except (EXCEPTION_EXECUTE_HANDLER)
643 volatile bool result =
true;
645 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerSHA1);
646 if (oldHandler == SIG_ERR)
649 volatile sigset_t oldMask;
650 if (sigprocmask(0, NULL, (sigset_t*)&oldMask))
653 if (setjmp(s_jmpNoSHA1))
657 uint32x4_t data1 = {1,2,3,4}, data2 = {5,6,7,8}, data3 = {9,10,11,12};
659 uint32x4_t r1 = vsha1cq_u32 (data1, 0, data2);
660 uint32x4_t r2 = vsha1mq_u32 (data1, 0, data2);
661 uint32x4_t r3 = vsha1pq_u32 (data1, 0, data2);
662 uint32x4_t r4 = vsha1su0q_u32 (data1, data2, data3);
663 uint32x4_t r5 = vsha1su1q_u32 (data1, data2);
666 result = !!(vgetq_lane_u32(r1,0) | vgetq_lane_u32(r2,1) | vgetq_lane_u32(r3,2) | vgetq_lane_u32(r4,3) | vgetq_lane_u32(r5,0));
669 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULL);
670 signal(SIGILL, oldHandler);
675 #endif // CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE 678 static bool TrySHA2()
680 #if (CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE) 681 # if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) 682 volatile bool result =
true;
685 uint32x4_t data1 = {1,2,3,4}, data2 = {5,6,7,8}, data3 = {9,10,11,12};
687 uint32x4_t r1 = vsha256hq_u32 (data1, data2, data3);
688 uint32x4_t r2 = vsha256h2q_u32 (data1, data2, data3);
689 uint32x4_t r3 = vsha256su0q_u32 (data1, data2);
690 uint32x4_t r4 = vsha256su1q_u32 (data1, data2, data3);
692 result = !!(vgetq_lane_u32(r1,0) | vgetq_lane_u32(r2,1) | vgetq_lane_u32(r3,2) | vgetq_lane_u32(r4,3));
694 __except (EXCEPTION_EXECUTE_HANDLER)
702 volatile bool result =
true;
704 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerSHA2);
705 if (oldHandler == SIG_ERR)
708 volatile sigset_t oldMask;
709 if (sigprocmask(0, NULL, (sigset_t*)&oldMask))
712 if (setjmp(s_jmpNoSHA2))
716 uint32x4_t data1 = {1,2,3,4}, data2 = {5,6,7,8}, data3 = {9,10,11,12};
718 uint32x4_t r1 = vsha256hq_u32 (data1, data2, data3);
719 uint32x4_t r2 = vsha256h2q_u32 (data1, data2, data3);
720 uint32x4_t r3 = vsha256su0q_u32 (data1, data2);
721 uint32x4_t r4 = vsha256su1q_u32 (data1, data2, data3);
724 result = !!(vgetq_lane_u32(r1,0) | vgetq_lane_u32(r2,1) | vgetq_lane_u32(r3,2) | vgetq_lane_u32(r4,3));
727 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULL);
728 signal(SIGILL, oldHandler);
733 #endif // CRYPTOPP_BOOL_ARM_CRYPTO_INTRINSICS_AVAILABLE 736 #if HAVE_GCC_CONSTRUCTOR1 737 void __attribute__ ((constructor (CRYPTOPP_INIT_PRIORITY + 50))) DetectArmFeatures()
738 #elif HAVE_GCC_CONSTRUCTOR0 739 void __attribute__ ((constructor)) DetectArmFeatures()
741 void DetectArmFeatures()
744 g_hasNEON = TryNEON();
745 g_hasPMULL = TryPMULL();
746 g_hasCRC32 = TryCRC32();
748 g_hasSHA1 = TrySHA1();
749 g_hasSHA2 = TrySHA2();
751 *((
volatile bool*)&g_ArmDetectionDone) =
true;
Utility functions for the Crypto++ library.
Library configuration file.
Functions for CPU features and intrinsics.
Crypto++ library namespace.