diff options
author | Jack Lloyd <[email protected]> | 2016-09-03 14:17:33 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-09-15 09:23:22 -0400 |
commit | be4655148cfc8cb048fd53de0965cc5e939c4cbc (patch) | |
tree | d441a6a5941d968fce80dd50a5f6010855714a77 /src/lib/block | |
parent | 272fcf00572432f64085b10132e364740d7eb093 (diff) |
Merge optimized implementations into base class
Various algorithms had an optimized implementation (for SSE2, AVX2, etc)
which was offered alongside the 'base' implementation. This is
admittedly very useful for testing, but it breaks user expectations in
bad ways. See GH #477 for background.
Now encrypting with `AES_128` (say) just runs whatever implementation
is best on the current processor/build.
Diffstat (limited to 'src/lib/block')
26 files changed, 413 insertions, 633 deletions
diff --git a/src/lib/block/aes/aes.cpp b/src/lib/block/aes/aes.cpp index 6ec21cb0c..eb24ce5a3 100644 --- a/src/lib/block/aes/aes.cpp +++ b/src/lib/block/aes/aes.cpp @@ -420,16 +420,58 @@ void aes_key_schedule(const byte key[], size_t length, void AES_128::encrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return aesni_encrypt_n(in, out, blocks); + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return ssse3_encrypt_n(in, out, blocks); + } +#endif + aes_encrypt_n(in, out, blocks, m_EK, m_ME); } void AES_128::decrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return aesni_decrypt_n(in, out, blocks); + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return ssse3_decrypt_n(in, out, blocks); + } +#endif + aes_decrypt_n(in, out, blocks, m_DK, m_MD); } void AES_128::key_schedule(const byte key[], size_t length) { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return aesni_key_schedule(key, length); + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return ssse3_key_schedule(key, length); + } +#endif + aes_key_schedule(key, length, m_EK, m_DK, m_ME, m_MD); } @@ -443,16 +485,58 @@ void AES_128::clear() void AES_192::encrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return aesni_encrypt_n(in, out, blocks); + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return ssse3_encrypt_n(in, out, blocks); + } +#endif + aes_encrypt_n(in, out, blocks, m_EK, m_ME); } void AES_192::decrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return aesni_decrypt_n(in, out, blocks); + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return ssse3_decrypt_n(in, out, blocks); + } +#endif + aes_decrypt_n(in, out, blocks, m_DK, m_MD); } void AES_192::key_schedule(const byte key[], size_t length) { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return aesni_key_schedule(key, length); + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return ssse3_key_schedule(key, length); + } +#endif + aes_key_schedule(key, length, m_EK, m_DK, m_ME, m_MD); } @@ -466,16 +550,58 @@ void AES_192::clear() void AES_256::encrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return aesni_encrypt_n(in, out, blocks); + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return ssse3_encrypt_n(in, out, blocks); + } +#endif + aes_encrypt_n(in, out, blocks, m_EK, m_ME); } void AES_256::decrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return aesni_decrypt_n(in, out, blocks); + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return ssse3_decrypt_n(in, out, blocks); + } +#endif + aes_decrypt_n(in, out, blocks, m_DK, m_MD); } void AES_256::key_schedule(const byte key[], size_t length) { +#if defined(BOTAN_HAS_AES_NI) + if(CPUID::has_aes_ni()) + { + return aesni_key_schedule(key, length); + } +#endif + +#if defined(BOTAN_HAS_AES_SSSE3) + if(CPUID::has_ssse3()) + { + return ssse3_key_schedule(key, length); + } +#endif + aes_key_schedule(key, length, m_EK, m_DK, m_ME, m_MD); } diff --git a/src/lib/block/aes/aes.h b/src/lib/block/aes/aes.h index a058adcf1..d6b334d3c 100644 --- a/src/lib/block/aes/aes.h +++ b/src/lib/block/aes/aes.h @@ -28,6 +28,18 @@ class BOTAN_DLL AES_128 final : public Block_Cipher_Fixed_Params<16, 16> private: void key_schedule(const byte key[], size_t length) override; +#if defined(BOTAN_HAS_AES_SSSE3) + void ssse3_encrypt_n(const byte in[], byte out[], size_t blocks) const; + void ssse3_decrypt_n(const byte in[], byte out[], size_t blocks) const; + void ssse3_key_schedule(const byte key[], size_t length); +#endif + +#if defined(BOTAN_HAS_AES_NI) + void aesni_encrypt_n(const byte in[], byte out[], size_t blocks) const; + void aesni_decrypt_n(const byte in[], byte out[], size_t blocks) const; + void aesni_key_schedule(const byte key[], size_t length); +#endif + secure_vector<u32bit> m_EK, m_DK; secure_vector<byte> m_ME, m_MD; }; @@ -46,6 +58,18 @@ class BOTAN_DLL AES_192 final : public Block_Cipher_Fixed_Params<16, 24> std::string name() const override { return "AES-192"; } BlockCipher* clone() const override { return new AES_192; } private: +#if defined(BOTAN_HAS_AES_SSSE3) + void ssse3_encrypt_n(const byte in[], byte out[], size_t blocks) const; + void ssse3_decrypt_n(const byte in[], byte out[], size_t blocks) const; + void ssse3_key_schedule(const byte key[], size_t length); +#endif + +#if defined(BOTAN_HAS_AES_NI) + void aesni_encrypt_n(const byte in[], byte out[], size_t blocks) const; + void aesni_decrypt_n(const byte in[], byte out[], size_t blocks) const; + void aesni_key_schedule(const byte key[], size_t length); +#endif + void key_schedule(const byte key[], size_t length) override; secure_vector<u32bit> m_EK, m_DK; @@ -66,6 +90,18 @@ class BOTAN_DLL AES_256 final : public Block_Cipher_Fixed_Params<16, 32> std::string name() const override { return "AES-256"; } BlockCipher* clone() const override { return new AES_256; } private: +#if defined(BOTAN_HAS_AES_SSSE3) + void ssse3_encrypt_n(const byte in[], byte out[], size_t blocks) const; + void ssse3_decrypt_n(const byte in[], byte out[], size_t blocks) const; + void ssse3_key_schedule(const byte key[], size_t length); +#endif + +#if defined(BOTAN_HAS_AES_NI) + void aesni_encrypt_n(const byte in[], byte out[], size_t blocks) const; + void aesni_decrypt_n(const byte in[], byte out[], size_t blocks) const; + void aesni_key_schedule(const byte key[], size_t length); +#endif + void key_schedule(const byte key[], size_t length) override; secure_vector<u32bit> m_EK, m_DK; diff --git a/src/lib/block/aes_ni/aes_ni.cpp b/src/lib/block/aes_ni/aes_ni.cpp index 51b30881f..3377f9d61 100644 --- a/src/lib/block/aes_ni/aes_ni.cpp +++ b/src/lib/block/aes_ni/aes_ni.cpp @@ -5,9 +5,8 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/aes_ni.h> +#include <botan/aes.h> #include <botan/loadstor.h> -#include <botan/cpuid.h> #include <wmmintrin.h> namespace Botan { @@ -104,7 +103,7 @@ __m128i aes_256_key_expansion(__m128i key, __m128i key2) /* * AES-128 Encryption */ -void AES_128_NI::encrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_128::aesni_encrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -180,7 +179,7 @@ void AES_128_NI::encrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-128 Decryption */ -void AES_128_NI::decrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_128::aesni_decrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -256,7 +255,7 @@ void AES_128_NI::decrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-128 Key Schedule */ -void AES_128_NI::key_schedule(const byte key[], size_t) +void AES_128::aesni_key_schedule(const byte key[], size_t) { m_EK.resize(44); m_DK.resize(44); @@ -306,18 +305,9 @@ void AES_128_NI::key_schedule(const byte key[], size_t) } /* -* Clear memory of sensitive data -*/ -void AES_128_NI::clear() - { - zap(m_EK); - zap(m_DK); - } - -/* * AES-192 Encryption */ -void AES_192_NI::encrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_192::aesni_encrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -399,7 +389,7 @@ void AES_192_NI::encrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-192 Decryption */ -void AES_192_NI::decrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_192::aesni_decrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -481,7 +471,7 @@ void AES_192_NI::decrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-192 Key Schedule */ -void AES_192_NI::key_schedule(const byte key[], size_t) +void AES_192::aesni_key_schedule(const byte key[], size_t) { m_EK.resize(52); m_DK.resize(52); @@ -528,18 +518,9 @@ void AES_192_NI::key_schedule(const byte key[], size_t) } /* -* Clear memory of sensitive data -*/ -void AES_192_NI::clear() - { - zap(m_EK); - zap(m_DK); - } - -/* * AES-256 Encryption */ -void AES_256_NI::encrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_256::aesni_encrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -627,7 +608,7 @@ void AES_256_NI::encrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-256 Decryption */ -void AES_256_NI::decrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_256::aesni_decrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -715,7 +696,7 @@ void AES_256_NI::decrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-256 Key Schedule */ -void AES_256_NI::key_schedule(const byte key[], size_t) +void AES_256::aesni_key_schedule(const byte key[], size_t) { m_EK.resize(60); m_DK.resize(60); @@ -779,15 +760,6 @@ void AES_256_NI::key_schedule(const byte key[], size_t) _mm_storeu_si128(DK_mm + 14, K0); } -/* -* Clear memory of sensitive data -*/ -void AES_256_NI::clear() - { - zap(m_EK); - zap(m_DK); - } - #undef AES_ENC_4_ROUNDS #undef AES_ENC_4_LAST_ROUNDS #undef AES_DEC_4_ROUNDS diff --git a/src/lib/block/aes_ni/aes_ni.h b/src/lib/block/aes_ni/aes_ni.h deleted file mode 100644 index 296fd7fcc..000000000 --- a/src/lib/block/aes_ni/aes_ni.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -* AES using AES-NI instructions -* (C) 2009 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_AES_NI_H__ -#define BOTAN_AES_NI_H__ - -#include <botan/block_cipher.h> - -namespace Botan { - -/** -* AES-128 using AES-NI -*/ -class BOTAN_DLL AES_128_NI final : public Block_Cipher_Fixed_Params<16, 16> - { - public: - size_t parallelism() const override { return 4; } - - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override { return "AES-128"; } - BlockCipher* clone() const override { return new AES_128_NI; } - private: - void key_schedule(const byte[], size_t) override; - - secure_vector<u32bit> m_EK, m_DK; - }; - -/** -* AES-192 using AES-NI -*/ -class BOTAN_DLL AES_192_NI final : public Block_Cipher_Fixed_Params<16, 24> - { - public: - size_t parallelism() const override { return 4; } - - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override { return "AES-192"; } - BlockCipher* clone() const override { return new AES_192_NI; } - private: - void key_schedule(const byte[], size_t) override; - - secure_vector<u32bit> m_EK, m_DK; - }; - -/** -* AES-256 using AES-NI -*/ -class BOTAN_DLL AES_256_NI final : public Block_Cipher_Fixed_Params<16, 32> - { - public: - size_t parallelism() const override { return 4; } - - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override { return "AES-256"; } - BlockCipher* clone() const override { return new AES_256_NI; } - private: - void key_schedule(const byte[], size_t) override; - - secure_vector<u32bit> m_EK, m_DK; - }; - -} - -#endif diff --git a/src/lib/block/aes_ssse3/aes_ssse3.cpp b/src/lib/block/aes_ssse3/aes_ssse3.cpp index 54e8fcbd8..eda39a7cc 100644 --- a/src/lib/block/aes_ssse3/aes_ssse3.cpp +++ b/src/lib/block/aes_ssse3/aes_ssse3.cpp @@ -10,8 +10,7 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/aes_ssse3.h> -#include <botan/cpuid.h> +#include <botan/aes.h> #include <botan/internal/ct_utils.h> #include <tmmintrin.h> @@ -337,7 +336,7 @@ __m128i aes_ssse3_decrypt(__m128i B, const __m128i* keys, size_t rounds) /* * AES-128 Encryption */ -void AES_128_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_128::ssse3_encrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -359,7 +358,7 @@ void AES_128_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-128 Decryption */ -void AES_128_SSSE3::decrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_128::ssse3_decrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -381,7 +380,7 @@ void AES_128_SSSE3::decrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-128 Key Schedule */ -void AES_128_SSSE3::key_schedule(const byte keyb[], size_t) +void AES_128::ssse3_key_schedule(const byte keyb[], size_t) { __m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81, 0x1F8391B9, 0xAF9DEEB6); @@ -416,16 +415,10 @@ void AES_128_SSSE3::key_schedule(const byte keyb[], size_t) _mm_storeu_si128(DK_mm, aes_schedule_mangle_last_dec(key)); } -void AES_128_SSSE3::clear() - { - zap(m_EK); - zap(m_DK); - } - /* * AES-192 Encryption */ -void AES_192_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_192::ssse3_encrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -447,7 +440,7 @@ void AES_192_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-192 Decryption */ -void AES_192_SSSE3::decrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_192::ssse3_decrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -469,7 +462,7 @@ void AES_192_SSSE3::decrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-192 Key Schedule */ -void AES_192_SSSE3::key_schedule(const byte keyb[], size_t) +void AES_192::ssse3_key_schedule(const byte keyb[], size_t) { __m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81, 0x1F8391B9, 0xAF9DEEB6); @@ -533,16 +526,10 @@ void AES_192_SSSE3::key_schedule(const byte keyb[], size_t) } } -void AES_192_SSSE3::clear() - { - zap(m_EK); - zap(m_DK); - } - /* * AES-256 Encryption */ -void AES_256_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_256::ssse3_encrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -564,7 +551,7 @@ void AES_256_SSSE3::encrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-256 Decryption */ -void AES_256_SSSE3::decrypt_n(const byte in[], byte out[], size_t blocks) const +void AES_256::ssse3_decrypt_n(const byte in[], byte out[], size_t blocks) const { const __m128i* in_mm = reinterpret_cast<const __m128i*>(in); __m128i* out_mm = reinterpret_cast<__m128i*>(out); @@ -586,7 +573,7 @@ void AES_256_SSSE3::decrypt_n(const byte in[], byte out[], size_t blocks) const /* * AES-256 Key Schedule */ -void AES_256_SSSE3::key_schedule(const byte keyb[], size_t) +void AES_256::ssse3_key_schedule(const byte keyb[], size_t) { __m128i rcon = _mm_set_epi32(0x702A9808, 0x4D7C7D81, 0x1F8391B9, 0xAF9DEEB6); @@ -629,10 +616,4 @@ void AES_256_SSSE3::key_schedule(const byte keyb[], size_t) _mm_storeu_si128(DK_mm + 0, aes_schedule_mangle_last_dec(key2)); } -void AES_256_SSSE3::clear() - { - zap(m_EK); - zap(m_DK); - } - } diff --git a/src/lib/block/aes_ssse3/aes_ssse3.h b/src/lib/block/aes_ssse3/aes_ssse3.h deleted file mode 100644 index 8e6c40dcd..000000000 --- a/src/lib/block/aes_ssse3/aes_ssse3.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -* AES using SSSE3 -* (C) 2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_AES_SSSE3_H__ -#define BOTAN_AES_SSSE3_H__ - -#include <botan/block_cipher.h> - -namespace Botan { - -/** -* AES-128 using SSSE3 -*/ -class BOTAN_DLL AES_128_SSSE3 final : public Block_Cipher_Fixed_Params<16, 16> - { - public: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override { return "AES-128"; } - BlockCipher* clone() const override { return new AES_128_SSSE3; } - private: - void key_schedule(const byte[], size_t) override; - - secure_vector<u32bit> m_EK, m_DK; - }; - -/** -* AES-192 using SSSE3 -*/ -class BOTAN_DLL AES_192_SSSE3 final : public Block_Cipher_Fixed_Params<16, 24> - { - public: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override { return "AES-192"; } - BlockCipher* clone() const override { return new AES_192_SSSE3; } - private: - void key_schedule(const byte[], size_t) override; - - secure_vector<u32bit> m_EK, m_DK; - }; - -/** -* AES-256 using SSSE3 -*/ -class BOTAN_DLL AES_256_SSSE3 final : public Block_Cipher_Fixed_Params<16, 32> - { - public: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - void clear() override; - std::string name() const override { return "AES-256"; } - BlockCipher* clone() const override { return new AES_256_SSSE3; } - private: - void key_schedule(const byte[], size_t) override; - - secure_vector<u32bit> m_EK, m_DK; - }; - -} - -#endif diff --git a/src/lib/block/block_cipher.cpp b/src/lib/block/block_cipher.cpp index 230d9e3a0..2388057c6 100644 --- a/src/lib/block/block_cipher.cpp +++ b/src/lib/block/block_cipher.cpp @@ -13,14 +13,6 @@ #include <botan/aes.h> #endif -#if defined(BOTAN_HAS_AES_SSSE3) - #include <botan/aes_ssse3.h> -#endif - -#if defined(BOTAN_HAS_AES_NI) - #include <botan/aes_ni.h> -#endif - #if defined(BOTAN_HAS_BLOWFISH) #include <botan/blowfish.h> #endif @@ -51,10 +43,6 @@ #include <botan/idea.h> #endif -#if defined(BOTAN_HAS_IDEA_SSE2) - #include <botan/idea_sse2.h> -#endif - #if defined(BOTAN_HAS_KASUMI) #include <botan/kasumi.h> #endif @@ -71,10 +59,6 @@ #include <botan/noekeon.h> #endif -#if defined(BOTAN_HAS_NOEKEON_SIMD) - #include <botan/noekeon_simd.h> -#endif - #if defined(BOTAN_HAS_SEED) #include <botan/seed.h> #endif @@ -83,10 +67,6 @@ #include <botan/serpent.h> #endif -#if defined(BOTAN_HAS_SERPENT_SIMD) - #include <botan/serp_simd.h> -#endif - #if defined(BOTAN_HAS_TWOFISH) #include <botan/twofish.h> #endif @@ -95,18 +75,10 @@ #include <botan/threefish.h> #endif -#if defined(BOTAN_HAS_THREEFISH_512_AVX2) - #include <botan/threefish_avx2.h> -#endif - #if defined(BOTAN_HAS_XTEA) #include <botan/xtea.h> #endif -#if defined(BOTAN_HAS_XTEA_SIMD) - #include <botan/xtea_simd.h> -#endif - namespace Botan { BlockCipher::~BlockCipher() {} @@ -143,21 +115,6 @@ BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(AES_192, "AES-192"); BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(AES_256, "AES-256"); #endif -#if defined(BOTAN_HAS_AES_NI) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_aes_ni(), AES_128_NI, "AES-128", "aes_ni", 200); -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_aes_ni(), AES_192_NI, "AES-192", "aes_ni", 200); -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_aes_ni(), AES_256_NI, "AES-256", "aes_ni", 200); -#endif - -#if defined(BOTAN_HAS_AES_SSSE3) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_ssse3(), AES_128_SSSE3, "AES-128", - "ssse3", BOTAN_SIMD_ALGORITHM_PRIO); -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_ssse3(), AES_192_SSSE3, "AES-192", - "ssse3", BOTAN_SIMD_ALGORITHM_PRIO); -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_ssse3(), AES_256_SSSE3, "AES-256", - "ssse3", BOTAN_SIMD_ALGORITHM_PRIO); -#endif - #if defined(BOTAN_HAS_BLOWFISH) BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Blowfish); #endif @@ -187,11 +144,6 @@ BOTAN_REGISTER_BLOCK_CIPHER_NAMED_1STR(GOST_28147_89, "GOST-28147-89", "R3411_94 BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(IDEA); #endif -#if defined(BOTAN_HAS_IDEA_SSE2) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_sse2(), IDEA_SSE2, "IDEA", - "sse2", BOTAN_SIMD_ALGORITHM_PRIO); -#endif - #if defined(BOTAN_HAS_KASUMI) BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(KASUMI); #endif @@ -204,11 +156,6 @@ BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(MISTY1); BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Noekeon); #endif -#if defined(BOTAN_HAS_NOEKEON_SIMD) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_simd_32(), Noekeon_SIMD, "Noekeon", - "simd32", BOTAN_SIMD_ALGORITHM_PRIO); -#endif - #if defined(BOTAN_HAS_SEED) BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(SEED); #endif @@ -217,11 +164,6 @@ BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(SEED); BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Serpent); #endif -#if defined(BOTAN_HAS_SERPENT_SIMD) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_simd_32(), Serpent_SIMD, "Serpent", - "simd32", BOTAN_SIMD_ALGORITHM_PRIO); -#endif - #if defined(BOTAN_HAS_TWOFISH) BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Twofish); #endif @@ -230,20 +172,10 @@ BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(Twofish); BOTAN_REGISTER_BLOCK_CIPHER_NAMED_NOARGS(Threefish_512, "Threefish-512"); #endif -#if defined(BOTAN_HAS_THREEFISH_512_AVX2) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_avx2(), Threefish_512_AVX2, "Threefish-512", - "avx2", BOTAN_SIMD_ALGORITHM_PRIO); -#endif - #if defined(BOTAN_HAS_XTEA) BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(XTEA); #endif -#if defined(BOTAN_HAS_XTEA_SIMD) -BOTAN_REGISTER_BLOCK_CIPHER_NOARGS_IF(CPUID::has_simd_32(), XTEA_SIMD, "XTEA", - "simd32", BOTAN_SIMD_ALGORITHM_PRIO); -#endif - #if defined(BOTAN_HAS_CASCADE) BOTAN_REGISTER_NAMED_T(BlockCipher, "Cascade", Cascade_Cipher, Cascade_Cipher::make); #endif diff --git a/src/lib/block/idea/idea.cpp b/src/lib/block/idea/idea.cpp index 4182c59a7..db55c5c26 100644 --- a/src/lib/block/idea/idea.cpp +++ b/src/lib/block/idea/idea.cpp @@ -7,6 +7,7 @@ #include <botan/idea.h> #include <botan/loadstor.h> +#include <botan/cpuid.h> #include <botan/internal/ct_utils.h> namespace Botan { @@ -113,6 +114,19 @@ void idea_op(const byte in[], byte out[], size_t blocks, const u16bit K[52]) */ void IDEA::encrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_IDEA_SSE2) + if(CPUID::has_sse2()) + { + while(blocks >= 8) + { + sse2_idea_op_8(in, out, m_EK.data()); + in += 8 * BLOCK_SIZE; + out += 8 * BLOCK_SIZE; + blocks -= 8; + } + } +#endif + idea_op(in, out, blocks, m_EK.data()); } @@ -121,6 +135,19 @@ void IDEA::encrypt_n(const byte in[], byte out[], size_t blocks) const */ void IDEA::decrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_IDEA_SSE2) + if(CPUID::has_sse2()) + { + while(blocks >= 8) + { + sse2_idea_op_8(in, out, m_DK.data()); + in += 8 * BLOCK_SIZE; + out += 8 * BLOCK_SIZE; + blocks -= 8; + } + } +#endif + idea_op(in, out, blocks, m_DK.data()); } diff --git a/src/lib/block/idea/idea.h b/src/lib/block/idea/idea.h index 59f98da9e..063ec65c4 100644 --- a/src/lib/block/idea/idea.h +++ b/src/lib/block/idea/idea.h @@ -15,7 +15,7 @@ namespace Botan { /** * IDEA */ -class BOTAN_DLL IDEA : public Block_Cipher_Fixed_Params<8, 16> +class BOTAN_DLL IDEA final : public Block_Cipher_Fixed_Params<8, 16> { public: void encrypt_n(const byte in[], byte out[], size_t blocks) const override; @@ -24,18 +24,11 @@ class BOTAN_DLL IDEA : public Block_Cipher_Fixed_Params<8, 16> void clear() override; std::string name() const override { return "IDEA"; } BlockCipher* clone() const override { return new IDEA; } - protected: - /** - * @return const reference to encryption subkeys - */ - const secure_vector<u16bit>& get_EK() const { return m_EK; } - - /** - * @return const reference to decryption subkeys - */ - const secure_vector<u16bit>& get_DK() const { return m_DK; } - private: +#if defined(BOTAN_HAS_IDEA_SSE2) + void sse2_idea_op_8(const byte in[64], byte out[64], const u16bit EK[52]) const; +#endif + void key_schedule(const byte[], size_t) override; secure_vector<u16bit> m_EK, m_DK; diff --git a/src/lib/block/idea_sse2/idea_sse2.cpp b/src/lib/block/idea_sse2/idea_sse2.cpp index c7d846e8b..4debfc95a 100644 --- a/src/lib/block/idea_sse2/idea_sse2.cpp +++ b/src/lib/block/idea_sse2/idea_sse2.cpp @@ -5,8 +5,7 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/idea_sse2.h> -#include <botan/cpuid.h> +#include <botan/idea.h> #include <botan/internal/ct_utils.h> #include <emmintrin.h> @@ -126,10 +125,12 @@ void transpose_out(__m128i& B0, __m128i& B1, __m128i& B2, __m128i& B3) B3 = _mm_unpackhi_epi32(T2, T3); } +} + /* -* IDEA encryption/decryption in SSE2 +* 8 wide IDEA encryption/decryption in SSE2 */ -void idea_op_8(const byte in[64], byte out[64], const u16bit EK[52]) +void IDEA::sse2_idea_op_8(const byte in[64], byte out[64], const u16bit EK[52]) const { CT::poison(in, 64); CT::poison(out, 64); @@ -201,43 +202,3 @@ void idea_op_8(const byte in[64], byte out[64], const u16bit EK[52]) } } - -/* -* IDEA Encryption -*/ -void IDEA_SSE2::encrypt_n(const byte in[], byte out[], size_t blocks) const - { - const u16bit* KS = &this->get_EK()[0]; - - while(blocks >= 8) - { - idea_op_8(in, out, KS); - in += 8 * BLOCK_SIZE; - out += 8 * BLOCK_SIZE; - blocks -= 8; - } - - if(blocks) - IDEA::encrypt_n(in, out, blocks); - } - -/* -* IDEA Decryption -*/ -void IDEA_SSE2::decrypt_n(const byte in[], byte out[], size_t blocks) const - { - const u16bit* KS = &this->get_DK()[0]; - - while(blocks >= 8) - { - idea_op_8(in, out, KS); - in += 8 * BLOCK_SIZE; - out += 8 * BLOCK_SIZE; - blocks -= 8; - } - - if(blocks) - IDEA::decrypt_n(in, out, blocks); - } - -} diff --git a/src/lib/block/idea_sse2/idea_sse2.h b/src/lib/block/idea_sse2/idea_sse2.h deleted file mode 100644 index 9e0df9925..000000000 --- a/src/lib/block/idea_sse2/idea_sse2.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -* IDEA in SSE2 -* (C) 2009 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_IDEA_SSE2_H__ -#define BOTAN_IDEA_SSE2_H__ - -#include <botan/idea.h> - -namespace Botan { - -/** -* IDEA in SSE2 -*/ -class BOTAN_DLL IDEA_SSE2 final : public IDEA - { - public: - size_t parallelism() const override { return 8; } - - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - BlockCipher* clone() const override { return new IDEA_SSE2; } - }; - -} - -#endif diff --git a/src/lib/block/noekeon/noekeon.cpp b/src/lib/block/noekeon/noekeon.cpp index 01f7491f3..5e7c0229e 100644 --- a/src/lib/block/noekeon/noekeon.cpp +++ b/src/lib/block/noekeon/noekeon.cpp @@ -7,6 +7,7 @@ #include <botan/noekeon.h> #include <botan/loadstor.h> +#include <botan/cpuid.h> namespace Botan { @@ -85,6 +86,19 @@ const byte Noekeon::RC[] = { */ void Noekeon::encrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_NOEKEON_SIMD) + if(CPUID::has_simd_32()) + { + while(blocks >= 4) + { + simd_encrypt_4(in, out); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + } +#endif + for(size_t i = 0; i != blocks; ++i) { u32bit A0 = load_be<u32bit>(in, 0); @@ -123,6 +137,32 @@ void Noekeon::encrypt_n(const byte in[], byte out[], size_t blocks) const */ void Noekeon::decrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_NOEKEON_SIMD) + if(CPUID::has_simd_32()) + { + /* + const size_t blocks4 = blocks / 4; + const size_t blocks_left = blocks % 4; + + in += blocks4 * BLOCK_SIZE; + out += blocks4 * BLOCK_SIZE; + blocks = blocks % 4; + + BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks4; ++i) + { + simd_encrypt_4(in + i*4*BLOCK_SIZE, out + i*4*BLOCK_SIZE); + } + */ + while(blocks >= 4) + { + simd_decrypt_4(in, out); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + } +#endif + for(size_t i = 0; i != blocks; ++i) { u32bit A0 = load_be<u32bit>(in, 0); diff --git a/src/lib/block/noekeon/noekeon.h b/src/lib/block/noekeon/noekeon.h index 4a3b9de0c..30c15a001 100644 --- a/src/lib/block/noekeon/noekeon.h +++ b/src/lib/block/noekeon/noekeon.h @@ -15,7 +15,7 @@ namespace Botan { /** * Noekeon */ -class BOTAN_DLL Noekeon : public Block_Cipher_Fixed_Params<16, 16> +class BOTAN_DLL Noekeon final : public Block_Cipher_Fixed_Params<16, 16> { public: void encrypt_n(const byte in[], byte out[], size_t blocks) const override; @@ -24,23 +24,17 @@ class BOTAN_DLL Noekeon : public Block_Cipher_Fixed_Params<16, 16> void clear() override; std::string name() const override { return "Noekeon"; } BlockCipher* clone() const override { return new Noekeon; } - protected: + private: +#if defined(BOTAN_HAS_NOEKEON_SIMD) + void simd_encrypt_4(const byte in[], byte out[]) const; + void simd_decrypt_4(const byte in[], byte out[]) const; +#endif + /** * The Noekeon round constants */ static const byte RC[17]; - /** - * @return const reference to encryption subkeys - */ - const secure_vector<u32bit>& get_EK() const { return m_EK; } - - /** - * @return const reference to decryption subkeys - */ - const secure_vector<u32bit>& get_DK() const { return m_DK; } - - private: void key_schedule(const byte[], size_t) override; secure_vector<u32bit> m_EK, m_DK; }; diff --git a/src/lib/block/noekeon_simd/info.txt b/src/lib/block/noekeon_simd/info.txt index 3b92eb206..45ff93467 100644 --- a/src/lib/block/noekeon_simd/info.txt +++ b/src/lib/block/noekeon_simd/info.txt @@ -1,4 +1,4 @@ -define NOEKEON_SIMD 20131128 +define NOEKEON_SIMD 20160903 <requires> noekeon diff --git a/src/lib/block/noekeon_simd/noekeon_simd.cpp b/src/lib/block/noekeon_simd/noekeon_simd.cpp index 07fcf19ff..e37412b5f 100644 --- a/src/lib/block/noekeon_simd/noekeon_simd.cpp +++ b/src/lib/block/noekeon_simd/noekeon_simd.cpp @@ -5,7 +5,7 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/noekeon_simd.h> +#include <botan/noekeon.h> #include <botan/internal/simd_32.h> namespace Botan { @@ -63,115 +63,91 @@ namespace Botan { /* * Noekeon Encryption */ -void Noekeon_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const +void Noekeon::simd_encrypt_4(const byte in[], byte out[]) const { - const secure_vector<u32bit>& EK = this->get_EK(); + const SIMD_32 K0 = SIMD_32(m_EK[0]); + const SIMD_32 K1 = SIMD_32(m_EK[1]); + const SIMD_32 K2 = SIMD_32(m_EK[2]); + const SIMD_32 K3 = SIMD_32(m_EK[3]); - SIMD_32 K0 = SIMD_32(EK[0]); - SIMD_32 K1 = SIMD_32(EK[1]); - SIMD_32 K2 = SIMD_32(EK[2]); - SIMD_32 K3 = SIMD_32(EK[3]); + SIMD_32 A0 = SIMD_32::load_be(in ); + SIMD_32 A1 = SIMD_32::load_be(in + 16); + SIMD_32 A2 = SIMD_32::load_be(in + 32); + SIMD_32 A3 = SIMD_32::load_be(in + 48); - while(blocks >= 4) - { - SIMD_32 A0 = SIMD_32::load_be(in ); - SIMD_32 A1 = SIMD_32::load_be(in + 16); - SIMD_32 A2 = SIMD_32::load_be(in + 32); - SIMD_32 A3 = SIMD_32::load_be(in + 48); - - SIMD_32::transpose(A0, A1, A2, A3); - - for(size_t i = 0; i != 16; ++i) - { - A0 ^= SIMD_32(RC[i]); - - NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); - - A1.rotate_left(1); - A2.rotate_left(5); - A3.rotate_left(2); + SIMD_32::transpose(A0, A1, A2, A3); - NOK_SIMD_GAMMA(A0, A1, A2, A3); - - A1.rotate_right(1); - A2.rotate_right(5); - A3.rotate_right(2); - } + for(size_t i = 0; i != 16; ++i) + { + A0 ^= SIMD_32(RC[i]); - A0 ^= SIMD_32(RC[16]); NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); - SIMD_32::transpose(A0, A1, A2, A3); + A1.rotate_left(1); + A2.rotate_left(5); + A3.rotate_left(2); - A0.store_be(out); - A1.store_be(out + 16); - A2.store_be(out + 32); - A3.store_be(out + 48); + NOK_SIMD_GAMMA(A0, A1, A2, A3); - in += 64; - out += 64; - blocks -= 4; + A1.rotate_right(1); + A2.rotate_right(5); + A3.rotate_right(2); } - if(blocks) - Noekeon::encrypt_n(in, out, blocks); + A0 ^= SIMD_32(RC[16]); + NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); + + SIMD_32::transpose(A0, A1, A2, A3); + + A0.store_be(out); + A1.store_be(out + 16); + A2.store_be(out + 32); + A3.store_be(out + 48); } /* * Noekeon Encryption */ -void Noekeon_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const +void Noekeon::simd_decrypt_4(const byte in[], byte out[]) const { - const secure_vector<u32bit>& DK = this->get_DK(); + const SIMD_32 K0 = SIMD_32(m_DK[0]); + const SIMD_32 K1 = SIMD_32(m_DK[1]); + const SIMD_32 K2 = SIMD_32(m_DK[2]); + const SIMD_32 K3 = SIMD_32(m_DK[3]); - SIMD_32 K0 = SIMD_32(DK[0]); - SIMD_32 K1 = SIMD_32(DK[1]); - SIMD_32 K2 = SIMD_32(DK[2]); - SIMD_32 K3 = SIMD_32(DK[3]); + SIMD_32 A0 = SIMD_32::load_be(in ); + SIMD_32 A1 = SIMD_32::load_be(in + 16); + SIMD_32 A2 = SIMD_32::load_be(in + 32); + SIMD_32 A3 = SIMD_32::load_be(in + 48); - while(blocks >= 4) - { - SIMD_32 A0 = SIMD_32::load_be(in ); - SIMD_32 A1 = SIMD_32::load_be(in + 16); - SIMD_32 A2 = SIMD_32::load_be(in + 32); - SIMD_32 A3 = SIMD_32::load_be(in + 48); - - SIMD_32::transpose(A0, A1, A2, A3); - - for(size_t i = 0; i != 16; ++i) - { - NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); + SIMD_32::transpose(A0, A1, A2, A3); - A0 ^= SIMD_32(RC[16-i]); - - A1.rotate_left(1); - A2.rotate_left(5); - A3.rotate_left(2); + for(size_t i = 0; i != 16; ++i) + { + NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); - NOK_SIMD_GAMMA(A0, A1, A2, A3); + A0 ^= SIMD_32(RC[16-i]); - A1.rotate_right(1); - A2.rotate_right(5); - A3.rotate_right(2); - } + A1.rotate_left(1); + A2.rotate_left(5); + A3.rotate_left(2); - NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); - A0 ^= SIMD_32(RC[0]); + NOK_SIMD_GAMMA(A0, A1, A2, A3); - SIMD_32::transpose(A0, A1, A2, A3); + A1.rotate_right(1); + A2.rotate_right(5); + A3.rotate_right(2); + } - A0.store_be(out); - A1.store_be(out + 16); - A2.store_be(out + 32); - A3.store_be(out + 48); + NOK_SIMD_THETA(A0, A1, A2, A3, K0, K1, K2, K3); + A0 ^= SIMD_32(RC[0]); - in += 64; - out += 64; - blocks -= 4; - } + SIMD_32::transpose(A0, A1, A2, A3); - if(blocks) - Noekeon::decrypt_n(in, out, blocks); + A0.store_be(out); + A1.store_be(out + 16); + A2.store_be(out + 32); + A3.store_be(out + 48); } } diff --git a/src/lib/block/noekeon_simd/noekeon_simd.h b/src/lib/block/noekeon_simd/noekeon_simd.h deleted file mode 100644 index 7907fc4ca..000000000 --- a/src/lib/block/noekeon_simd/noekeon_simd.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -* Noekeon in SIMD -* (C) 2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_NOEKEON_SIMD_H__ -#define BOTAN_NOEKEON_SIMD_H__ - -#include <botan/noekeon.h> - -namespace Botan { - -/** -* Noekeon implementation using SIMD operations -*/ -class BOTAN_DLL Noekeon_SIMD final : public Noekeon - { - public: - size_t parallelism() const override { return 4; } - - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - BlockCipher* clone() const override { return new Noekeon_SIMD; } - }; - -} - -#endif diff --git a/src/lib/block/serpent/serpent.cpp b/src/lib/block/serpent/serpent.cpp index c35e3e338..1e3699914 100644 --- a/src/lib/block/serpent/serpent.cpp +++ b/src/lib/block/serpent/serpent.cpp @@ -9,6 +9,10 @@ #include <botan/loadstor.h> #include <botan/internal/serpent_sbox.h> +#if defined(BOTAN_HAS_SERPENT_SIMD) + #include <botan/cpuid.h> +#endif + namespace Botan { namespace { @@ -53,6 +57,19 @@ inline void i_transform(u32bit& B0, u32bit& B1, u32bit& B2, u32bit& B3) */ void Serpent::encrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_SERPENT_SIMD) + if(CPUID::has_simd_32()) + { + while(blocks >= 4) + { + simd_encrypt_4(in, out); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + } +#endif + for(size_t i = 0; i != blocks; ++i) { u32bit B0 = load_le<u32bit>(in, 0); @@ -105,6 +122,19 @@ void Serpent::encrypt_n(const byte in[], byte out[], size_t blocks) const */ void Serpent::decrypt_n(const byte in[], byte out[], size_t blocks) const { +#if defined(BOTAN_HAS_SERPENT_SIMD) + if(CPUID::has_simd_32()) + { + while(blocks >= 4) + { + simd_decrypt_4(in, out); + in += 4 * BLOCK_SIZE; + out += 4 * BLOCK_SIZE; + blocks -= 4; + } + } +#endif + for(size_t i = 0; i != blocks; ++i) { u32bit B0 = load_le<u32bit>(in, 0); diff --git a/src/lib/block/serpent/serpent.h b/src/lib/block/serpent/serpent.h index b9864cf89..8f854678a 100644 --- a/src/lib/block/serpent/serpent.h +++ b/src/lib/block/serpent/serpent.h @@ -13,9 +13,10 @@ namespace Botan { /** -* Serpent, an AES finalist +* Serpent is the most conservative of the AES finalists +* http://www.cl.cam.ac.uk/~rja14/serpent.html */ -class BOTAN_DLL Serpent : public Block_Cipher_Fixed_Params<16, 16, 32, 8> +class BOTAN_DLL Serpent final : public Block_Cipher_Fixed_Params<16, 16, 32, 8> { public: void encrypt_n(const byte in[], byte out[], size_t blocks) const override; @@ -24,7 +25,22 @@ class BOTAN_DLL Serpent : public Block_Cipher_Fixed_Params<16, 16, 32, 8> void clear() override; std::string name() const override { return "Serpent"; } BlockCipher* clone() const override { return new Serpent; } + + size_t parallelism() const override { return 4; } + protected: +#if defined(BOTAN_HAS_SERPENT_SIMD) + /** + * Encrypt 4 blocks in parallel using SSE2 or AltiVec + */ + void simd_encrypt_4(const byte in[64], byte out[64]) const; + + /** + * Decrypt 4 blocks in parallel using SSE2 or AltiVec + */ + void simd_decrypt_4(const byte in[64], byte out[64]) const; +#endif + /** * For use by subclasses using SIMD, asm, etc * @return const reference to the key schedule diff --git a/src/lib/block/serpent_simd/info.txt b/src/lib/block/serpent_simd/info.txt index acb0b76d8..eedc92757 100644 --- a/src/lib/block/serpent_simd/info.txt +++ b/src/lib/block/serpent_simd/info.txt @@ -1,14 +1,6 @@ -define SERPENT_SIMD 20131128 +define SERPENT_SIMD 20160903 <requires> serpent simd </requires> - -<source> -serp_simd.cpp -</source> - -<header:public> -serp_simd.h -</header:public> diff --git a/src/lib/block/serpent_simd/serp_simd.cpp b/src/lib/block/serpent_simd/serp_simd.cpp index 02fe7d6d9..7571e5511 100644 --- a/src/lib/block/serpent_simd/serp_simd.cpp +++ b/src/lib/block/serpent_simd/serp_simd.cpp @@ -5,7 +5,7 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/serp_simd.h> +#include <botan/serpent.h> #include <botan/internal/serpent_sbox.h> #include <botan/internal/simd_32.h> @@ -15,10 +15,10 @@ namespace { #define key_xor(round, B0, B1, B2, B3) \ do { \ - B0 ^= SIMD_32(keys[4*round ]); \ - B1 ^= SIMD_32(keys[4*round+1]); \ - B2 ^= SIMD_32(keys[4*round+2]); \ - B3 ^= SIMD_32(keys[4*round+3]); \ + B0 ^= SIMD_32(m_round_key[4*round ]); \ + B1 ^= SIMD_32(m_round_key[4*round+1]); \ + B2 ^= SIMD_32(m_round_key[4*round+2]); \ + B3 ^= SIMD_32(m_round_key[4*round+3]); \ } while(0); /* @@ -52,12 +52,12 @@ namespace { B0.rotate_right(13); \ } while(0); +} + /* * SIMD Serpent Encryption of 4 blocks in parallel */ -void serpent_encrypt_4(const byte in[64], - byte out[64], - const u32bit keys[132]) +void Serpent::simd_encrypt_4(const byte in[64], byte out[64]) const { SIMD_32 B0 = SIMD_32::load_le(in); SIMD_32 B1 = SIMD_32::load_le(in + 16); @@ -113,9 +113,7 @@ void serpent_encrypt_4(const byte in[64], /* * SIMD Serpent Decryption of 4 blocks in parallel */ -void serpent_decrypt_4(const byte in[64], - byte out[64], - const u32bit keys[132]) +void Serpent::simd_decrypt_4(const byte in[64], byte out[64]) const { SIMD_32 B0 = SIMD_32::load_le(in); SIMD_32 B1 = SIMD_32::load_le(in + 16); @@ -168,48 +166,8 @@ void serpent_decrypt_4(const byte in[64], B3.store_le(out + 48); } -} - #undef key_xor #undef transform #undef i_transform -/* -* Serpent Encryption -*/ -void Serpent_SIMD::encrypt_n(const byte in[], byte out[], size_t blocks) const - { - const u32bit* KS = &(this->get_round_keys()[0]); - - while(blocks >= 4) - { - serpent_encrypt_4(in, out, KS); - in += 4 * BLOCK_SIZE; - out += 4 * BLOCK_SIZE; - blocks -= 4; - } - - if(blocks) - Serpent::encrypt_n(in, out, blocks); - } - -/* -* Serpent Decryption -*/ -void Serpent_SIMD::decrypt_n(const byte in[], byte out[], size_t blocks) const - { - const u32bit* KS = &(this->get_round_keys()[0]); - - while(blocks >= 4) - { - serpent_decrypt_4(in, out, KS); - in += 4 * BLOCK_SIZE; - out += 4 * BLOCK_SIZE; - blocks -= 4; - } - - if(blocks) - Serpent::decrypt_n(in, out, blocks); - } - } diff --git a/src/lib/block/serpent_simd/serp_simd.h b/src/lib/block/serpent_simd/serp_simd.h deleted file mode 100644 index e10d4cfe2..000000000 --- a/src/lib/block/serpent_simd/serp_simd.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -* Serpent (SIMD) -* (C) 2009 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_SERPENT_SIMD_H__ -#define BOTAN_SERPENT_SIMD_H__ - -#include <botan/serpent.h> - -namespace Botan { - -/** -* Serpent implementation using SIMD -*/ -class BOTAN_DLL Serpent_SIMD final : public Serpent - { - public: - size_t parallelism() const override { return 4; } - - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - BlockCipher* clone() const override { return new Serpent_SIMD; } - }; - -} - -#endif diff --git a/src/lib/block/threefish/threefish.cpp b/src/lib/block/threefish/threefish.cpp index c8e2aff85..a4c99936c 100644 --- a/src/lib/block/threefish/threefish.cpp +++ b/src/lib/block/threefish/threefish.cpp @@ -1,12 +1,13 @@ /* * Threefish-512 -* (C) 2013,2014 Jack Lloyd +* (C) 2013,2014,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include <botan/threefish.h> #include <botan/loadstor.h> +#include <botan/cpuid.h> namespace Botan { @@ -102,6 +103,13 @@ void Threefish_512::encrypt_n(const byte in[], byte out[], size_t blocks) const BOTAN_ASSERT(m_K.size() == 9, "Key was set"); BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); +#if defined(BOTAN_HAS_THREEFISH_AVX2) + if(CPUID::has_avx2()) + { + return avx2_encrypt_n(in, out, blocks); + } +#endif + for(size_t i = 0; i != blocks; ++i) { u64bit X0 = load_le<u64bit>(in, 0); @@ -141,6 +149,13 @@ void Threefish_512::decrypt_n(const byte in[], byte out[], size_t blocks) const BOTAN_ASSERT(m_K.size() == 9, "Key was set"); BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); +#if defined(BOTAN_HAS_THREEFISH_AVX2) + if(CPUID::has_avx2()) + { + return avx2_dencrypt_n(in, out, blocks); + } +#endif + #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \ do { \ X4 ^= X0; \ diff --git a/src/lib/block/threefish/threefish.h b/src/lib/block/threefish/threefish.h index 373600885..270e71354 100644 --- a/src/lib/block/threefish/threefish.h +++ b/src/lib/block/threefish/threefish.h @@ -15,7 +15,7 @@ namespace Botan { /** * Threefish-512 */ -class BOTAN_DLL Threefish_512 : public Block_Cipher_Fixed_Params<64, 64> +class BOTAN_DLL Threefish_512 final : public Block_Cipher_Fixed_Params<64, 64> { public: void encrypt_n(const byte in[], byte out[], size_t blocks) const override; @@ -30,6 +30,12 @@ class BOTAN_DLL Threefish_512 : public Block_Cipher_Fixed_Params<64, 64> const secure_vector<u64bit>& get_T() const { return m_T; } const secure_vector<u64bit>& get_K() const { return m_K; } private: + +#if defined(BOTAN_HAS_THREEFISH_512_AVX2) + void avx2_encrypt_n(const byte in[], byte out[], size_t blocks) const; + void avx2_decrypt_n(const byte in[], byte out[], size_t blocks) const; +#endif + void key_schedule(const byte key[], size_t key_len) override; // Interface for Skein diff --git a/src/lib/block/threefish_avx2/info.txt b/src/lib/block/threefish_avx2/info.txt index 4a3275092..907253c64 100644 --- a/src/lib/block/threefish_avx2/info.txt +++ b/src/lib/block/threefish_avx2/info.txt @@ -1,4 +1,4 @@ -define THREEFISH_512_AVX2 20131224 +define THREEFISH_512_AVX2 20160903 need_isa avx2 diff --git a/src/lib/block/threefish_avx2/threefish_avx2.cpp b/src/lib/block/threefish_avx2/threefish_avx2.cpp index 9b808a221..e0321812a 100644 --- a/src/lib/block/threefish_avx2/threefish_avx2.cpp +++ b/src/lib/block/threefish_avx2/threefish_avx2.cpp @@ -5,8 +5,7 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/threefish_avx2.h> -#include <botan/cpuid.h> +#include <botan/threefish.h> #include <immintrin.h> namespace Botan { @@ -38,7 +37,8 @@ inline void rotate_keys(__m256i& R0, __m256i& R1, __m256i R2) { /* Behold. The key schedule progresses like so. The values - loop back to the originals after the rounds are complete. + loop back to the originals after the rounds are complete + so we don't need to reload for starting the next block. R0 R1 R2 K1,K2,K3 (7,5,3,1),(8,6,4,2),(0,7,5,3) @@ -71,7 +71,7 @@ inline void rotate_keys(__m256i& R0, __m256i& R1, __m256i R2) } -void Threefish_512_AVX2::encrypt_n(const byte in[], byte out[], size_t blocks) const +void Threefish_512::avx2_encrypt_n(const byte in[], byte out[], size_t blocks) const { const u64bit* K = &get_K()[0]; const u64bit* T_64 = &get_T()[0]; @@ -245,7 +245,7 @@ void Threefish_512_AVX2::encrypt_n(const byte in[], byte out[], size_t blocks) c #undef THREEFISH_INJECT_KEY_2 } -void Threefish_512_AVX2::decrypt_n(const byte in[], byte out[], size_t blocks) const +void Threefish_512::avx2_decrypt_n(const byte in[], byte out[], size_t blocks) const { const u64bit* K = &get_K()[0]; const u64bit* T_64 = &get_T()[0]; diff --git a/src/lib/block/threefish_avx2/threefish_avx2.h b/src/lib/block/threefish_avx2/threefish_avx2.h deleted file mode 100644 index fbf2f9d8a..000000000 --- a/src/lib/block/threefish_avx2/threefish_avx2.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Threefish-512 in AVX2 -* (C) 2013 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_THREEFISH_AVX2_H__ -#define BOTAN_THREEFISH_AVX2_H__ - -#include <botan/threefish.h> - -namespace Botan { - -/** -* Threefish-512 -*/ -class BOTAN_DLL Threefish_512_AVX2 final : public Threefish_512 - { - private: - void encrypt_n(const byte in[], byte out[], size_t blocks) const override; - void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - - /* TODO: - void skein_feedfwd(const secure_vector<u64bit>& M, - const secure_vector<u64bit>& T) override; - */ - - BlockCipher* clone() const override { return new Threefish_512_AVX2; } - }; - -} - -#endif |