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