From 3d4901a60c662cd3be85ff9f6354b6772f75088c Mon Sep 17 00:00:00 2001 From: Jens Steube Date: Wed, 4 Jun 2025 10:09:44 +0200 Subject: [PATCH] - Add CPU SIMD detection at runtime, relevant for bridge plugins - Update BUILD_WSL.md document, add preparation for python bridge --- BUILD_WSL.md | 13 +- docker/BinaryPackage.arch | 4 +- docker/BinaryPackage.ubuntu20 | 4 +- include/cpu_features.h | 21 +++ src/bridges/bridge_argon2id_reference.c | 8 +- src/bridges/bridge_argon2id_reference.mk | 8 +- src/bridges/bridge_python_generic_hash_mp.c | 7 + src/bridges/bridge_python_generic_hash_mp.mk | 17 +- src/bridges/bridge_python_generic_hash_sp.c | 7 + src/bridges/bridge_python_generic_hash_sp.mk | 19 +- src/bridges/bridge_scrypt_jane.c | 8 +- src/bridges/bridge_scrypt_jane.mk | 8 +- src/bridges/bridge_scrypt_yescrypt.c | 8 +- src/bridges/bridge_scrypt_yescrypt.mk | 8 +- src/cpu_features.c | 181 +++++++++++++++++++ 15 files changed, 274 insertions(+), 47 deletions(-) create mode 100644 include/cpu_features.h create mode 100644 src/cpu_features.c diff --git a/BUILD_WSL.md b/BUILD_WSL.md index 8e0ff1fbc..9fc136183 100644 --- a/BUILD_WSL.md +++ b/BUILD_WSL.md @@ -1,24 +1,27 @@ -# Compiling hashcat for Windows with Windows Subsystem for Linux. +# Compiling hashcat for Windows with Windows Subsystem for Linux 2. -Tested on Windows 10 x64, should also work to build hashcat for Windows on Linux. +Tested on Windows 11 x64, should also work to build hashcat for Windows on Linux. -I had it tested with WSL2 using Ubuntu_2004.2020.424.0_x64.appx. +I had it tested with WSL2 using "Ubuntu", which at the time of writing is Ubuntu 24.04 Make sure to have the system upgraded after install (otherwise it will fail to find the gcc-mingw-w64-x86-64 package). ### Installation ### -Enable WSL. +Enable WSL2. Press the win + r key on your keyboard simultaneously and in the "Run" popup window type bash and make sure to install additional dependencies necessary for hashcat compilation ```bash -sudo apt install gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 make git +sudo apt install gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 make git zstd python3-dev git clone https://github.com/hashcat/hashcat git clone https://github.com/win-iconv/win-iconv cd win-iconv/ cmake -D WIN_ICONV_BUILD_EXECUTABLE=OFF -D CMAKE_INSTALL_PREFIX=/opt/win-iconv-64 -D CMAKE_CXX_COMPILER=$(which x86_64-w64-mingw32-g++) -D CMAKE_C_COMPILER=$(which x86_64-w64-mingw32-gcc) sudo make install cd ../ +wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst +sudo mkdir /opt/win-python +sudo tar --zstd -xf mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst -C /opt/win-python ``` ### Building ### diff --git a/docker/BinaryPackage.arch b/docker/BinaryPackage.arch index 40d736557..e6ddbd4a1 100644 --- a/docker/BinaryPackage.arch +++ b/docker/BinaryPackage.arch @@ -43,8 +43,8 @@ RUN cmake \ make -j$(nproc) && make install # Download and extract MSYS2 Python headers (still 3.12) -RUN mkdir /opt/cpython-mingw -WORKDIR /opt/cpython-mingw +RUN mkdir /opt/win-python +WORKDIR /opt/win-python RUN wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst && \ zstd -d mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst && \ tar -xf mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar diff --git a/docker/BinaryPackage.ubuntu20 b/docker/BinaryPackage.ubuntu20 index 872ec5b90..c23d5832d 100644 --- a/docker/BinaryPackage.ubuntu20 +++ b/docker/BinaryPackage.ubuntu20 @@ -79,8 +79,8 @@ ENV PATH="/opt/linux-python/bin:$PATH" WORKDIR /root -RUN mkdir /opt/cpython-mingw -WORKDIR /opt/cpython-mingw +RUN mkdir /opt/win-python +WORKDIR /opt/win-python RUN wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst RUN unzstd mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst RUN tar -xf mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar diff --git a/include/cpu_features.h b/include/cpu_features.h new file mode 100644 index 000000000..e7630fc80 --- /dev/null +++ b/include/cpu_features.h @@ -0,0 +1,21 @@ +/** + * Author......: See docs/credits.txt + * License.....: MIT + */ + +#ifndef HC_CPU_FEATURES_H +#define HC_CPU_FEATURES_H + +#include +#include + +// SIMD detection + +int cpu_supports_sse2 (); +int cpu_supports_ssse3 (); +int cpu_supports_xop (); +int cpu_supports_avx2 (); +int cpu_supports_avx512f (); +int cpu_chipset_test (); + +#endif // HC_CPU_FEATURES_H diff --git a/src/bridges/bridge_argon2id_reference.c b/src/bridges/bridge_argon2id_reference.c index 5483950c9..06c9eda22 100644 --- a/src/bridges/bridge_argon2id_reference.c +++ b/src/bridges/bridge_argon2id_reference.c @@ -7,6 +7,8 @@ #include "types.h" #include "bridges.h" #include "memory.h" +#include "shared.h" +#include "cpu_features.h" // argon2 reference @@ -133,7 +135,11 @@ static void units_term (bridge_argon2id_t *bridge_argon2id) void *platform_init () { - // bridge_argon2id_t will be our platform context + // Verify CPU features + + if (cpu_chipset_test () == -1) return NULL; + + // Allocate platform context bridge_argon2id_t *bridge_argon2id = (bridge_argon2id_t *) hcmalloc (sizeof (bridge_argon2id_t)); diff --git a/src/bridges/bridge_argon2id_reference.mk b/src/bridges/bridge_argon2id_reference.mk index d55c5bc07..d02eed8ff 100644 --- a/src/bridges/bridge_argon2id_reference.mk +++ b/src/bridges/bridge_argon2id_reference.mk @@ -15,16 +15,16 @@ endif endif ifeq ($(BUILD_MODE),cross) -bridges/bridge_argon2id_reference.so: src/bridges/bridge_argon2id_reference.c obj/combined.LINUX.a +bridges/bridge_argon2id_reference.so: src/bridges/bridge_argon2id_reference.c src/cpu_features.c obj/combined.LINUX.a $(CC_LINUX) $(CCFLAGS) $(CFLAGS_CROSS_LINUX) $^ -o $@ $(LFLAGS_CROSS_LINUX) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(ARGON2_REFERENCE_CFLAGS) -bridges/bridge_argon2id_reference.dll: src/bridges/bridge_argon2id_reference.c obj/combined.WIN.a +bridges/bridge_argon2id_reference.dll: src/bridges/bridge_argon2id_reference.c src/cpu_features.c obj/combined.WIN.a $(CC_WIN) $(CCFLAGS) $(CFLAGS_CROSS_WIN) $^ -o $@ $(LFLAGS_CROSS_WIN) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(ARGON2_REFERENCE_CFLAGS) else ifeq ($(SHARED),1) -bridges/bridge_argon2id_reference.$(BRIDGE_SUFFIX): src/bridges/bridge_argon2id_reference.c $(HASHCAT_LIBRARY) +bridges/bridge_argon2id_reference.$(BRIDGE_SUFFIX): src/bridges/bridge_argon2id_reference.c src/cpu_features.c $(HASHCAT_LIBRARY) $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(ARGON2_REFERENCE_CFLAGS) else -bridges/bridge_argon2id_reference.$(BRIDGE_SUFFIX): src/bridges/bridge_argon2id_reference.c obj/combined.NATIVE.a +bridges/bridge_argon2id_reference.$(BRIDGE_SUFFIX): src/bridges/bridge_argon2id_reference.c src/cpu_features.c obj/combined.NATIVE.a $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(ARGON2_REFERENCE_CFLAGS) endif endif diff --git a/src/bridges/bridge_python_generic_hash_mp.c b/src/bridges/bridge_python_generic_hash_mp.c index c75563ba5..9bffc87fe 100644 --- a/src/bridges/bridge_python_generic_hash_mp.c +++ b/src/bridges/bridge_python_generic_hash_mp.c @@ -8,6 +8,7 @@ #include "bridges.h" #include "memory.h" #include "shared.h" +#include "cpu_features.h" #include "dynloader.h" #if defined (_WIN) @@ -679,6 +680,12 @@ static void units_term (python_interpreter_t *python_interpreter) void *platform_init (user_options_t *user_options) { + // Verify CPU features + + if (cpu_chipset_test () == -1) return NULL; + + // Allocate platform context + python_interpreter_t *python_interpreter = (python_interpreter_t *) hcmalloc (sizeof (python_interpreter_t)); hc_python_lib_t *python = (hc_python_lib_t *) hcmalloc (sizeof (hc_python_lib_t)); diff --git a/src/bridges/bridge_python_generic_hash_mp.mk b/src/bridges/bridge_python_generic_hash_mp.mk index 075c45640..e69931382 100644 --- a/src/bridges/bridge_python_generic_hash_mp.mk +++ b/src/bridges/bridge_python_generic_hash_mp.mk @@ -1,24 +1,19 @@ PYTHON_CONFIG_FLAGS_LINUX := `python3-config --includes` - -# Experimental support for for Windows: -# $ mkdir /opt/cpython-mingw -# $ cd /opt/cpython-mingw -# $ wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst -# $ tar --zstd -xf mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst -PYTHON_CONFIG_FLAGS_WIN := -I/opt/cpython-mingw/mingw64/include/python3.12 +# See BUILD_WSL.md to prepare /opt/win-python +PYTHON_CONFIG_FLAGS_WIN := -I/opt/win-python/mingw64/include/python3.12 ifeq ($(BUILD_MODE),cross) -bridges/bridge_python_generic_hash_mp.so: src/bridges/bridge_python_generic_hash_mp.c obj/combined.LINUX.a +bridges/bridge_python_generic_hash_mp.so: src/bridges/bridge_python_generic_hash_mp.c src/cpu_features.c obj/combined.LINUX.a $(CC_LINUX) $(CCFLAGS) $(CFLAGS_CROSS_LINUX) $^ -o $@ $(LFLAGS_CROSS_LINUX) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(PYTHON_CONFIG_FLAGS_LINUX) -bridges/bridge_python_generic_hash_mp.dll: src/bridges/bridge_python_generic_hash_mp.c obj/combined.WIN.a +bridges/bridge_python_generic_hash_mp.dll: src/bridges/bridge_python_generic_hash_mp.c src/cpu_features.c obj/combined.WIN.a $(CC_WIN) $(CCFLAGS) $(CFLAGS_CROSS_WIN) $^ -o $@ $(LFLAGS_CROSS_WIN) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(PYTHON_CONFIG_FLAGS_WIN) else ifeq ($(SHARED),1) -bridges/bridge_python_generic_hash_mp.$(BRIDGE_SUFFIX): src/bridges/bridge_python_generic_hash_mp.c $(HASHCAT_LIBRARY) +bridges/bridge_python_generic_hash_mp.$(BRIDGE_SUFFIX): src/bridges/bridge_python_generic_hash_mp.c src/cpu_features.c $(HASHCAT_LIBRARY) $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(PYTHON_CONFIG_FLAGS_LINUX) $(PYTHON_CONFIG_FLAGS_WIN) else -bridges/bridge_python_generic_hash_mp.$(BRIDGE_SUFFIX): src/bridges/bridge_python_generic_hash_mp.c obj/combined.NATIVE.a +bridges/bridge_python_generic_hash_mp.$(BRIDGE_SUFFIX): src/bridges/bridge_python_generic_hash_mp.c src/cpu_features.c obj/combined.NATIVE.a $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(PYTHON_CONFIG_FLAGS_LINUX) $(PYTHON_CONFIG_FLAGS_WIN) endif endif diff --git a/src/bridges/bridge_python_generic_hash_sp.c b/src/bridges/bridge_python_generic_hash_sp.c index 87c51d32c..5bcd930c4 100644 --- a/src/bridges/bridge_python_generic_hash_sp.c +++ b/src/bridges/bridge_python_generic_hash_sp.c @@ -8,6 +8,7 @@ #include "bridges.h" #include "memory.h" #include "shared.h" +#include "cpu_features.h" #include "dynloader.h" #if defined (_WIN) @@ -687,6 +688,12 @@ static void units_term (python_interpreter_t *python_interpreter) void *platform_init (user_options_t *user_options) { + // Verify CPU features + + if (cpu_chipset_test () == -1) return NULL; + + // Allocate platform context + python_interpreter_t *python_interpreter = (python_interpreter_t *) hcmalloc (sizeof (python_interpreter_t)); hc_python_lib_t *python = (hc_python_lib_t *) hcmalloc (sizeof (hc_python_lib_t)); diff --git a/src/bridges/bridge_python_generic_hash_sp.mk b/src/bridges/bridge_python_generic_hash_sp.mk index c98c57eab..52662448c 100644 --- a/src/bridges/bridge_python_generic_hash_sp.mk +++ b/src/bridges/bridge_python_generic_hash_sp.mk @@ -1,24 +1,19 @@ PYTHON_CONFIG_FLAGS_LINUX := `python3-config --includes` - -# Experimental support for for Windows: -# $ mkdir /opt/cpython-mingw -# $ cd /opt/cpython-mingw -# $ wget https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst -# $ tar --zstd -xf mingw-w64-x86_64-python-3.12.10-1-any.pkg.tar.zst -PYTHON_CONFIG_FLAGS_WIN := -I/opt/cpython-mingw/mingw64/include/python3.12 +# See BUILD_WSL.md to prepare /opt/win-python +PYTHON_CONFIG_FLAGS_WIN := -I/opt/win-python/mingw64/include/python3.12 ifeq ($(BUILD_MODE),cross) -bridges/bridge_python_generic_hash_sp.so: src/bridges/bridge_python_generic_hash_sp.c obj/combined.LINUX.a +bridges/bridge_python_generic_hash_sp.so: src/bridges/bridge_python_generic_hash_sp.c src/cpu_features.c obj/combined.LINUX.a $(CC_LINUX) $(CCFLAGS) $(CFLAGS_CROSS_LINUX) $^ -o $@ $(LFLAGS_CROSS_LINUX) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(PYTHON_CONFIG_FLAGS_LINUX) -bridges/bridge_python_generic_hash_sp.dll: src/bridges/bridge_python_generic_hash_sp.c obj/combined.WIN.a +bridges/bridge_python_generic_hash_sp.dll: src/bridges/bridge_python_generic_hash_sp.c src/cpu_features.c obj/combined.WIN.a $(CC_WIN) $(CCFLAGS) $(CFLAGS_CROSS_WIN) $^ -o $@ $(LFLAGS_CROSS_WIN) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(PYTHON_CONFIG_FLAGS_WIN) else ifeq ($(SHARED),1) -bridges/bridge_python_generic_hash_sp.$(BRIDGE_SUFFIX): src/bridges/bridge_python_generic_hash_sp.c $(HASHCAT_LIBRARY) +bridges/bridge_python_generic_hash_sp.$(BRIDGE_SUFFIX): src/bridges/bridge_python_generic_hash_sp.c src/cpu_features.c $(HASHCAT_LIBRARY) $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(PYTHON_CONFIG_FLAGS_LINUX) $(PYTHON_CONFIG_FLAGS_WIN) else -bridges/bridge_python_generic_hash_sp.$(BRIDGE_SUFFIX): src/bridges/bridge_python_generic_hash_sp.c obj/combined.NATIVE.a +bridges/bridge_python_generic_hash_sp.$(BRIDGE_SUFFIX): src/bridges/bridge_python_generic_hash_sp.c src/cpu_features.c obj/combined.NATIVE.a $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(PYTHON_CONFIG_FLAGS_LINUX) $(PYTHON_CONFIG_FLAGS_WIN) endif endif @@ -32,6 +27,6 @@ bridges/bridge_python_generic_hash_sp.so: @echo "" @echo "WARNING: Skipping freethreaded plugin 70200: Python 3.12+ headers not found." @echo " Please read 'docs/hashcat-python-plugin-requirements.md'." - @echo "" + @echo "" endif endif diff --git a/src/bridges/bridge_scrypt_jane.c b/src/bridges/bridge_scrypt_jane.c index 39132171e..f6df8fd12 100644 --- a/src/bridges/bridge_scrypt_jane.c +++ b/src/bridges/bridge_scrypt_jane.c @@ -7,6 +7,8 @@ #include "types.h" #include "bridges.h" #include "memory.h" +#include "shared.h" +#include "cpu_features.h" #include "code/scrypt-jane-portable.h" #include "code/scrypt-jane-hash.h" @@ -106,7 +108,11 @@ static void units_term (bridge_scrypt_jane_t *bridge_scrypt_jane) void *platform_init () { - // bridge_scrypt_jane_t will be our platform context + // Verify CPU features + + if (cpu_chipset_test () == -1) return NULL; + + // Allocate platform context bridge_scrypt_jane_t *bridge_scrypt_jane = (bridge_scrypt_jane_t *) hcmalloc (sizeof (bridge_scrypt_jane_t)); diff --git a/src/bridges/bridge_scrypt_jane.mk b/src/bridges/bridge_scrypt_jane.mk index ba1fc834c..9aa789fc3 100644 --- a/src/bridges/bridge_scrypt_jane.mk +++ b/src/bridges/bridge_scrypt_jane.mk @@ -15,16 +15,16 @@ endif endif ifeq ($(BUILD_MODE),cross) -bridges/bridge_scrypt_jane.so: src/bridges/bridge_scrypt_jane.c obj/combined.LINUX.a +bridges/bridge_scrypt_jane.so: src/bridges/bridge_scrypt_jane.c src/cpu_features.c obj/combined.LINUX.a $(CC_LINUX) $(CCFLAGS) $(CFLAGS_CROSS_LINUX) $^ -o $@ $(LFLAGS_CROSS_LINUX) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(SCRYPT_JANE_CFLAGS) -bridges/bridge_scrypt_jane.dll: src/bridges/bridge_scrypt_jane.c obj/combined.WIN.a +bridges/bridge_scrypt_jane.dll: src/bridges/bridge_scrypt_jane.c src/cpu_features.c obj/combined.WIN.a $(CC_WIN) $(CCFLAGS) $(CFLAGS_CROSS_WIN) $^ -o $@ $(LFLAGS_CROSS_WIN) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(SCRYPT_JANE_CFLAGS) else ifeq ($(SHARED),1) -bridges/bridge_scrypt_jane.$(BRIDGE_SUFFIX): src/bridges/bridge_scrypt_jane.c $(HASHCAT_LIBRARY) +bridges/bridge_scrypt_jane.$(BRIDGE_SUFFIX): src/bridges/bridge_scrypt_jane.c src/cpu_features.c $(HASHCAT_LIBRARY) $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(SCRYPT_JANE_CFLAGS) else -bridges/bridge_scrypt_jane.$(BRIDGE_SUFFIX): src/bridges/bridge_scrypt_jane.c obj/combined.NATIVE.a +bridges/bridge_scrypt_jane.$(BRIDGE_SUFFIX): src/bridges/bridge_scrypt_jane.c src/cpu_features.c obj/combined.NATIVE.a $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(SCRYPT_JANE_CFLAGS) endif endif diff --git a/src/bridges/bridge_scrypt_yescrypt.c b/src/bridges/bridge_scrypt_yescrypt.c index 0096c2f3b..4e709153f 100644 --- a/src/bridges/bridge_scrypt_yescrypt.c +++ b/src/bridges/bridge_scrypt_yescrypt.c @@ -7,6 +7,8 @@ #include "types.h" #include "bridges.h" #include "memory.h" +#include "shared.h" +#include "cpu_features.h" #include "yescrypt.h" @@ -108,7 +110,11 @@ static void units_term (bridge_scrypt_yescrypt_t *bridge_scrypt_yescrypt) void *platform_init () { - // bridge_scrypt_yescrypt_t will be our platform context + // Verify CPU features + + if (cpu_chipset_test () == -1) return NULL; + + // Allocate platform context bridge_scrypt_yescrypt_t *bridge_scrypt_yescrypt = (bridge_scrypt_yescrypt_t *) hcmalloc (sizeof (bridge_scrypt_yescrypt_t)); diff --git a/src/bridges/bridge_scrypt_yescrypt.mk b/src/bridges/bridge_scrypt_yescrypt.mk index 715bbb950..046450a33 100644 --- a/src/bridges/bridge_scrypt_yescrypt.mk +++ b/src/bridges/bridge_scrypt_yescrypt.mk @@ -15,16 +15,16 @@ endif endif ifeq ($(BUILD_MODE),cross) -bridges/bridge_scrypt_yescrypt.so: src/bridges/bridge_scrypt_yescrypt.c $(SCRYPT_YESCRYPT)/yescrypt-opt.c $(SCRYPT_YESCRYPT)/sha256.c obj/combined.LINUX.a +bridges/bridge_scrypt_yescrypt.so: src/bridges/bridge_scrypt_yescrypt.c src/cpu_features.c $(SCRYPT_YESCRYPT)/yescrypt-opt.c $(SCRYPT_YESCRYPT)/sha256.c obj/combined.LINUX.a $(CC_LINUX) $(CCFLAGS) $(CFLAGS_CROSS_LINUX) $^ -o $@ $(LFLAGS_CROSS_LINUX) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(SCRYPT_YESCRYPT_CFLAGS) -bridges/bridge_scrypt_yescrypt.dll: src/bridges/bridge_scrypt_yescrypt.c $(SCRYPT_YESCRYPT)/yescrypt-opt.c $(SCRYPT_YESCRYPT)/sha256.c obj/combined.WIN.a +bridges/bridge_scrypt_yescrypt.dll: src/bridges/bridge_scrypt_yescrypt.c src/cpu_features.c $(SCRYPT_YESCRYPT)/yescrypt-opt.c $(SCRYPT_YESCRYPT)/sha256.c obj/combined.WIN.a $(CC_WIN) $(CCFLAGS) $(CFLAGS_CROSS_WIN) $^ -o $@ $(LFLAGS_CROSS_WIN) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(SCRYPT_YESCRYPT_CFLAGS) else ifeq ($(SHARED),1) -bridges/bridge_scrypt_yescrypt.$(BRIDGE_SUFFIX): src/bridges/bridge_scrypt_yescrypt.c $(SCRYPT_YESCRYPT)/yescrypt-opt.c $(SCRYPT_YESCRYPT)/sha256.c $(HASHCAT_LIBRARY) +bridges/bridge_scrypt_yescrypt.$(BRIDGE_SUFFIX): src/bridges/bridge_scrypt_yescrypt.c src/cpu_features.c $(SCRYPT_YESCRYPT)/yescrypt-opt.c $(SCRYPT_YESCRYPT)/sha256.c $(HASHCAT_LIBRARY) $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(SCRYPT_YESCRYPT_CFLAGS) else -bridges/bridge_scrypt_yescrypt.$(BRIDGE_SUFFIX): src/bridges/bridge_scrypt_yescrypt.c $(SCRYPT_YESCRYPT)/yescrypt-opt.c $(SCRYPT_YESCRYPT)/sha256.c obj/combined.NATIVE.a +bridges/bridge_scrypt_yescrypt.$(BRIDGE_SUFFIX): src/bridges/bridge_scrypt_yescrypt.c src/cpu_features.c $(SCRYPT_YESCRYPT)/yescrypt-opt.c $(SCRYPT_YESCRYPT)/sha256.c obj/combined.NATIVE.a $(CC) $(CCFLAGS) $(CFLAGS_NATIVE) $^ -o $@ $(LFLAGS_NATIVE) -shared -fPIC -D BRIDGE_INTERFACE_VERSION_CURRENT=$(BRIDGE_INTERFACE_VERSION) $(SCRYPT_YESCRYPT_CFLAGS) endif endif diff --git a/src/cpu_features.c b/src/cpu_features.c new file mode 100644 index 000000000..2f104a044 --- /dev/null +++ b/src/cpu_features.c @@ -0,0 +1,181 @@ +/** + * Author......: See docs/credits.txt + * License.....: MIT + */ + +#include "common.h" +#include "types.h" +#include "cpu_features.h" + +static inline void cpuid (u32 leaf, u32 subleaf, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) +{ + __cpuid_count (leaf, subleaf, *eax, *ebx, *ecx, *edx); +} + +static inline u64 xgetbv (u32 index) +{ + u32 eax, edx; + + __asm__ volatile (".byte 0x0f, 0x01, 0xd0" + : "=a"(eax), "=d"(edx) + : "c"(index)); + + return ((u64)edx << 32) | eax; +} + +// Should always be present on 64 bit? +int cpu_supports_sse2 () +{ + u32 eax, ebx, ecx, edx; + + cpuid(1, 0, &eax, &ebx, &ecx, &edx); + + return (edx & bit_SSE2) != 0; +} + +int cpu_supports_ssse3 () +{ + u32 eax, ebx, ecx, edx; + + cpuid (1, 0, &eax, &ebx, &ecx, &edx); + + return (ecx & bit_SSSE3) != 0; +} + +int cpu_supports_xop () +{ + u32 eax, ebx, ecx, edx; + + cpuid (0x80000000, 0, &eax, &ebx, &ecx, &edx); + + if (eax < 0x80000001) + { + return 0; + } + + cpuid (0x80000001, 0, &eax, &ebx, &ecx, &edx); + + return (ecx & (1 << 11)) != 0; // No macro for XOP +} + +int cpu_supports_avx2 () +{ + u32 eax, ebx, ecx, edx; + + cpuid (1, 0, &eax, &ebx, &ecx, &edx); + + if (!(ecx & bit_OSXSAVE) || !(ecx & bit_AVX)) + { + return 0; + } + + if ((xgetbv(0) & 0x6) != 0x6) // XMM and YMM state + { + return 0; + } + + cpuid (7, 0, &eax, &ebx, &ecx, &edx); + + return (ebx & bit_AVX2) != 0; +} + +int cpu_supports_avx512f () +{ + u32 eax, ebx, ecx, edx; + + cpuid (1, 0, &eax, &ebx, &ecx, &edx); + + if (!(ecx & bit_OSXSAVE) || !(ecx & bit_AVX)) + { + return 0; + } + + if ((xgetbv(0) & 0xE6) != 0xE6) + { + return 0; + } + + cpuid (7, 0, &eax, &ebx, &ecx, &edx); + + return (ebx & bit_AVX512F) != 0; +} + +int cpu_supports_avx512vl () +{ + u32 eax, ebx, ecx, edx; + + cpuid (1, 0, &eax, &ebx, &ecx, &edx); + + if (!(ecx & bit_OSXSAVE) || !(ecx & bit_AVX)) + { + return 0; + } + + if ((xgetbv(0) & 0xE6) != 0xE6) + { + return 0; + } + + cpuid (7, 0, &eax, &ebx, &ecx, &edx); + + return (ebx & (1u << 31)) != 0; +} + +int cpu_chipset_test () +{ + #ifdef __SSE2__ + if (cpu_supports_sse2 () == 0) + { + fprintf (stderr, "ERROR: Compiled with SSE2 but CPU does not support it.\n"); + + return -1; + } + #endif + + #ifdef __SSSE3__ + if (cpu_supports_ssse3 () == 0) + { + fprintf (stderr, "ERROR: Compiled with SSSE3 but CPU does not support it.\n"); + + return -1; + } + #endif + + #ifdef __XOP__ + if (cpu_supports_xop () == 0) + { + fprintf (stderr, "ERROR: Compiled with XOP but CPU does not support it.\n"); + + return -1; + } + #endif + + #ifdef __AVX2__ + if (cpu_supports_avx2 () == 0) + { + fprintf (stderr, "ERROR: Compiled with AVX2 but CPU does not support it.\n"); + + return -1; + } + #endif + + #ifdef __AVX512F__ + if (cpu_supports_avx512f () == 0) + { + fprintf (stderr, "ERROR: Compiled with AVX512F but CPU does not support it.\n"); + + return -1; + } + #endif + + #ifdef __AVX512VL__ + if (cpu_supports_avx512vl () == 0) + { + fprintf (stderr, "ERROR: Compiled with AVX512VL but CPU does not support it.\n"); + + return -1; + } + #endif + + return 0; +}