1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <setjmp.h> 5 #include <signal.h> 6 #include <crypto.h> 7 8 #include "arm_arch.h" 9 10 __attribute__ ((visibility("hidden"))) 11 unsigned int OPENSSL_armcap_P = 0; 12 13 #if __ARM_MAX_ARCH__<7 14 void OPENSSL_cpuid_setup(void) 15 { 16 } 17 18 unsigned long OPENSSL_rdtsc(void) 19 { 20 return 0; 21 } 22 #else 23 static sigset_t all_masked; 24 25 static sigjmp_buf ill_jmp; 26 static void ill_handler(int sig) 27 { 28 siglongjmp(ill_jmp, sig); 29 } 30 31 /* 32 * Following subroutines could have been inlined, but it's not all 33 * ARM compilers support inline assembler... 34 */ 35 void _armv7_neon_probe(void); 36 void _armv8_aes_probe(void); 37 void _armv8_sha1_probe(void); 38 void _armv8_sha256_probe(void); 39 void _armv8_pmull_probe(void); 40 unsigned long _armv7_tick(void); 41 42 unsigned long OPENSSL_rdtsc(void) 43 { 44 if (OPENSSL_armcap_P & ARMV7_TICK) 45 return _armv7_tick(); 46 else 47 return 0; 48 } 49 50 /* 51 * Use a weak reference to getauxval() so we can use it if it is available but 52 * don't break the build if it is not. 53 */ 54 # if defined(__GNUC__) && __GNUC__>=2 55 void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); 56 extern unsigned long getauxval(unsigned long type) __attribute__ ((weak)); 57 # else 58 static unsigned long (*getauxval) (unsigned long) = NULL; 59 # endif 60 61 /* 62 * ARM puts the the feature bits for Crypto Extensions in AT_HWCAP2, whereas 63 * AArch64 used AT_HWCAP. 64 */ 65 # if defined(__arm__) || defined (__arm) 66 # define HWCAP 16 67 /* AT_HWCAP */ 68 # define HWCAP_NEON (1 << 12) 69 70 # define HWCAP_CE 26 71 /* AT_HWCAP2 */ 72 # define HWCAP_CE_AES (1 << 0) 73 # define HWCAP_CE_PMULL (1 << 1) 74 # define HWCAP_CE_SHA1 (1 << 2) 75 # define HWCAP_CE_SHA256 (1 << 3) 76 # elif defined(__aarch64__) 77 # define HWCAP 16 78 /* AT_HWCAP */ 79 # define HWCAP_NEON (1 << 1) 80 81 # define HWCAP_CE HWCAP 82 # define HWCAP_CE_AES (1 << 3) 83 # define HWCAP_CE_PMULL (1 << 4) 84 # define HWCAP_CE_SHA1 (1 << 5) 85 # define HWCAP_CE_SHA256 (1 << 6) 86 # endif 87 88 void OPENSSL_cpuid_setup(void) 89 { 90 char *e; 91 struct sigaction ill_oact, ill_act; 92 sigset_t oset; 93 static int trigger = 0; 94 95 if (trigger) 96 return; 97 trigger = 1; 98 99 if ((e = getenv("OPENSSL_armcap"))) { 100 OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0); 101 return; 102 } 103 104 sigfillset(&all_masked); 105 sigdelset(&all_masked, SIGILL); 106 sigdelset(&all_masked, SIGTRAP); 107 sigdelset(&all_masked, SIGFPE); 108 sigdelset(&all_masked, SIGBUS); 109 sigdelset(&all_masked, SIGSEGV); 110 111 OPENSSL_armcap_P = 0; 112 113 memset(&ill_act, 0, sizeof(ill_act)); 114 ill_act.sa_handler = ill_handler; 115 ill_act.sa_mask = all_masked; 116 117 sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); 118 sigaction(SIGILL, &ill_act, &ill_oact); 119 120 if (getauxval != NULL) { 121 if (getauxval(HWCAP) & HWCAP_NEON) { 122 unsigned long hwcap = getauxval(HWCAP_CE); 123 124 OPENSSL_armcap_P |= ARMV7_NEON; 125 126 if (hwcap & HWCAP_CE_AES) 127 OPENSSL_armcap_P |= ARMV8_AES; 128 129 if (hwcap & HWCAP_CE_PMULL) 130 OPENSSL_armcap_P |= ARMV8_PMULL; 131 132 if (hwcap & HWCAP_CE_SHA1) 133 OPENSSL_armcap_P |= ARMV8_SHA1; 134 135 if (hwcap & HWCAP_CE_SHA256) 136 OPENSSL_armcap_P |= ARMV8_SHA256; 137 } 138 } else if (sigsetjmp(ill_jmp, 1) == 0) { 139 _armv7_neon_probe(); 140 OPENSSL_armcap_P |= ARMV7_NEON; 141 if (sigsetjmp(ill_jmp, 1) == 0) { 142 _armv8_pmull_probe(); 143 OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; 144 } else if (sigsetjmp(ill_jmp, 1) == 0) { 145 _armv8_aes_probe(); 146 OPENSSL_armcap_P |= ARMV8_AES; 147 } 148 if (sigsetjmp(ill_jmp, 1) == 0) { 149 _armv8_sha1_probe(); 150 OPENSSL_armcap_P |= ARMV8_SHA1; 151 } 152 if (sigsetjmp(ill_jmp, 1) == 0) { 153 _armv8_sha256_probe(); 154 OPENSSL_armcap_P |= ARMV8_SHA256; 155 } 156 } 157 if (sigsetjmp(ill_jmp, 1) == 0) { 158 _armv7_tick(); 159 OPENSSL_armcap_P |= ARMV7_TICK; 160 } 161 162 sigaction(SIGILL, &ill_oact, NULL); 163 sigprocmask(SIG_SETMASK, &oset, NULL); 164 } 165 #endif 166