You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

356 lines
9.8 KiB

  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. #include <openssl/cpu.h>
  15. #if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP)
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <string.h>
  19. #include <sys/types.h>
  20. #include <unistd.h>
  21. #include <openssl/arm_arch.h>
  22. #include <openssl/buf.h>
  23. #include <openssl/mem.h>
  24. #include "internal.h"
  25. #define AT_HWCAP 16
  26. #define AT_HWCAP2 26
  27. #define HWCAP_NEON (1 << 12)
  28. /* See /usr/include/asm/hwcap.h on an ARM installation for the source of
  29. * these values. */
  30. #define HWCAP2_AES (1 << 0)
  31. #define HWCAP2_PMULL (1 << 1)
  32. #define HWCAP2_SHA1 (1 << 2)
  33. #define HWCAP2_SHA2 (1 << 3)
  34. /* |getauxval| is not available on Android until API level 20. Link it as a weak
  35. * symbol and use other methods as fallback. */
  36. unsigned long getauxval(unsigned long type) __attribute__((weak));
  37. static int open_eintr(const char *path, int flags) {
  38. int ret;
  39. do {
  40. ret = open(path, flags);
  41. } while (ret < 0 && errno == EINTR);
  42. return ret;
  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. /* read_full reads exactly |len| bytes from |fd| to |out|. On error or end of
  52. * file, it returns zero. */
  53. static int read_full(int fd, void *out, size_t len) {
  54. char *outp = out;
  55. while (len > 0) {
  56. ssize_t ret = read_eintr(fd, outp, len);
  57. if (ret <= 0) {
  58. return 0;
  59. }
  60. outp += ret;
  61. len -= ret;
  62. }
  63. return 1;
  64. }
  65. /* read_file opens |path| and reads until end-of-file. On success, it returns
  66. * one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the
  67. * contents. Otherwise, it returns zero. */
  68. static int read_file(char **out_ptr, size_t *out_len, const char *path) {
  69. int fd = open_eintr(path, O_RDONLY);
  70. if (fd < 0) {
  71. return 0;
  72. }
  73. static const size_t kReadSize = 1024;
  74. int ret = 0;
  75. size_t cap = kReadSize, len = 0;
  76. char *buf = OPENSSL_malloc(cap);
  77. if (buf == NULL) {
  78. goto err;
  79. }
  80. for (;;) {
  81. if (cap - len < kReadSize) {
  82. size_t new_cap = cap * 2;
  83. if (new_cap < cap) {
  84. goto err;
  85. }
  86. char *new_buf = OPENSSL_realloc(buf, new_cap);
  87. if (new_buf == NULL) {
  88. goto err;
  89. }
  90. buf = new_buf;
  91. cap = new_cap;
  92. }
  93. ssize_t bytes_read = read_eintr(fd, buf + len, kReadSize);
  94. if (bytes_read < 0) {
  95. goto err;
  96. }
  97. if (bytes_read == 0) {
  98. break;
  99. }
  100. len += bytes_read;
  101. }
  102. *out_ptr = buf;
  103. *out_len = len;
  104. ret = 1;
  105. buf = NULL;
  106. err:
  107. OPENSSL_free(buf);
  108. close(fd);
  109. return ret;
  110. }
  111. /* getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv. */
  112. static unsigned long getauxval_proc(unsigned long type) {
  113. int fd = open_eintr("/proc/self/auxv", O_RDONLY);
  114. if (fd < 0) {
  115. return 0;
  116. }
  117. struct {
  118. unsigned long tag;
  119. unsigned long value;
  120. } entry;
  121. for (;;) {
  122. if (!read_full(fd, &entry, sizeof(entry)) ||
  123. (entry.tag == 0 && entry.value == 0)) {
  124. break;
  125. }
  126. if (entry.tag == type) {
  127. close(fd);
  128. return entry.value;
  129. }
  130. }
  131. close(fd);
  132. return 0;
  133. }
  134. typedef struct {
  135. const char *data;
  136. size_t len;
  137. } STRING_PIECE;
  138. static int STRING_PIECE_equals(const STRING_PIECE *a, const char *b) {
  139. size_t b_len = strlen(b);
  140. return a->len == b_len && memcmp(a->data, b, b_len) == 0;
  141. }
  142. /* STRING_PIECE_split finds the first occurence of |sep| in |in| and, if found,
  143. * sets |*out_left| and |*out_right| to |in| split before and after it. It
  144. * returns one if |sep| was found and zero otherwise. */
  145. static int STRING_PIECE_split(STRING_PIECE *out_left, STRING_PIECE *out_right,
  146. const STRING_PIECE *in, char sep) {
  147. const char *p = memchr(in->data, sep, in->len);
  148. if (p == NULL) {
  149. return 0;
  150. }
  151. /* |out_left| or |out_right| may alias |in|, so make a copy. */
  152. STRING_PIECE in_copy = *in;
  153. out_left->data = in_copy.data;
  154. out_left->len = p - in_copy.data;
  155. out_right->data = in_copy.data + out_left->len + 1;
  156. out_right->len = in_copy.len - out_left->len - 1;
  157. return 1;
  158. }
  159. /* STRING_PIECE_trim removes leading and trailing whitespace from |s|. */
  160. static void STRING_PIECE_trim(STRING_PIECE *s) {
  161. while (s->len != 0 && (s->data[0] == ' ' || s->data[0] == '\t')) {
  162. s->data++;
  163. s->len--;
  164. }
  165. while (s->len != 0 &&
  166. (s->data[s->len - 1] == ' ' || s->data[s->len - 1] == '\t')) {
  167. s->len--;
  168. }
  169. }
  170. /* extract_cpuinfo_field extracts a /proc/cpuinfo field named |field| from
  171. * |in|. If found, it sets |*out| to the value and returns one. Otherwise, it
  172. * returns zero. */
  173. static int extract_cpuinfo_field(STRING_PIECE *out, const STRING_PIECE *in,
  174. const char *field) {
  175. /* Process |in| one line at a time. */
  176. STRING_PIECE remaining = *in, line;
  177. while (STRING_PIECE_split(&line, &remaining, &remaining, '\n')) {
  178. STRING_PIECE key, value;
  179. if (!STRING_PIECE_split(&key, &value, &line, ':')) {
  180. continue;
  181. }
  182. STRING_PIECE_trim(&key);
  183. if (STRING_PIECE_equals(&key, field)) {
  184. STRING_PIECE_trim(&value);
  185. *out = value;
  186. return 1;
  187. }
  188. }
  189. return 0;
  190. }
  191. static int cpuinfo_field_equals(const STRING_PIECE *cpuinfo, const char *field,
  192. const char *value) {
  193. STRING_PIECE extracted;
  194. return extract_cpuinfo_field(&extracted, cpuinfo, field) &&
  195. STRING_PIECE_equals(&extracted, value);
  196. }
  197. /* has_list_item treats |list| as a space-separated list of items and returns
  198. * one if |item| is contained in |list| and zero otherwise. */
  199. static int has_list_item(const STRING_PIECE *list, const char *item) {
  200. STRING_PIECE remaining = *list, feature;
  201. while (STRING_PIECE_split(&feature, &remaining, &remaining, ' ')) {
  202. if (STRING_PIECE_equals(&feature, item)) {
  203. return 1;
  204. }
  205. }
  206. return 0;
  207. }
  208. static unsigned long get_hwcap_cpuinfo(const STRING_PIECE *cpuinfo) {
  209. if (cpuinfo_field_equals(cpuinfo, "CPU architecture", "8")) {
  210. /* This is a 32-bit ARM binary running on a 64-bit kernel. NEON is always
  211. * available on ARMv8. Linux omits required features, so reading the
  212. * "Features" line does not work. (For simplicity, use strict equality. We
  213. * assume everything running on future ARM architectures will have a
  214. * working |getauxval|.) */
  215. return HWCAP_NEON;
  216. }
  217. STRING_PIECE features;
  218. if (extract_cpuinfo_field(&features, cpuinfo, "Features") &&
  219. has_list_item(&features, "neon")) {
  220. return HWCAP_NEON;
  221. }
  222. return 0;
  223. }
  224. static unsigned long get_hwcap2_cpuinfo(const STRING_PIECE *cpuinfo) {
  225. STRING_PIECE features;
  226. if (!extract_cpuinfo_field(&features, cpuinfo, "Features")) {
  227. return 0;
  228. }
  229. unsigned long ret = 0;
  230. if (has_list_item(&features, "aes")) {
  231. ret |= HWCAP2_AES;
  232. }
  233. if (has_list_item(&features, "pmull")) {
  234. ret |= HWCAP2_PMULL;
  235. }
  236. if (has_list_item(&features, "sha1")) {
  237. ret |= HWCAP2_SHA1;
  238. }
  239. if (has_list_item(&features, "sha2")) {
  240. ret |= HWCAP2_SHA2;
  241. }
  242. return ret;
  243. }
  244. /* has_broken_neon returns one if |in| matches a CPU known to have a broken
  245. * NEON unit. See https://crbug.com/341598. */
  246. static int has_broken_neon(const STRING_PIECE *cpuinfo) {
  247. return cpuinfo_field_equals(cpuinfo, "CPU implementer", "0x51") &&
  248. cpuinfo_field_equals(cpuinfo, "CPU architecture", "7") &&
  249. cpuinfo_field_equals(cpuinfo, "CPU variant", "0x1") &&
  250. cpuinfo_field_equals(cpuinfo, "CPU part", "0x04d") &&
  251. cpuinfo_field_equals(cpuinfo, "CPU revision", "0");
  252. }
  253. extern uint32_t OPENSSL_armcap_P;
  254. void OPENSSL_cpuid_setup(void) {
  255. char *cpuinfo_data;
  256. size_t cpuinfo_len;
  257. if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) {
  258. return;
  259. }
  260. STRING_PIECE cpuinfo;
  261. cpuinfo.data = cpuinfo_data;
  262. cpuinfo.len = cpuinfo_len;
  263. /* |getauxval| is not available on Android until API level 20. If it is
  264. * unavailable, read from /proc/self/auxv as a fallback. This is unreadable
  265. * on some versions of Android, so further fall back to /proc/cpuinfo.
  266. *
  267. * See
  268. * https://android.googlesource.com/platform/ndk/+/882ac8f3392858991a0e1af33b4b7387ec856bd2
  269. * and b/13679666 (Google-internal) for details. */
  270. unsigned long hwcap = 0;
  271. if (getauxval != NULL) {
  272. hwcap = getauxval(AT_HWCAP);
  273. }
  274. if (hwcap == 0) {
  275. hwcap = getauxval_proc(AT_HWCAP);
  276. }
  277. if (hwcap == 0) {
  278. hwcap = get_hwcap_cpuinfo(&cpuinfo);
  279. }
  280. /* Clear NEON support if known broken. */
  281. if (has_broken_neon(&cpuinfo)) {
  282. hwcap &= ~HWCAP_NEON;
  283. }
  284. /* Matching OpenSSL, only report other features if NEON is present. */
  285. if (hwcap & HWCAP_NEON) {
  286. OPENSSL_armcap_P |= ARMV7_NEON;
  287. /* Some ARMv8 Android devices don't expose AT_HWCAP2. Fall back to
  288. * /proc/cpuinfo. See https://crbug.com/596156. */
  289. unsigned long hwcap2 = 0;
  290. if (getauxval != NULL) {
  291. hwcap2 = getauxval(AT_HWCAP2);
  292. }
  293. if (hwcap2 == 0) {
  294. hwcap2 = get_hwcap2_cpuinfo(&cpuinfo);
  295. }
  296. if (hwcap2 & HWCAP2_AES) {
  297. OPENSSL_armcap_P |= ARMV8_AES;
  298. }
  299. if (hwcap2 & HWCAP2_PMULL) {
  300. OPENSSL_armcap_P |= ARMV8_PMULL;
  301. }
  302. if (hwcap2 & HWCAP2_SHA1) {
  303. OPENSSL_armcap_P |= ARMV8_SHA1;
  304. }
  305. if (hwcap2 & HWCAP2_SHA2) {
  306. OPENSSL_armcap_P |= ARMV8_SHA256;
  307. }
  308. }
  309. OPENSSL_free(cpuinfo_data);
  310. }
  311. #endif /* OPENSSL_ARM && !OPENSSL_STATIC_ARMCAP */