1 /* 2 * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <setjmp.h> 14 #include <signal.h> 15 #include <openssl/crypto.h> 16 #include "internal/cryptlib.h" 17 18 #include "arm_arch.h" 19 20 __attribute__ ((visibility("hidden"))) 21 unsigned int OPENSSL_armcap_P = 0; 22 23 #if __ARM_MAX_ARCH__<7 24 void OPENSSL_cpuid_setup(void) 25 { 26 } 27 28 uint32_t OPENSSL_rdtsc(void) 29 { 30 return 0; 31 } 32 #else 33 static sigset_t all_masked; 34 35 static sigjmp_buf ill_jmp; 36 static void ill_handler(int sig) 37 { 38 siglongjmp(ill_jmp, sig); 39 } 40 41 /* 42 * Following subroutines could have been inlined, but it's not all 43 * ARM compilers support inline assembler... 44 */ 45 void _armv7_neon_probe(void); 46 void _armv8_aes_probe(void); 47 void _armv8_sha1_probe(void); 48 void _armv8_sha256_probe(void); 49 void _armv8_pmull_probe(void); 50 # ifdef __aarch64__ 51 void _armv8_sha512_probe(void); 52 # endif 53 uint32_t _armv7_tick(void); 54 55 uint32_t OPENSSL_rdtsc(void) 56 { 57 if (OPENSSL_armcap_P & ARMV7_TICK) 58 return _armv7_tick(); 59 else 60 return 0; 61 } 62 63 # if defined(__GNUC__) && __GNUC__>=2 64 void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); 65 # endif 66 /* 67 * Use a weak reference to getauxval() so we can use it if it is available but 68 * don't break the build if it is not. 69 */ 70 # if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) 71 extern unsigned long getauxval(unsigned long type) __attribute__ ((weak)); 72 # else 73 static unsigned long (*getauxval) (unsigned long) = NULL; 74 # endif 75 76 /* 77 * ARM puts the feature bits for Crypto Extensions in AT_HWCAP2, whereas 78 * AArch64 used AT_HWCAP. 79 */ 80 # if defined(__arm__) || defined (__arm) 81 # define HWCAP 16 82 /* AT_HWCAP */ 83 # define HWCAP_NEON (1 << 12) 84 85 # define HWCAP_CE 26 86 /* AT_HWCAP2 */ 87 # define HWCAP_CE_AES (1 << 0) 88 # define HWCAP_CE_PMULL (1 << 1) 89 # define HWCAP_CE_SHA1 (1 << 2) 90 # define HWCAP_CE_SHA256 (1 << 3) 91 # elif defined(__aarch64__) 92 # define HWCAP 16 93 /* AT_HWCAP */ 94 # define HWCAP_NEON (1 << 1) 95 96 # define HWCAP_CE HWCAP 97 # define HWCAP_CE_AES (1 << 3) 98 # define HWCAP_CE_PMULL (1 << 4) 99 # define HWCAP_CE_SHA1 (1 << 5) 100 # define HWCAP_CE_SHA256 (1 << 6) 101 # define HWCAP_CE_SHA512 (1 << 21) 102 # endif 103 104 void OPENSSL_cpuid_setup(void) 105 { 106 const char *e; 107 struct sigaction ill_oact, ill_act; 108 sigset_t oset; 109 static int trigger = 0; 110 111 if (trigger) 112 return; 113 trigger = 1; 114 115 if ((e = getenv("OPENSSL_armcap"))) { 116 OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0); 117 return; 118 } 119 120 # if defined(__APPLE__) && !defined(__aarch64__) 121 /* 122 * Capability probing by catching SIGILL appears to be problematic 123 * on iOS. But since Apple universe is "monocultural", it's actually 124 * possible to simply set pre-defined processor capability mask. 125 */ 126 if (1) { 127 OPENSSL_armcap_P = ARMV7_NEON; 128 return; 129 } 130 /* 131 * One could do same even for __aarch64__ iOS builds. It's not done 132 * exclusively for reasons of keeping code unified across platforms. 133 * Unified code works because it never triggers SIGILL on Apple 134 * devices... 135 */ 136 # endif 137 138 sigfillset(&all_masked); 139 sigdelset(&all_masked, SIGILL); 140 sigdelset(&all_masked, SIGTRAP); 141 sigdelset(&all_masked, SIGFPE); 142 sigdelset(&all_masked, SIGBUS); 143 sigdelset(&all_masked, SIGSEGV); 144 145 OPENSSL_armcap_P = 0; 146 147 memset(&ill_act, 0, sizeof(ill_act)); 148 ill_act.sa_handler = ill_handler; 149 ill_act.sa_mask = all_masked; 150 151 sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); 152 sigaction(SIGILL, &ill_act, &ill_oact); 153 154 if (getauxval != NULL) { 155 if (getauxval(HWCAP) & HWCAP_NEON) { 156 unsigned long hwcap = getauxval(HWCAP_CE); 157 158 OPENSSL_armcap_P |= ARMV7_NEON; 159 160 if (hwcap & HWCAP_CE_AES) 161 OPENSSL_armcap_P |= ARMV8_AES; 162 163 if (hwcap & HWCAP_CE_PMULL) 164 OPENSSL_armcap_P |= ARMV8_PMULL; 165 166 if (hwcap & HWCAP_CE_SHA1) 167 OPENSSL_armcap_P |= ARMV8_SHA1; 168 169 if (hwcap & HWCAP_CE_SHA256) 170 OPENSSL_armcap_P |= ARMV8_SHA256; 171 172 # ifdef __aarch64__ 173 if (hwcap & HWCAP_CE_SHA512) 174 OPENSSL_armcap_P |= ARMV8_SHA512; 175 # endif 176 } 177 } else if (sigsetjmp(ill_jmp, 1) == 0) { 178 _armv7_neon_probe(); 179 OPENSSL_armcap_P |= ARMV7_NEON; 180 if (sigsetjmp(ill_jmp, 1) == 0) { 181 _armv8_pmull_probe(); 182 OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; 183 } else if (sigsetjmp(ill_jmp, 1) == 0) { 184 _armv8_aes_probe(); 185 OPENSSL_armcap_P |= ARMV8_AES; 186 } 187 if (sigsetjmp(ill_jmp, 1) == 0) { 188 _armv8_sha1_probe(); 189 OPENSSL_armcap_P |= ARMV8_SHA1; 190 } 191 if (sigsetjmp(ill_jmp, 1) == 0) { 192 _armv8_sha256_probe(); 193 OPENSSL_armcap_P |= ARMV8_SHA256; 194 } 195 # if defined(__aarch64__) && !defined(__APPLE__) 196 if (sigsetjmp(ill_jmp, 1) == 0) { 197 _armv8_sha512_probe(); 198 OPENSSL_armcap_P |= ARMV8_SHA512; 199 } 200 # endif 201 } 202 if (sigsetjmp(ill_jmp, 1) == 0) { 203 _armv7_tick(); 204 OPENSSL_armcap_P |= ARMV7_TICK; 205 } 206 207 sigaction(SIGILL, &ill_oact, NULL); 208 sigprocmask(SIG_SETMASK, &oset, NULL); 209 } 210 #endif 211