diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index 2684750e16..5aab4aff24 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -237,6 +237,7 @@ add_executable( cmac/cmac_test.cc compiler_test.cc constant_time_test.cc + cpu-arm-linux_test.cc curve25519/ed25519_test.cc curve25519/spake25519_test.cc curve25519/x25519_test.cc diff --git a/crypto/cpu-arm-linux.c b/crypto/cpu-arm-linux.c index 839b632b05..91078bdf88 100644 --- a/crypto/cpu-arm-linux.c +++ b/crypto/cpu-arm-linux.c @@ -14,150 +14,23 @@ #include -#if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP) +#include "cpu-arm-linux.h" +#include "internal.h" +#if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP) #include #include -#include #include #include #include #include #include +#endif -#include "internal.h" - - -#define AT_HWCAP 16 -#define AT_HWCAP2 26 - -#define HWCAP_NEON (1 << 12) - -// See /usr/include/asm/hwcap.h on an ARM installation for the source of -// these values. -#define HWCAP2_AES (1 << 0) -#define HWCAP2_PMULL (1 << 1) -#define HWCAP2_SHA1 (1 << 2) -#define HWCAP2_SHA2 (1 << 3) - -// |getauxval| is not available on Android until API level 20. Link it as a weak -// symbol and use other methods as fallback. -unsigned long getauxval(unsigned long type) __attribute__((weak)); - -static int open_eintr(const char *path, int flags) { - int ret; - do { - ret = open(path, flags); - } while (ret < 0 && errno == EINTR); - return ret; -} - -static ssize_t read_eintr(int fd, void *out, size_t len) { - ssize_t ret; - do { - ret = read(fd, out, len); - } while (ret < 0 && errno == EINTR); - return ret; -} - -// read_full reads exactly |len| bytes from |fd| to |out|. On error or end of -// file, it returns zero. -static int read_full(int fd, void *out, size_t len) { - char *outp = out; - while (len > 0) { - ssize_t ret = read_eintr(fd, outp, len); - if (ret <= 0) { - return 0; - } - outp += ret; - len -= ret; - } - return 1; -} - -// read_file opens |path| and reads until end-of-file. On success, it returns -// one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the -// contents. Otherwise, it returns zero. -static int read_file(char **out_ptr, size_t *out_len, const char *path) { - int fd = open_eintr(path, O_RDONLY); - if (fd < 0) { - return 0; - } - - static const size_t kReadSize = 1024; - int ret = 0; - size_t cap = kReadSize, len = 0; - char *buf = OPENSSL_malloc(cap); - if (buf == NULL) { - goto err; - } - - for (;;) { - if (cap - len < kReadSize) { - size_t new_cap = cap * 2; - if (new_cap < cap) { - goto err; - } - char *new_buf = OPENSSL_realloc(buf, new_cap); - if (new_buf == NULL) { - goto err; - } - buf = new_buf; - cap = new_cap; - } - - ssize_t bytes_read = read_eintr(fd, buf + len, kReadSize); - if (bytes_read < 0) { - goto err; - } - if (bytes_read == 0) { - break; - } - len += bytes_read; - } - - *out_ptr = buf; - *out_len = len; - ret = 1; - buf = NULL; - -err: - OPENSSL_free(buf); - close(fd); - return ret; -} - -// getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv. -static unsigned long getauxval_proc(unsigned long type) { - int fd = open_eintr("/proc/self/auxv", O_RDONLY); - if (fd < 0) { - return 0; - } - struct { - unsigned long tag; - unsigned long value; - } entry; - - for (;;) { - if (!read_full(fd, &entry, sizeof(entry)) || - (entry.tag == 0 && entry.value == 0)) { - break; - } - if (entry.tag == type) { - close(fd); - return entry.value; - } - } - close(fd); - return 0; -} - -typedef struct { - const char *data; - size_t len; -} STRING_PIECE; +// The following functions are only used in ARM, but they are defined on all +// platforms for testing and fuzzing purposes. static int STRING_PIECE_equals(const STRING_PIECE *a, const char *b) { size_t b_len = strlen(b); @@ -182,6 +55,23 @@ static int STRING_PIECE_split(STRING_PIECE *out_left, STRING_PIECE *out_right, return 1; } +// STRING_PIECE_get_delimited reads a |sep|-delimited entry from |s|, writing it +// to |out| and updating |s| to point beyond it. It returns one on success and +// zero if |s| is empty. If |s| is has no copies of |sep| and is non-empty, it +// reads the entire string to |out|. +static int STRING_PIECE_get_delimited(STRING_PIECE *s, STRING_PIECE *out, char sep) { + if (s->len == 0) { + return 0; + } + if (!STRING_PIECE_split(out, s, s, sep)) { + // |s| had no instances of |sep|. Return the entire string. + *out = *s; + s->data += s->len; + s->len = 0; + } + return 1; +} + // STRING_PIECE_trim removes leading and trailing whitespace from |s|. static void STRING_PIECE_trim(STRING_PIECE *s) { while (s->len != 0 && (s->data[0] == ' ' || s->data[0] == '\t')) { @@ -195,13 +85,13 @@ static void STRING_PIECE_trim(STRING_PIECE *s) { } // extract_cpuinfo_field extracts a /proc/cpuinfo field named |field| from -// |in|. If found, it sets |*out| to the value and returns one. Otherwise, it +// |in|. If found, it sets |*out| to the value and returns one. Otherwise, it // returns zero. static int extract_cpuinfo_field(STRING_PIECE *out, const STRING_PIECE *in, const char *field) { // Process |in| one line at a time. STRING_PIECE remaining = *in, line; - while (STRING_PIECE_split(&line, &remaining, &remaining, '\n')) { + while (STRING_PIECE_get_delimited(&remaining, &line, '\n')) { STRING_PIECE key, value; if (!STRING_PIECE_split(&key, &value, &line, ':')) { continue; @@ -228,7 +118,7 @@ static int cpuinfo_field_equals(const STRING_PIECE *cpuinfo, const char *field, // one if |item| is contained in |list| and zero otherwise. static int has_list_item(const STRING_PIECE *list, const char *item) { STRING_PIECE remaining = *list, feature; - while (STRING_PIECE_split(&feature, &remaining, &remaining, ' ')) { + while (STRING_PIECE_get_delimited(&remaining, &feature, ' ')) { if (STRING_PIECE_equals(&feature, item)) { return 1; } @@ -236,7 +126,7 @@ static int has_list_item(const STRING_PIECE *list, const char *item) { return 0; } -static unsigned long get_hwcap_cpuinfo(const STRING_PIECE *cpuinfo) { +unsigned long crypto_get_arm_hwcap_from_cpuinfo(const STRING_PIECE *cpuinfo) { if (cpuinfo_field_equals(cpuinfo, "CPU architecture", "8")) { // This is a 32-bit ARM binary running on a 64-bit kernel. NEON is always // available on ARMv8. Linux omits required features, so reading the @@ -254,7 +144,7 @@ static unsigned long get_hwcap_cpuinfo(const STRING_PIECE *cpuinfo) { return 0; } -static unsigned long get_hwcap2_cpuinfo(const STRING_PIECE *cpuinfo) { +unsigned long crypto_get_arm_hwcap2_from_cpuinfo(const STRING_PIECE *cpuinfo) { STRING_PIECE features; if (!extract_cpuinfo_field(&features, cpuinfo, "Features")) { return 0; @@ -276,9 +166,7 @@ static unsigned long get_hwcap2_cpuinfo(const STRING_PIECE *cpuinfo) { return ret; } -// has_broken_neon returns one if |in| matches a CPU known to have a broken -// NEON unit. See https://crbug.com/341598. -static int has_broken_neon(const STRING_PIECE *cpuinfo) { +int crypto_cpuinfo_has_broken_neon(const STRING_PIECE *cpuinfo) { return cpuinfo_field_equals(cpuinfo, "CPU implementer", "0x51") && cpuinfo_field_equals(cpuinfo, "CPU architecture", "7") && cpuinfo_field_equals(cpuinfo, "CPU variant", "0x1") && @@ -286,6 +174,124 @@ static int has_broken_neon(const STRING_PIECE *cpuinfo) { cpuinfo_field_equals(cpuinfo, "CPU revision", "0"); } +#if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP) + +#define AT_HWCAP 16 +#define AT_HWCAP2 26 + +// |getauxval| is not available on Android until API level 20. Link it as a weak +// symbol and use other methods as fallback. +unsigned long getauxval(unsigned long type) __attribute__((weak)); + +static int open_eintr(const char *path, int flags) { + int ret; + do { + ret = open(path, flags); + } while (ret < 0 && errno == EINTR); + return ret; +} + +static ssize_t read_eintr(int fd, void *out, size_t len) { + ssize_t ret; + do { + ret = read(fd, out, len); + } while (ret < 0 && errno == EINTR); + return ret; +} + +// read_full reads exactly |len| bytes from |fd| to |out|. On error or end of +// file, it returns zero. +static int read_full(int fd, void *out, size_t len) { + char *outp = out; + while (len > 0) { + ssize_t ret = read_eintr(fd, outp, len); + if (ret <= 0) { + return 0; + } + outp += ret; + len -= ret; + } + return 1; +} + +// read_file opens |path| and reads until end-of-file. On success, it returns +// one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the +// contents. Otherwise, it returns zero. +static int read_file(char **out_ptr, size_t *out_len, const char *path) { + int fd = open_eintr(path, O_RDONLY); + if (fd < 0) { + return 0; + } + + static const size_t kReadSize = 1024; + int ret = 0; + size_t cap = kReadSize, len = 0; + char *buf = OPENSSL_malloc(cap); + if (buf == NULL) { + goto err; + } + + for (;;) { + if (cap - len < kReadSize) { + size_t new_cap = cap * 2; + if (new_cap < cap) { + goto err; + } + char *new_buf = OPENSSL_realloc(buf, new_cap); + if (new_buf == NULL) { + goto err; + } + buf = new_buf; + cap = new_cap; + } + + ssize_t bytes_read = read_eintr(fd, buf + len, kReadSize); + if (bytes_read < 0) { + goto err; + } + if (bytes_read == 0) { + break; + } + len += bytes_read; + } + + *out_ptr = buf; + *out_len = len; + ret = 1; + buf = NULL; + +err: + OPENSSL_free(buf); + close(fd); + return ret; +} + +// getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv. +static unsigned long getauxval_proc(unsigned long type) { + int fd = open_eintr("/proc/self/auxv", O_RDONLY); + if (fd < 0) { + return 0; + } + + struct { + unsigned long tag; + unsigned long value; + } entry; + + for (;;) { + if (!read_full(fd, &entry, sizeof(entry)) || + (entry.tag == 0 && entry.value == 0)) { + break; + } + if (entry.tag == type) { + close(fd); + return entry.value; + } + } + close(fd); + return 0; +} + extern uint32_t OPENSSL_armcap_P; static int g_has_broken_neon, g_needs_hwcap2_workaround; @@ -315,11 +321,11 @@ void OPENSSL_cpuid_setup(void) { hwcap = getauxval_proc(AT_HWCAP); } if (hwcap == 0) { - hwcap = get_hwcap_cpuinfo(&cpuinfo); + hwcap = crypto_get_arm_hwcap_from_cpuinfo(&cpuinfo); } // Clear NEON support if known broken. - g_has_broken_neon = has_broken_neon(&cpuinfo); + g_has_broken_neon = crypto_cpuinfo_has_broken_neon(&cpuinfo); if (g_has_broken_neon) { hwcap &= ~HWCAP_NEON; } @@ -335,7 +341,7 @@ void OPENSSL_cpuid_setup(void) { hwcap2 = getauxval(AT_HWCAP2); } if (hwcap2 == 0) { - hwcap2 = get_hwcap2_cpuinfo(&cpuinfo); + hwcap2 = crypto_get_arm_hwcap2_from_cpuinfo(&cpuinfo); g_needs_hwcap2_workaround = hwcap2 != 0; } diff --git a/crypto/cpu-arm-linux.h b/crypto/cpu-arm-linux.h new file mode 100644 index 0000000000..eabf4eac38 --- /dev/null +++ b/crypto/cpu-arm-linux.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_CPU_ARM_LINUX_H +#define OPENSSL_HEADER_CRYPTO_CPU_ARM_LINUX_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// The following symbols are defined on all platforms and exported for testing +// and fuzzing purposes. They are not exported from the shared library so the +// static linker will drop them outside of tests. + +#define HWCAP_NEON (1 << 12) + +// See /usr/include/asm/hwcap.h on an ARM installation for the source of +// these values. +#define HWCAP2_AES (1 << 0) +#define HWCAP2_PMULL (1 << 1) +#define HWCAP2_SHA1 (1 << 2) +#define HWCAP2_SHA2 (1 << 3) + +typedef struct { + const char *data; + size_t len; +} STRING_PIECE; + +// crypto_get_arm_hwcap_from_cpuinfo returns an equivalent ARM |AT_HWCAP| value +// from |cpuinfo|. +unsigned long crypto_get_arm_hwcap_from_cpuinfo(const STRING_PIECE *cpuinfo); + +// crypto_get_arm_hwcap2_from_cpuinfo returns an equivalent ARM |AT_HWCAP2| +// value from |cpuinfo|. +unsigned long crypto_get_arm_hwcap2_from_cpuinfo(const STRING_PIECE *cpuinfo); + +// crypto_cpuinfo_has_broken_neon returns one if |cpuinfo| matches a CPU known +// to have broken NEON unit and zero otherwise. See https://crbug.com/341598. +int crypto_cpuinfo_has_broken_neon(const STRING_PIECE *cpuinfo); + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_CRYPTO_CPU_ARM_LINUX_H diff --git a/crypto/cpu-arm-linux_test.cc b/crypto/cpu-arm-linux_test.cc new file mode 100644 index 0000000000..056aa8054e --- /dev/null +++ b/crypto/cpu-arm-linux_test.cc @@ -0,0 +1,236 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "cpu-arm-linux.h" + +#include + +#include + + +#if !defined(BORINGSSL_SHARED_LIBRARY) + +TEST(ARMLinuxTest, CPUInfo) { + struct Test { + const char *cpuinfo; + unsigned long hwcap; + unsigned long hwcap2; + bool broken_neon; + } kTests[] = { + // https://crbug.com/341598#c33 + { + "Processor: ARMv7 Processory rev 0 (v71)\n" + "processor: 0\n" + "BogoMIPS: 13.50\n" + "\n" + "Processor: 1\n" + "BogoMIPS: 13.50\n" + "\n" + "Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 " + "idiva idivt\n" + "CPU implementer : 0x51\n" + "CPU architecture: 7\n" + "CPU variant: 0x1\n" + "CPU part: 0x04d\n" + "CPU revision: 0\n" + "\n" + "Hardware: SAMSUNG M2\n" + "Revision: 0010\n" + "Serial: 00001e030000354e\n", + HWCAP_NEON, + 0, + true, + }, + // https://crbug.com/341598#c39 + { + "Processor : ARMv7 Processor rev 0 (v7l)\n" + "processor : 0\n" + "BogoMIPS : 13.53\n" + "\n" + "Features : swp half thumb fastmult vfp edsp neon vfpv3 tls " + "vfpv4\n" + "CPU implementer : 0x51\n" + "CPU architecture: 7\n" + "CPU variant : 0x1\n" + "CPU part : 0x04d\n" + "CPU revision : 0\n" + "\n" + "Hardware : SAMSUNG M2_ATT\n" + "Revision : 0010\n" + "Serial : 0000df0c00004d4c\n", + HWCAP_NEON, + 0, + true, + }, + // Nexus 4 from https://crbug.com/341598#c43 + { + "Processor : ARMv7 Processor rev 2 (v7l)\n" + "processor : 0\n" + "BogoMIPS : 13.53\n" + "\n" + "processor : 1\n" + "BogoMIPS : 13.53\n" + "\n" + "processor : 2\n" + "BogoMIPS : 13.53\n" + "\n" + "processor : 3\n" + "BogoMIPS : 13.53\n" + "\n" + "Features : swp half thumb fastmult vfp edsp neon vfpv3 tls " + "vfpv4 \n" + "CPU implementer : 0x51\n" + "CPU architecture: 7\n" + "CPU variant : 0x0\n" + "CPU part : 0x06f\n" + "CPU revision : 2\n" + "\n" + "Hardware : QCT APQ8064 MAKO\n" + "Revision : 000b\n" + "Serial : 0000000000000000\n", + HWCAP_NEON, + 0, + false, + }, + // Razr M from https://crbug.com/341598#c43 + { + "Processor : ARMv7 Processor rev 4 (v7l)\n" + "processor : 0\n" + "BogoMIPS : 13.53\n" + "\n" + "Features : swp half thumb fastmult vfp edsp neon vfpv3 tls " + "vfpv4\n" + "CPU implementer : 0x51\n" + "CPU architecture: 7\n" + "CPU variant : 0x1\n" + "CPU part : 0x04d\n" + "CPU revision : 4\n" + "\n" + "Hardware : msm8960dt\n" + "Revision : 82a0\n" + "Serial : 0001000201fe37a5\n", + HWCAP_NEON, + 0, + false, + }, + // Pixel 2 (truncated slightly) + { + "Processor : AArch64 Processor rev 1 (aarch64)\n" + "processor : 0\n" + "BogoMIPS : 38.00\n" + "Features : fp asimd evtstrm aes pmull sha1 sha2 crc32\n" + "CPU implementer : 0x51\n" + "CPU architecture: 8\n" + "CPU variant : 0xa\n" + "CPU part : 0x801\n" + "CPU revision : 4\n" + "\n" + "processor : 1\n" + "BogoMIPS : 38.00\n" + "Features : fp asimd evtstrm aes pmull sha1 sha2 crc32\n" + "CPU implementer : 0x51\n" + "CPU architecture: 8\n" + "CPU variant : 0xa\n" + "CPU part : 0x801\n" + "CPU revision : 4\n" + "\n" + "processor : 2\n" + "BogoMIPS : 38.00\n" + "Features : fp asimd evtstrm aes pmull sha1 sha2 crc32\n" + "CPU implementer : 0x51\n" + "CPU architecture: 8\n" + "CPU variant : 0xa\n" + "CPU part : 0x801\n" + "CPU revision : 4\n" + "\n" + "processor : 3\n" + "BogoMIPS : 38.00\n" + "Features : fp asimd evtstrm aes pmull sha1 sha2 crc32\n" + "CPU implementer : 0x51\n" + "CPU architecture: 8\n" + "CPU variant : 0xa\n" + "CPU part : 0x801\n" + "CPU revision : 4\n" + // (Extra processors omitted.) + "\n" + "Hardware : Qualcomm Technologies, Inc MSM8998\n", + HWCAP_NEON, // CPU architecture 8 implies NEON. + HWCAP2_AES | HWCAP2_PMULL | HWCAP2_SHA1 | HWCAP2_SHA2, + false, + }, + // Nexus 4 from + // Garbage should be tolerated. + { + "Blah blah blah this is definitely an ARM CPU", + 0, + 0, + false, + }, + // A hypothetical ARMv8 CPU without crc32 (and thus no trailing space + // after the last crypto entry). + { + "Features : aes pmull sha1 sha2\n" + "CPU architecture: 8\n", + HWCAP_NEON, + HWCAP2_AES | HWCAP2_PMULL | HWCAP2_SHA1 | HWCAP2_SHA2, + false, + }, + // Various combinations of ARMv8 flags. + { + "Features : aes sha1 sha2\n" + "CPU architecture: 8\n", + HWCAP_NEON, + HWCAP2_AES | HWCAP2_SHA1 | HWCAP2_SHA2, + false, + }, + { + "Features : pmull sha2\n" + "CPU architecture: 8\n", + HWCAP_NEON, + HWCAP2_PMULL | HWCAP2_SHA2, + false, + }, + { + "Features : aes aes aes not_aes aes aes \n" + "CPU architecture: 8\n", + HWCAP_NEON, + HWCAP2_AES, + false, + }, + { + "Features : \n" + "CPU architecture: 8\n", + HWCAP_NEON, + 0, + false, + }, + { + "Features : nothing\n" + "CPU architecture: 8\n", + HWCAP_NEON, + 0, + false, + }, + }; + + for (const auto &t : kTests) { + SCOPED_TRACE(t.cpuinfo); + STRING_PIECE sp = {t.cpuinfo, strlen(t.cpuinfo)}; + EXPECT_EQ(t.hwcap, crypto_get_arm_hwcap_from_cpuinfo(&sp)); + EXPECT_EQ(t.hwcap2, crypto_get_arm_hwcap2_from_cpuinfo(&sp)); + EXPECT_EQ(t.broken_neon ? 1 : 0, crypto_cpuinfo_has_broken_neon(&sp)); + } +} + +#endif // !BORINGSSL_SHARED_LIBRARY diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index b7dbd6b728..f60dc00043 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt @@ -8,6 +8,7 @@ macro(fuzzer name) set_target_properties(${name} PROPERTIES LINK_FLAGS "-fsanitize=fuzzer") endmacro() +fuzzer(arm_cpuinfo) fuzzer(bn_mod_exp) fuzzer(privkey) fuzzer(cert) diff --git a/fuzz/arm_cpuinfo.cc b/fuzz/arm_cpuinfo.cc new file mode 100644 index 0000000000..5d70046636 --- /dev/null +++ b/fuzz/arm_cpuinfo.cc @@ -0,0 +1,24 @@ +/* Copyright (c) 2018, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "../crypto/cpu-arm-linux.h" + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { + STRING_PIECE sp = {reinterpret_cast(buf), len}; + crypto_get_arm_hwcap_from_cpuinfo(&sp); + crypto_get_arm_hwcap2_from_cpuinfo(&sp); + crypto_cpuinfo_has_broken_neon(&sp); + return 0; +} diff --git a/fuzz/arm_cpuinfo_corpus/0b628cc4b99b6b797a0486c67a6ff6fa7d24b3b4 b/fuzz/arm_cpuinfo_corpus/0b628cc4b99b6b797a0486c67a6ff6fa7d24b3b4 new file mode 100644 index 0000000000..c95dfd3c57 --- /dev/null +++ b/fuzz/arm_cpuinfo_corpus/0b628cc4b99b6b797a0486c67a6ff6fa7d24b3b4 @@ -0,0 +1,17 @@ +Processor: ARMv7 Processory rev 0 (v71) +processor: 0 +BogoMIPS: 13.50 + +Processor: 1 +BogoMIPS: 13.50 + +Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt +CPU implementer : 0x51 +CPU architecture: 7 +CPU variant: 0x1 +CPU part: 0x04d +CPU revision: 0 + +Hardware: SAMSUNG M2 +Revision: 0010 +Serial: 00001e030000354e diff --git a/fuzz/arm_cpuinfo_corpus/27cdc19e630f4174c00376cdc51b1c556723b0e1 b/fuzz/arm_cpuinfo_corpus/27cdc19e630f4174c00376cdc51b1c556723b0e1 new file mode 100644 index 0000000000..89b9a0c1ce --- /dev/null +++ b/fuzz/arm_cpuinfo_corpus/27cdc19e630f4174c00376cdc51b1c556723b0e1 @@ -0,0 +1,14 @@ +Processor : ARMv7 Processor rev 0 (v7l) +processor : 0 +BogoMIPS : 13.53 + +Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 +CPU implementer : 0x51 +CPU architecture: 7 +CPU variant : 0x1 +CPU part : 0x04d +CPU revision : 0 + +Hardware : SAMSUNG M2_ATT +Revision : 0010 +Serial : 0000df0c00004d4c diff --git a/fuzz/arm_cpuinfo_corpus/8e90793faafbdfa30081e963e45fff08a360dc75 b/fuzz/arm_cpuinfo_corpus/8e90793faafbdfa30081e963e45fff08a360dc75 new file mode 100644 index 0000000000..4709eb27e9 --- /dev/null +++ b/fuzz/arm_cpuinfo_corpus/8e90793faafbdfa30081e963e45fff08a360dc75 @@ -0,0 +1,14 @@ +Processor : ARMv7 Processor rev 4 (v7l) +processor : 0 +BogoMIPS : 13.53 + +Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 +CPU implementer : 0x51 +CPU architecture: 7 +CPU variant : 0x1 +CPU part : 0x04d +CPU revision : 4 + +Hardware : msm8960dt +Revision : 82a0 +Serial : 0001000201fe37a5 diff --git a/fuzz/arm_cpuinfo_corpus/d8895d2c91f858239b2670eb211af78a71d75d02 b/fuzz/arm_cpuinfo_corpus/d8895d2c91f858239b2670eb211af78a71d75d02 new file mode 100644 index 0000000000..60a5409ebb --- /dev/null +++ b/fuzz/arm_cpuinfo_corpus/d8895d2c91f858239b2670eb211af78a71d75d02 @@ -0,0 +1,74 @@ +Processor : AArch64 Processor rev 1 (aarch64) +processor : 0 +BogoMIPS : 38.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x51 +CPU architecture: 8 +CPU variant : 0xa +CPU part : 0x801 +CPU revision : 4 + +processor : 1 +BogoMIPS : 38.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x51 +CPU architecture: 8 +CPU variant : 0xa +CPU part : 0x801 +CPU revision : 4 + +processor : 2 +BogoMIPS : 38.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x51 +CPU architecture: 8 +CPU variant : 0xa +CPU part : 0x801 +CPU revision : 4 + +processor : 3 +BogoMIPS : 38.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x51 +CPU architecture: 8 +CPU variant : 0xa +CPU part : 0x801 +CPU revision : 4 + +processor : 4 +BogoMIPS : 38.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x51 +CPU architecture: 8 +CPU variant : 0xa +CPU part : 0x800 +CPU revision : 1 + +processor : 5 +BogoMIPS : 38.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x51 +CPU architecture: 8 +CPU variant : 0xa +CPU part : 0x800 +CPU revision : 1 + +processor : 6 +BogoMIPS : 38.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x51 +CPU architecture: 8 +CPU variant : 0xa +CPU part : 0x800 +CPU revision : 1 + +processor : 7 +BogoMIPS : 38.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x51 +CPU architecture: 8 +CPU variant : 0xa +CPU part : 0x800 +CPU revision : 1 + +Hardware : Qualcomm Technologies, Inc MSM8998 diff --git a/fuzz/arm_cpuinfo_corpus/dfa633d05f10f2cb5c32b0a767efd10bf36cf3be b/fuzz/arm_cpuinfo_corpus/dfa633d05f10f2cb5c32b0a767efd10bf36cf3be new file mode 100644 index 0000000000..cfb8017748 --- /dev/null +++ b/fuzz/arm_cpuinfo_corpus/dfa633d05f10f2cb5c32b0a767efd10bf36cf3be @@ -0,0 +1,23 @@ +Processor : ARMv7 Processor rev 2 (v7l) +processor : 0 +BogoMIPS : 13.53 + +processor : 1 +BogoMIPS : 13.53 + +processor : 2 +BogoMIPS : 13.53 + +processor : 3 +BogoMIPS : 13.53 + +Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 +CPU implementer : 0x51 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0x06f +CPU revision : 2 + +Hardware : QCT APQ8064 MAKO +Revision : 000b +Serial : 0000000000000000