From 9c1cb56e99c3f9766679d91f4858f48e90ee79be Mon Sep 17 00:00:00 2001 From: mrdcvlsc Date: Thu, 14 Sep 2023 21:59:03 +0800 Subject: [PATCH] renamed macro for enabling aes neon instruction --- AES.hpp | 4 ++-- README.md | 15 ++++++++++----- makefile | 2 +- tests | Bin 52920 -> 0 bytes 4 files changed, 13 insertions(+), 8 deletions(-) delete mode 100755 tests diff --git a/AES.hpp b/AES.hpp index b1b7ddb..d80bfdc 100644 --- a/AES.hpp +++ b/AES.hpp @@ -3,7 +3,7 @@ #include -#if defined(USE_ARM_NEON_AES) +#if defined(USE_NEON_AES) #ifndef HARDWARE_ACCELERATION_ARM_NEON_AES #define HARDWARE_ACCELERATION_ARM_NEON_AES #endif @@ -30,7 +30,7 @@ #endif #if (defined(_WIN32) || defined(_WIN64) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__)) && \ - !defined(USE_CXX_AES) && !defined(USE_ARM_NEON_AES) + !defined(USE_CXX_AES) && !defined(USE_NEON_AES) #ifdef _MSC_VER #include #endif diff --git a/README.md b/README.md index aff8a1a..8f67c2f 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,14 @@ ![tests](https://github.com/mrdcvlsc/AES/actions/workflows/tests.yml/badge.svg) -This repository contains a **single header file C++ library** that provides AES encryption and decryption functionality. The library _**supports**_ both a **pure C++** implementation and optimized implementations that leverage **hardware acceleration technologies**, such as `AES-NI` for `x86-64` architectures and `ARM NEON` for `ARM` architectures. +This repository contains a **single header file C++** that provides AES encryption and decryption function that _**supports**_ both a **pure C++** implementation and optimized implementations that leverage **hardware acceleration technologies** such as; `AES-NI` for `x86-64` architectures and `ARM NEON` for `ARM` architectures. -**Please note** that this library **focuses solely** on the **encryption** and **decryption** of **AES blocks** and _**does not include padding functions or encryption modes**_. You may need to incorporate additional functions or libraries to handle padding and implement specific encryption modes, such as CBC or CTR. +> [!IMPORTANT] +> This library **focuses solely** on the **encryption** and **decryption** of **AES blocks** and _**does not include padding functions or block cipher encryption modes**_. +> +> You need to code additional functions or incorporate libraries to handle padding and encryption modes such as CBC or CTR. +> +> Here is a [CLI program for File Encryption](https://github.com/mrdcvlsc/bethela/blob/main/main.cpp) that uses some of the modules that I wrote ([AES](https://github.com/mrdcvlsc/AES), [BytePadding](https://github.com/mrdcvlsc/BytePadding), [BlockCipherModes](https://github.com/mrdcvlsc/BlockCipherModes)) which can be used as an example. ----------- @@ -38,7 +43,7 @@ To gain a speed-up performance, add the following flag when compiling for **`aar _e.g. modern android devices_. -**Additional Compiler Flag: `-D USE_ARM_NEON_AES -march=armv8-a+crypto`** +**Additional Compiler Flag: `-D USE_NEON_AES -march=armv8-a+crypto`** **CMake: `AES_IMPL=neon`** @@ -110,7 +115,7 @@ if("${AES_IMPL}" STREQUAL "aesni") target_compile_options(main PRIVATE -maes) endif() elseif("${AES_IMPL}" STREQUAL "neon") - target_compile_definitions(main PUBLIC USE_ARM_NEON_AES) + target_compile_definitions(main PUBLIC USE_NEON_AES) target_compile_options(main PRIVATE -march=armv8-a+crypto) elseif("${AES_IMPL}" STREQUAL "portable") target_compile_definitions(main PUBLIC USE_CXX_AES) @@ -146,5 +151,5 @@ The value of `` could be `aesni`, `neon` or `portable`, . 3. **comple with [Arm-NEON-AES]** ``` - g++ -o sample.exe sample.cpp -D USE_ARM_NEON_AES -march=armv8-a+crypto -O3 + g++ -o sample.exe sample.cpp -D USE_NEON_AES -march=armv8-a+crypto -O3 ``` \ No newline at end of file diff --git a/makefile b/makefile index 77d04b0..5a6e365 100644 --- a/makefile +++ b/makefile @@ -34,7 +34,7 @@ COMPILATION_MSG="compiling AES-NI version" DFLAGS:=-D USE_INTEL_AESNI -maes else ifeq ($(VERSION), neon) COMPILATION_MSG="compiling AES aarch64 neon version" -DFLAGS:=-D USE_ARM_NEON_AES -march=armv8-a+crypto +DFLAGS:=-D USE_NEON_AES -march=armv8-a+crypto endif ########################## type ########################## diff --git a/tests b/tests deleted file mode 100755 index 959820a33212db23f23c08021ccf99e0357ae048..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52920 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 ZN3k1Ouf)