/* $OpenBSD: armcap.c,v 1.1 2022/03/23 15:13:31 tb Exp $ */ #include #include #include #include #include #include #include "arm_arch.h" unsigned int OPENSSL_armcap_P; #if __ARM_ARCH__ >= 7 static sigset_t all_masked; static sigjmp_buf ill_jmp; static void ill_handler (int sig) { siglongjmp(ill_jmp, sig); } /* * Following subroutines could have been inlined, but it's not all * ARM compilers support inline assembler... */ void _armv7_neon_probe(void); void _armv8_aes_probe(void); void _armv8_sha1_probe(void); void _armv8_sha256_probe(void); void _armv8_pmull_probe(void); #endif #if defined(__GNUC__) && __GNUC__>=2 void OPENSSL_cpuid_setup(void) __attribute__((constructor)); #endif void OPENSSL_cpuid_setup(void) { #if __ARM_ARCH__ >= 7 struct sigaction ill_oact, ill_act; sigset_t oset; #endif static int trigger = 0; if (trigger) return; trigger = 1; OPENSSL_armcap_P = 0; #if __ARM_ARCH__ >= 7 sigfillset(&all_masked); sigdelset(&all_masked, SIGILL); sigdelset(&all_masked, SIGTRAP); sigdelset(&all_masked, SIGFPE); sigdelset(&all_masked, SIGBUS); sigdelset(&all_masked, SIGSEGV); memset(&ill_act, 0, sizeof(ill_act)); ill_act.sa_handler = ill_handler; ill_act.sa_mask = all_masked; sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); sigaction(SIGILL, &ill_act, &ill_oact); if (sigsetjmp(ill_jmp, 1) == 0) { _armv7_neon_probe(); OPENSSL_armcap_P |= ARMV7_NEON; if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_pmull_probe(); OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; } else if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_aes_probe(); OPENSSL_armcap_P |= ARMV8_AES; } if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_sha1_probe(); OPENSSL_armcap_P |= ARMV8_SHA1; } if (sigsetjmp(ill_jmp, 1) == 0) { _armv8_sha256_probe(); OPENSSL_armcap_P |= ARMV8_SHA256; } } sigaction (SIGILL, &ill_oact, NULL); sigprocmask(SIG_SETMASK, &oset, NULL); #endif }