diff --git a/CMakeLists.txt b/CMakeLists.txt index e94a50f4..ee8e201b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,42 +26,57 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug) endif() -# Compiler flags customization (by vendor) -if(NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -maes") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic") - # TODO: The following is incompatible with static build and enabled hardening - # for OpenWRT. - # Multiple definitions of __stack_chk_fail (libssp & libc) - set(CMAKE_CXX_FLAGS_MINSIZEREL - "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections") - # -flto is added from above - set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") +### TODO(unassigned): improve detection and use-case +# Minimal processor detection (needed for ARM build) +set(CPU "${CMAKE_SYSTEM_PROCESSOR}") +string(SUBSTRING "${CPU}" 0 3 PARSE_ARM) +if (CPU STREQUAL "aarch64" OR PARSE_ARM STREQUAL "arm") + set(ARM TRUE) endif() -# Check for c++14 support +# Detect minimum compiler version +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.3) + message(FATAL_ERROR "GCC 4.9.3 or higher is required") + endif() + set(GNU TRUE) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) + message(FATAL_ERROR "Clang 3.5 or higher is required") + endif() + set(Clang TRUE) # TODO(unassigned): make use of this +endif() + +# Check for C++14 support (minimum version compilers guarantee this) include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++1y" CXX14_SUPPORTED) if(CXX14_SUPPORTED) - add_definitions("-std=c++1y") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") elseif(NOT MSVC) message(FATAL_ERROR "C++14 standard not supported by compiler. See building instructions.") endif() -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.3) - message(FATAL_ERROR "GCC 4.9.3 or higher is required") +### TODO(unassigned): review, cleanup, improve +# Compiler flags (by vendor) +if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch") + if(NOT ARM) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") endif() + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic") + # TODO: The following is incompatible with static build and enabled hardening + # for OpenWRT. + # Multiple definitions of __stack_chk_fail (libssp & libc) + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections") + # -flto is added from above + set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") if(WITH_HARDENING) add_definitions("-D_FORTIFY_SOURCE=2") - set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security -Werror=format-security") - set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -fstack-protector-strong -fPIE --param ssp-buffer-size=4 -z relro -z now") - endif() -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) - message(FATAL_ERROR "Clang 3.5 or higher is required") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security -Werror=format-security") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-strong -fPIE --param ssp-buffer-size=4") + if(GNU) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -z relro -z now") + endif() endif() endif() diff --git a/src/core/crypto/impl/cryptopp/aes.cc b/src/core/crypto/impl/cryptopp/aes.cc index 53914b84..a4f5224c 100644 --- a/src/core/crypto/impl/cryptopp/aes.cc +++ b/src/core/crypto/impl/cryptopp/aes.cc @@ -47,6 +47,7 @@ namespace core { /// TODO(unassigned): if we switch libraries, we should move AES-NI elsewhere. /// TODO(unassigned): ARM support? MSVC x86-64 support? bool HasAESNI() { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI unsigned int eax, ecx; // We only need ECX const unsigned int flag = (1 << 25); // ECX bit 25 for AES-NI LogPrint(eLogDebug, "Crypto: checking for AES-NI..."); @@ -59,6 +60,7 @@ bool HasAESNI() { LogPrint(eLogDebug, "Crypto: AES-NI is available!"); return true; } +#endif LogPrint(eLogDebug, "Crypto: AES-NI is not available. Using library."); return false; } @@ -81,6 +83,7 @@ class ECBCryptoAESNI { } protected: +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI void ExpandKey( const AESKey& key) { __asm__( @@ -116,6 +119,7 @@ class ECBCryptoAESNI { : [key]"r"((const std::uint8_t *)key), [sched]"r"(GetKeySchedule()) // Input : "%xmm1", "%xmm2", "%xmm3", "%xmm4", "memory"); // Clobbered } +#endif private: AESAlignedBuffer<240> m_KeySchedule; // 14 rounds for AES-256, 240 bytes @@ -141,7 +145,9 @@ class ECBEncryption::ECBEncryptionImpl : public ECBCryptoAESNI { void SetKey( const AESKey& key) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI ExpandKey(key); +#endif } else { try { m_Encryption.SetKey(key, 32); @@ -156,6 +162,7 @@ class ECBEncryption::ECBEncryptionImpl : public ECBCryptoAESNI { const CipherBlock* in, CipherBlock* out) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI __asm__( "movups (%[in]), %%xmm0 \n" EncryptAES256(sched) @@ -163,6 +170,7 @@ class ECBEncryption::ECBEncryptionImpl : public ECBCryptoAESNI { : : [sched]"r"(GetKeySchedule()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"); +#endif } else { try { m_Encryption.ProcessData(out->buf, in->buf, 16); @@ -218,6 +226,7 @@ class ECBDecryption::ECBDecryptionImpl : public ECBCryptoAESNI { void SetKey( const AESKey& key) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI ExpandKey(key); // expand encryption key first // then invert it using aesimc __asm__( @@ -237,6 +246,7 @@ class ECBDecryption::ECBDecryptionImpl : public ECBCryptoAESNI { : : [shed]"r"(GetKeySchedule()) : "%xmm0", "memory"); +#endif } else { try { m_Decryption.SetKey(key, 32); @@ -251,6 +261,7 @@ class ECBDecryption::ECBDecryptionImpl : public ECBCryptoAESNI { const CipherBlock* in, CipherBlock* out) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI __asm__( "movups (%[in]), %%xmm0 \n" DecryptAES256(sched) @@ -258,6 +269,7 @@ class ECBDecryption::ECBDecryptionImpl : public ECBCryptoAESNI { : : [sched]"r"(GetKeySchedule()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"); +#endif } else { try { m_Decryption.ProcessData(out->buf, in->buf, 16); @@ -330,6 +342,7 @@ class CBCEncryption::CBCEncryptionImpl { const CipherBlock* in, CipherBlock* out) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI __asm__( "movups (%[iv]), %%xmm1 \n" "1: \n" @@ -348,6 +361,7 @@ class CBCEncryption::CBCEncryptionImpl { [sched]"r"(m_ECBEncryption.GetKeySchedule()), [in]"r"(in), [out]"r"(out), [num]"r"(num_blocks) : "%xmm0", "%xmm1", "cc", "memory"); +#endif } else { for (int i = 0; i < num_blocks; i++) { m_LastBlock ^= in[i]; @@ -374,6 +388,7 @@ class CBCEncryption::CBCEncryptionImpl { const std::uint8_t* in, std::uint8_t* out) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI __asm__( "movups (%[iv]), %%xmm1 \n" "movups (%[in]), %%xmm0 \n" @@ -386,6 +401,7 @@ class CBCEncryption::CBCEncryptionImpl { [sched]"r"(m_ECBEncryption.GetKeySchedule()), [in]"r"(in), [out]"r"(out) : "%xmm0", "%xmm1", "memory"); +#endif } else { Encrypt( 1, @@ -478,6 +494,7 @@ class CBCDecryption::CBCDecryptionImpl { const CipherBlock* in, CipherBlock* out) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI __asm__( "movups (%[iv]), %%xmm1 \n" "1: \n" @@ -496,6 +513,7 @@ class CBCDecryption::CBCDecryptionImpl { : [iv]"r"(&m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out), [num]"r"(num_blocks) : "%xmm0", "%xmm1", "%xmm2", "cc", "memory"); +#endif } else { for (int i = 0; i < num_blocks; i++) { CipherBlock tmp = in[i]; @@ -523,6 +541,7 @@ class CBCDecryption::CBCDecryptionImpl { const std::uint8_t* in, std::uint8_t* out) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI __asm__( "movups (%[iv]), %%xmm1 \n" "movups (%[in]), %%xmm0 \n" @@ -534,6 +553,7 @@ class CBCDecryption::CBCDecryptionImpl { : [iv]"r"(&m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule()), [in]"r"(in), [out]"r"(out) : "%xmm0", "%xmm1", "memory"); +#endif } else { Decrypt( 1, diff --git a/src/core/crypto/impl/cryptopp/tunnel.cc b/src/core/crypto/impl/cryptopp/tunnel.cc index e4e3e40f..75cbf523 100644 --- a/src/core/crypto/impl/cryptopp/tunnel.cc +++ b/src/core/crypto/impl/cryptopp/tunnel.cc @@ -64,6 +64,7 @@ class TunnelEncryption::TunnelEncryptionImpl { const std::uint8_t* in, std::uint8_t* out) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI __asm__( // encrypt IV "movups (%[in]), %%xmm0 \n" @@ -88,6 +89,7 @@ class TunnelEncryption::TunnelEncryptionImpl { [sched_l]"r"(m_ECBLayerEncryption.GetKeySchedule()), [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes : "%xmm0", "%xmm1", "cc", "memory"); +#endif } else { m_IVEncryption.Encrypt( // iv (const CipherBlock *)in, @@ -148,6 +150,7 @@ class TunnelDecryption::TunnelDecryptionImpl { const std::uint8_t* in, std::uint8_t* out) { if (UsingAESNI()) { +#if defined(__x86_64__) || defined(_M_X64) // TODO(unassigned): hack until we implement ARM AES-NI __asm__( // decrypt IV "movups (%[in]), %%xmm0 \n" @@ -173,6 +176,7 @@ class TunnelDecryption::TunnelDecryptionImpl { [sched_l]"r"(m_ECBLayerDecryption.GetKeySchedule()), [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes : "%xmm0", "%xmm1", "%xmm2", "cc", "memory"); +#endif } else { m_IVDecryption.Decrypt( (const CipherBlock *)in,