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