1 /* Copyright (c) 2016, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15 #include <openssl/cpu.h> 16 17 #if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP) 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <sys/types.h> 21 #include <unistd.h> 22 23 #include <openssl/arm_arch.h> 24 #include <openssl/buf.h> 25 #include <openssl/mem.h> 26 27 #include "cpu-arm-linux.h" 28 29 #define AT_HWCAP 16 30 #define AT_HWCAP2 26 31 32 // |getauxval| is not available on Android until API level 20. Link it as a weak 33 // symbol and use other methods as fallback. 34 unsigned long getauxval(unsigned long type) __attribute__((weak)); 35 36 static int open_eintr(const char *path, int flags) { 37 int ret; 38 do { 39 ret = open(path, flags); 40 } while (ret < 0 && errno == EINTR); 41 return ret; 42 } 43 44 static ssize_t read_eintr(int fd, void *out, size_t len) { 45 ssize_t ret; 46 do { 47 ret = read(fd, out, len); 48 } while (ret < 0 && errno == EINTR); 49 return ret; 50 } 51 52 // read_full reads exactly |len| bytes from |fd| to |out|. On error or end of 53 // file, it returns zero. 54 static int read_full(int fd, void *out, size_t len) { 55 char *outp = out; 56 while (len > 0) { 57 ssize_t ret = read_eintr(fd, outp, len); 58 if (ret <= 0) { 59 return 0; 60 } 61 outp += ret; 62 len -= ret; 63 } 64 return 1; 65 } 66 67 // read_file opens |path| and reads until end-of-file. On success, it returns 68 // one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the 69 // contents. Otherwise, it returns zero. 70 static int read_file(char **out_ptr, size_t *out_len, const char *path) { 71 int fd = open_eintr(path, O_RDONLY); 72 if (fd < 0) { 73 return 0; 74 } 75 76 static const size_t kReadSize = 1024; 77 int ret = 0; 78 size_t cap = kReadSize, len = 0; 79 char *buf = OPENSSL_malloc(cap); 80 if (buf == NULL) { 81 goto err; 82 } 83 84 for (;;) { 85 if (cap - len < kReadSize) { 86 size_t new_cap = cap * 2; 87 if (new_cap < cap) { 88 goto err; 89 } 90 char *new_buf = OPENSSL_realloc(buf, new_cap); 91 if (new_buf == NULL) { 92 goto err; 93 } 94 buf = new_buf; 95 cap = new_cap; 96 } 97 98 ssize_t bytes_read = read_eintr(fd, buf + len, kReadSize); 99 if (bytes_read < 0) { 100 goto err; 101 } 102 if (bytes_read == 0) { 103 break; 104 } 105 len += bytes_read; 106 } 107 108 *out_ptr = buf; 109 *out_len = len; 110 ret = 1; 111 buf = NULL; 112 113 err: 114 OPENSSL_free(buf); 115 close(fd); 116 return ret; 117 } 118 119 // getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv. 120 static unsigned long getauxval_proc(unsigned long type) { 121 int fd = open_eintr("/proc/self/auxv", O_RDONLY); 122 if (fd < 0) { 123 return 0; 124 } 125 126 struct { 127 unsigned long tag; 128 unsigned long value; 129 } entry; 130 131 for (;;) { 132 if (!read_full(fd, &entry, sizeof(entry)) || 133 (entry.tag == 0 && entry.value == 0)) { 134 break; 135 } 136 if (entry.tag == type) { 137 close(fd); 138 return entry.value; 139 } 140 } 141 close(fd); 142 return 0; 143 } 144 145 extern uint32_t OPENSSL_armcap_P; 146 147 static int g_has_broken_neon, g_needs_hwcap2_workaround; 148 149 void OPENSSL_cpuid_setup(void) { 150 char *cpuinfo_data; 151 size_t cpuinfo_len; 152 if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) { 153 return; 154 } 155 STRING_PIECE cpuinfo; 156 cpuinfo.data = cpuinfo_data; 157 cpuinfo.len = cpuinfo_len; 158 159 // |getauxval| is not available on Android until API level 20. If it is 160 // unavailable, read from /proc/self/auxv as a fallback. This is unreadable 161 // on some versions of Android, so further fall back to /proc/cpuinfo. 162 // 163 // See 164 // https://android.googlesource.com/platform/ndk/+/882ac8f3392858991a0e1af33b4b7387ec856bd2 165 // and b/13679666 (Google-internal) for details. 166 unsigned long hwcap = 0; 167 if (getauxval != NULL) { 168 hwcap = getauxval(AT_HWCAP); 169 } 170 if (hwcap == 0) { 171 hwcap = getauxval_proc(AT_HWCAP); 172 } 173 if (hwcap == 0) { 174 hwcap = crypto_get_arm_hwcap_from_cpuinfo(&cpuinfo); 175 } 176 177 // Clear NEON support if known broken. 178 g_has_broken_neon = crypto_cpuinfo_has_broken_neon(&cpuinfo); 179 if (g_has_broken_neon) { 180 hwcap &= ~HWCAP_NEON; 181 } 182 183 // Matching OpenSSL, only report other features if NEON is present. 184 if (hwcap & HWCAP_NEON) { 185 OPENSSL_armcap_P |= ARMV7_NEON; 186 187 // Some ARMv8 Android devices don't expose AT_HWCAP2. Fall back to 188 // /proc/cpuinfo. See https://crbug.com/596156. 189 unsigned long hwcap2 = 0; 190 if (getauxval != NULL) { 191 hwcap2 = getauxval(AT_HWCAP2); 192 } 193 if (hwcap2 == 0) { 194 hwcap2 = crypto_get_arm_hwcap2_from_cpuinfo(&cpuinfo); 195 g_needs_hwcap2_workaround = hwcap2 != 0; 196 } 197 198 if (hwcap2 & HWCAP2_AES) { 199 OPENSSL_armcap_P |= ARMV8_AES; 200 } 201 if (hwcap2 & HWCAP2_PMULL) { 202 OPENSSL_armcap_P |= ARMV8_PMULL; 203 } 204 if (hwcap2 & HWCAP2_SHA1) { 205 OPENSSL_armcap_P |= ARMV8_SHA1; 206 } 207 if (hwcap2 & HWCAP2_SHA2) { 208 OPENSSL_armcap_P |= ARMV8_SHA256; 209 } 210 } 211 212 OPENSSL_free(cpuinfo_data); 213 } 214 215 int CRYPTO_has_broken_NEON(void) { return g_has_broken_neon; } 216 217 int CRYPTO_needs_hwcap2_workaround(void) { return g_needs_hwcap2_workaround; } 218 219 #endif // OPENSSL_ARM && !OPENSSL_STATIC_ARMCAP 220