aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/news.rst16
-rw-r--r--src/lib/block/aes/aes.cpp149
-rw-r--r--src/lib/block/aes/aes.h40
-rw-r--r--src/lib/block/aes_ni/aes_ni.cpp48
-rw-r--r--src/lib/block/aes_ni/aes_ni.h77
-rw-r--r--src/lib/block/aes_ssse3/aes_ssse3.cpp39
-rw-r--r--src/lib/block/aes_ssse3/aes_ssse3.h71
-rw-r--r--src/lib/block/block_cipher.cpp68
-rw-r--r--src/lib/block/block_cipher.h7
-rw-r--r--src/lib/block/idea/idea.cpp39
-rw-r--r--src/lib/block/idea/idea.h19
-rw-r--r--src/lib/block/idea_sse2/idea_sse2.cpp49
-rw-r--r--src/lib/block/idea_sse2/idea_sse2.h31
-rw-r--r--src/lib/block/noekeon/noekeon.cpp52
-rw-r--r--src/lib/block/noekeon/noekeon.h21
-rw-r--r--src/lib/block/noekeon_simd/info.txt2
-rw-r--r--src/lib/block/noekeon_simd/noekeon_simd.cpp142
-rw-r--r--src/lib/block/noekeon_simd/noekeon_simd.h31
-rw-r--r--src/lib/block/serpent/serpent.cpp42
-rw-r--r--src/lib/block/serpent/serpent.h21
-rw-r--r--src/lib/block/serpent_simd/info.txt10
-rw-r--r--src/lib/block/serpent_simd/serp_simd.cpp60
-rw-r--r--src/lib/block/serpent_simd/serp_simd.h31
-rw-r--r--src/lib/block/threefish/threefish.cpp29
-rw-r--r--src/lib/block/threefish/threefish.h9
-rw-r--r--src/lib/block/threefish_avx2/info.txt2
-rw-r--r--src/lib/block/threefish_avx2/threefish_avx2.cpp10
-rw-r--r--src/lib/block/threefish_avx2/threefish_avx2.h34
-rw-r--r--src/lib/hash/hash.cpp9
-rw-r--r--src/lib/hash/hash.h6
-rw-r--r--src/lib/hash/sha1/sha160.cpp11
-rw-r--r--src/lib/hash/sha1/sha160.h33
-rw-r--r--src/lib/hash/sha1_sse2/info.txt2
-rw-r--r--src/lib/hash/sha1_sse2/sha1_sse2.cpp38
-rw-r--r--src/lib/hash/sha1_sse2/sha1_sse2.h29
-rw-r--r--src/lib/mac/mac.h7
-rw-r--r--src/lib/modes/aead/gcm/gcm.cpp10
-rw-r--r--src/lib/modes/aead/gcm/gcm.h2
-rw-r--r--src/lib/modes/cipher_mode.h14
-rw-r--r--src/lib/prov/openssl/openssl_block.cpp1
-rw-r--r--src/lib/prov/openssl/openssl_hash.cpp1
-rw-r--r--src/lib/prov/openssl/openssl_rc4.cpp2
-rw-r--r--src/lib/pubkey/dh/dh.cpp4
-rw-r--r--src/lib/stream/chacha/chacha.cpp12
-rw-r--r--src/lib/stream/chacha/chacha.h2
-rw-r--r--src/lib/stream/stream_cipher.h6
-rw-r--r--src/lib/utils/cpuid.cpp29
-rw-r--r--src/lib/utils/cpuid.h114
-rw-r--r--src/tests/data/aead/gcm.vec3
-rw-r--r--src/tests/data/block/aes.vec3
-rw-r--r--src/tests/data/block/idea.vec3
-rw-r--r--src/tests/data/block/noekeon.vec3
-rw-r--r--src/tests/data/block/serpent.vec3
-rw-r--r--src/tests/data/block/threefish.vec3
-rw-r--r--src/tests/data/hash/sha1.vec2
-rw-r--r--src/tests/data/stream/chacha.vec3
-rw-r--r--src/tests/main.cpp20
-rw-r--r--src/tests/test_block.cpp8
-rw-r--r--src/tests/test_hash.cpp8
-rw-r--r--src/tests/test_mac.cpp9
-rw-r--r--src/tests/test_modes.cpp1
-rw-r--r--src/tests/test_stream.cpp8
-rw-r--r--src/tests/tests.cpp117
-rw-r--r--src/tests/tests.h5
64 files changed, 875 insertions, 805 deletions
diff --git a/doc/news.rst b/doc/news.rst
index fce6bfee8..012ad81fa 100644
--- a/doc/news.rst
+++ b/doc/news.rst
@@ -20,6 +20,22 @@ Version 1.11.32, Not Yet Released
* Add a new TLS Callbacks interface. Compatability with previous versions is
maintained. The documentation has been updated accordingly. GH #457 and #567
+* How the library presents optimized algorithm implementations has changed. For
+ example with the algorithm AES-128, previously there were three BlockCipher
+ classes AES_128, AES_128_SSSE3, and AES_128_NI which used (resp) a table-based
+ implementation vulnerable to side channels, a constant time version using
+ SSSE3 SIMD extensions on modern x86, and x86 AES-NI instructions. Using the
+ correct version at runtime required using `BlockCipher::create`. Now, only the
+ class AES_128 is presented, and the best available version is always used
+ based on CPUID checks. The tests have been extended to selectively disable
+ CPUID bits to ensure all available versions are tested.
+
+ Removes API classes AES_128_NI, AES_192_NI, AES_256_NI, AES_128_SSSE3,
+ AES_192_SSSE3 AES_256_SSSE3, IDEA_SSE2, Noekeon_SIMD, Serpent_SIMD,
+ Threefish_512_AVX2, SHA_160_SSE2
+
+ GH #477 #623
+
* The deprecated algorithms Rabin-Williams, Nyberg-Rueppel, MARS, RC2, RC5, RC6,
SAFER-SK, TEA, MD2, HAS-160, and RIPEMD-128 have been removed. GH #580
diff --git a/src/lib/block/aes/aes.cpp b/src/lib/block/aes/aes.cpp
index 6ec21cb0c..39f5bd0db 100644
--- a/src/lib/block/aes/aes.cpp
+++ b/src/lib/block/aes/aes.cpp
@@ -416,20 +416,85 @@ void aes_key_schedule(const byte key[], size_t length,
copy_mem(DK.data(), XDK.data(), DK.size());
}
+const char* aes_provider()
+ {
+#if defined(BOTAN_HAS_AES_NI)
+ if(CPUID::has_aes_ni())
+ {
+ return "aesni";
+ }
+#endif
+
+#if defined(BOTAN_HAS_AES_SSSE3)
+ if(CPUID::has_ssse3())
+ {
+ return "ssse3";
+ }
+#endif
+
+ return "base";
+ }
+
}
+std::string AES_128::provider() const { return aes_provider(); }
+std::string AES_192::provider() const { return aes_provider(); }
+std::string AES_256::provider() const { return aes_provider(); }
+
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 +508,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 +573,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..6bd38cada 100644
--- a/src/lib/block/aes/aes.h
+++ b/src/lib/block/aes/aes.h
@@ -23,11 +23,24 @@ class BOTAN_DLL AES_128 final : public Block_Cipher_Fixed_Params<16, 16>
void clear() override;
+ std::string provider() const override;
std::string name() const override { return "AES-128"; }
BlockCipher* clone() const override { return new AES_128; }
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;
};
@@ -43,9 +56,22 @@ class BOTAN_DLL AES_192 final : public Block_Cipher_Fixed_Params<16, 24>
void clear() override;
+ std::string provider() const override;
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;
@@ -63,9 +89,23 @@ class BOTAN_DLL AES_256 final : public Block_Cipher_Fixed_Params<16, 32>
void clear() override;
+ std::string provider() const override;
+
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/block_cipher.h b/src/lib/block/block_cipher.h
index 0f4c2c1c5..b16468958 100644
--- a/src/lib/block/block_cipher.h
+++ b/src/lib/block/block_cipher.h
@@ -10,6 +10,7 @@
#include <botan/scan_name.h>
#include <botan/sym_algo.h>
+#include <string>
namespace Botan {
@@ -53,6 +54,12 @@ class BOTAN_DLL BlockCipher : public SymmetricAlgorithm
}
/**
+ * @return provider information about this implementation. Default is "base",
+ * might also return "sse2", "avx2", "openssl", or some other arbitrary string.
+ */
+ virtual std::string provider() const { return "base"; }
+
+ /**
* Encrypt a block.
* @param in The plaintext block to be encrypted as a byte array.
* Must be of length block_size().
diff --git a/src/lib/block/idea/idea.cpp b/src/lib/block/idea/idea.cpp
index 4182c59a7..85cc5e757 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 {
@@ -108,11 +109,36 @@ void idea_op(const byte in[], byte out[], size_t blocks, const u16bit K[52])
}
+std::string IDEA::provider() const
+ {
+#if defined(BOTAN_HAS_IDEA_SSE2)
+ if(CPUID::has_sse2())
+ {
+ return "sse2";
+ }
+#endif
+
+ return "base";
+ }
+
/*
* IDEA Encryption
*/
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 +147,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..eb391a0c8 100644
--- a/src/lib/block/idea/idea.h
+++ b/src/lib/block/idea/idea.h
@@ -15,27 +15,22 @@ 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;
void decrypt_n(const byte in[], byte out[], size_t blocks) const override;
void clear() override;
+
+ std::string provider() const 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..eac0979a4 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 {
@@ -72,6 +73,18 @@ inline void gamma(u32bit& A0, u32bit& A1, u32bit& A2, u32bit& A3)
}
+std::string Noekeon::provider() const
+ {
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ if(CPUID::has_simd_32())
+ {
+ return "simd";
+ }
+#endif
+
+ return "base";
+ }
+
/*
* Noekeon Round Constants
*/
@@ -85,6 +98,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 +149,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..b0aa4218c 100644
--- a/src/lib/block/noekeon/noekeon.h
+++ b/src/lib/block/noekeon/noekeon.h
@@ -15,32 +15,27 @@ 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;
void decrypt_n(const byte in[], byte out[], size_t blocks) const override;
+ std::string provider() const override;
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..07088211d 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);
@@ -201,4 +231,16 @@ void Serpent::clear()
zap(m_round_key);
}
+std::string Serpent::provider() const
+ {
+#if defined(BOTAN_HAS_SERPENT_SIMD)
+ if(CPUID::has_simd_32())
+ {
+ return "simd";
+ }
+#endif
+
+ return "base";
+ }
+
}
diff --git a/src/lib/block/serpent/serpent.h b/src/lib/block/serpent/serpent.h
index b9864cf89..218772e0c 100644
--- a/src/lib/block/serpent/serpent.h
+++ b/src/lib/block/serpent/serpent.h
@@ -13,18 +13,35 @@
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;
void decrypt_n(const byte in[], byte out[], size_t blocks) const override;
void clear() override;
+ std::string provider() const 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..f592021fb 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 {
@@ -97,11 +98,30 @@ void Threefish_512::skein_feedfwd(const secure_vector<u64bit>& M,
m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
}
+std::string Threefish_512::provider() const
+ {
+#if defined(BOTAN_HAS_THREEFISH_512_AVX2)
+ if(CPUID::has_avx2())
+ {
+ return "avx2";
+ }
+#endif
+
+ return "base";
+ }
+
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_512_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 +161,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_512_AVX2)
+ if(CPUID::has_avx2())
+ {
+ return avx2_decrypt_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..b02239c93 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;
@@ -24,12 +24,19 @@ class BOTAN_DLL Threefish_512 : public Block_Cipher_Fixed_Params<64, 64>
void set_tweak(const byte tweak[], size_t len);
void clear() override;
+ std::string provider() const override;
std::string name() const override { return "Threefish-512"; }
BlockCipher* clone() const override { return new Threefish_512; }
protected:
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
diff --git a/src/lib/hash/hash.cpp b/src/lib/hash/hash.cpp
index 42a7666b6..5a31763d1 100644
--- a/src/lib/hash/hash.cpp
+++ b/src/lib/hash/hash.cpp
@@ -45,10 +45,6 @@
#include <botan/sha160.h>
#endif
-#if defined(BOTAN_HAS_SHA1_SSE2)
- #include <botan/sha1_sse2.h>
-#endif
-
#if defined(BOTAN_HAS_SHA2_32)
#include <botan/sha2_32.h>
#endif
@@ -155,11 +151,6 @@ BOTAN_REGISTER_HASH_NAMED_NOARGS(RIPEMD_160, "RIPEMD-160");
BOTAN_REGISTER_HASH_NAMED_NOARGS(SHA_160, "SHA-160");
#endif
-#if defined(BOTAN_HAS_SHA1_SSE2)
-BOTAN_REGISTER_HASH_NOARGS_IF(CPUID::has_sse2(), SHA_160_SSE2, "SHA-160",
- "sse2", BOTAN_SIMD_ALGORITHM_PRIO);
-#endif
-
#if defined(BOTAN_HAS_SHA2_32)
BOTAN_REGISTER_HASH_NAMED_NOARGS(SHA_224, "SHA-224");
BOTAN_REGISTER_HASH_NAMED_NOARGS(SHA_256, "SHA-256");
diff --git a/src/lib/hash/hash.h b/src/lib/hash/hash.h
index ac1c22a65..08b5d5243 100644
--- a/src/lib/hash/hash.h
+++ b/src/lib/hash/hash.h
@@ -40,6 +40,12 @@ class BOTAN_DLL HashFunction : public Buffered_Computation
*/
virtual HashFunction* clone() const = 0;
+ /**
+ * @return provider information about this implementation. Default is "base",
+ * might also return "sse2", "avx2", "openssl", or some other arbitrary string.
+ */
+ virtual std::string provider() const { return "base"; }
+
HashFunction();
virtual ~HashFunction();
diff --git a/src/lib/hash/sha1/sha160.cpp b/src/lib/hash/sha1/sha160.cpp
index 21e87465a..87738fb00 100644
--- a/src/lib/hash/sha1/sha160.cpp
+++ b/src/lib/hash/sha1/sha160.cpp
@@ -6,6 +6,7 @@
*/
#include <botan/sha160.h>
+#include <botan/cpuid.h>
namespace Botan {
@@ -60,9 +61,19 @@ void SHA_160::compress_n(const byte input[], size_t blocks)
{
using namespace SHA1_F;
+#if defined(BOTAN_HAS_SHA1_SSE2)
+ if(CPUID::has_sse2())
+ {
+ return sse2_compress_n(m_digest, input, blocks);
+ }
+
+#endif
+
u32bit A = m_digest[0], B = m_digest[1], C = m_digest[2],
D = m_digest[3], E = m_digest[4];
+ m_W.resize(80);
+
for(size_t i = 0; i != blocks; ++i)
{
load_be(m_W.data(), input, 16);
diff --git a/src/lib/hash/sha1/sha160.h b/src/lib/hash/sha1/sha160.h
index b4a161c14..d7860834f 100644
--- a/src/lib/hash/sha1/sha160.h
+++ b/src/lib/hash/sha1/sha160.h
@@ -1,6 +1,6 @@
/*
* SHA-160
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2007,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -15,7 +15,7 @@ namespace Botan {
/**
* NIST's SHA-160
*/
-class BOTAN_DLL SHA_160 : public MDx_HashFunction
+class BOTAN_DLL SHA_160 final : public MDx_HashFunction
{
public:
std::string name() const override { return "SHA-160"; }
@@ -24,37 +24,36 @@ class BOTAN_DLL SHA_160 : public MDx_HashFunction
void clear() override;
- SHA_160() : MDx_HashFunction(64, true, true), m_digest(5), m_W(80)
- {
- clear();
- }
- protected:
- /**
- * Set a custom size for the W array. Normally 80, but some
- * subclasses need slightly more for best performance/internal
- * constraints
- * @param W_size how big to make W
- */
- explicit SHA_160(size_t W_size) :
- MDx_HashFunction(64, true, true), m_digest(5), m_W(W_size)
+ SHA_160() : MDx_HashFunction(64, true, true), m_digest(5)
{
clear();
}
+ private:
void compress_n(const byte[], size_t blocks) override;
+
+#if defined(BOTAN_HAS_SHA1_SSE2)
+ static void sse2_compress_n(secure_vector<u32bit>& digest,
+ const byte blocks[],
+ size_t block_count);
+#endif
+
+
void copy_out(byte[]) override;
/**
- * The digest value, exposed for use by subclasses (asm, SSE2)
+ * The digest value
*/
secure_vector<u32bit> m_digest;
/**
- * The message buffer, exposed for use by subclasses (asm, SSE2)
+ * The message buffer
*/
secure_vector<u32bit> m_W;
};
+typedef SHA_160 SHA_1;
+
}
#endif
diff --git a/src/lib/hash/sha1_sse2/info.txt b/src/lib/hash/sha1_sse2/info.txt
index 78f5540e7..e352364ec 100644
--- a/src/lib/hash/sha1_sse2/info.txt
+++ b/src/lib/hash/sha1_sse2/info.txt
@@ -1,4 +1,4 @@
-define SHA1_SSE2 20131128
+define SHA1_SSE2 20160803
need_isa sse2
diff --git a/src/lib/hash/sha1_sse2/sha1_sse2.cpp b/src/lib/hash/sha1_sse2/sha1_sse2.cpp
index 14ad88bc4..2ece541b0 100644
--- a/src/lib/hash/sha1_sse2/sha1_sse2.cpp
+++ b/src/lib/hash/sha1_sse2/sha1_sse2.cpp
@@ -7,8 +7,7 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include <botan/sha1_sse2.h>
-#include <botan/cpuid.h>
+#include <botan/sha160.h>
#include <emmintrin.h>
namespace Botan {
@@ -152,7 +151,8 @@ inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
/*
* SHA-160 Compression Function using SSE for message expansion
*/
-void SHA_160_SSE2::compress_n(const byte input_bytes[], size_t blocks)
+//static
+void SHA_160::sse2_compress_n(secure_vector<uint32_t>& digest, const byte input[], size_t blocks)
{
using namespace SHA1_SSE2_F;
@@ -161,13 +161,13 @@ void SHA_160_SSE2::compress_n(const byte input_bytes[], size_t blocks)
const __m128i K40_59 = _mm_set1_epi32(0x8F1BBCDC);
const __m128i K60_79 = _mm_set1_epi32(0xCA62C1D6);
- u32bit A = m_digest[0],
- B = m_digest[1],
- C = m_digest[2],
- D = m_digest[3],
- E = m_digest[4];
+ u32bit A = digest[0],
+ B = digest[1],
+ C = digest[2],
+ D = digest[3],
+ E = digest[4];
- const __m128i* input = reinterpret_cast<const __m128i*>(input_bytes);
+ const __m128i* input_mm = reinterpret_cast<const __m128i*>(input);
for(size_t i = 0; i != blocks; ++i)
{
@@ -178,16 +178,16 @@ void SHA_160_SSE2::compress_n(const byte input_bytes[], size_t blocks)
v4si P0, P1, P2, P3;
- __m128i W0 = _mm_loadu_si128(&input[0]);
+ __m128i W0 = _mm_loadu_si128(&input_mm[0]);
prep00_15(P0, W0);
- __m128i W1 = _mm_loadu_si128(&input[1]);
+ __m128i W1 = _mm_loadu_si128(&input_mm[1]);
prep00_15(P1, W1);
- __m128i W2 = _mm_loadu_si128(&input[2]);
+ __m128i W2 = _mm_loadu_si128(&input_mm[2]);
prep00_15(P2, W2);
- __m128i W3 = _mm_loadu_si128(&input[3]);
+ __m128i W3 = _mm_loadu_si128(&input_mm[3]);
prep00_15(P3, W3);
/*
@@ -316,13 +316,13 @@ void SHA_160_SSE2::compress_n(const byte input_bytes[], size_t blocks)
F4(C, D, E, A, B, GET_P_32(P3, 2));
F4(B, C, D, E, A, GET_P_32(P3, 3));
- A = (m_digest[0] += A);
- B = (m_digest[1] += B);
- C = (m_digest[2] += C);
- D = (m_digest[3] += D);
- E = (m_digest[4] += E);
+ A = (digest[0] += A);
+ B = (digest[1] += B);
+ C = (digest[2] += C);
+ D = (digest[3] += D);
+ E = (digest[4] += E);
- input += (hash_block_size() / 16);
+ input_mm += (64 / 16);
}
#undef GET_P_32
diff --git a/src/lib/hash/sha1_sse2/sha1_sse2.h b/src/lib/hash/sha1_sse2/sha1_sse2.h
deleted file mode 100644
index a38600762..000000000
--- a/src/lib/hash/sha1_sse2/sha1_sse2.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-* SHA-160
-* (C) 1999-2007 Jack Lloyd
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#ifndef BOTAN_SHA_160_SSE2_H__
-#define BOTAN_SHA_160_SSE2_H__
-
-#include <botan/sha160.h>
-
-namespace Botan {
-
-/**
-* SHA-160 using SSE2 for the message expansion
-*/
-class BOTAN_DLL SHA_160_SSE2 final : public SHA_160
- {
- public:
- HashFunction* clone() const override { return new SHA_160_SSE2; }
- SHA_160_SSE2() : SHA_160(0) {} // no W needed
- private:
- void compress_n(const byte[], size_t blocks) override;
- };
-
-}
-
-#endif
diff --git a/src/lib/mac/mac.h b/src/lib/mac/mac.h
index fe3388f3b..ae8ea5405 100644
--- a/src/lib/mac/mac.h
+++ b/src/lib/mac/mac.h
@@ -51,6 +51,13 @@ class BOTAN_DLL MessageAuthenticationCode : public Buffered_Computation,
* Get a new object representing the same algorithm as *this
*/
virtual MessageAuthenticationCode* clone() const = 0;
+
+ /**
+ * @return provider information about this implementation. Default is "base",
+ * might also return "sse2", "avx2", "openssl", or some other arbitrary string.
+ */
+ virtual std::string provider() const { return "base"; }
+
};
typedef MessageAuthenticationCode MAC;
diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp
index e23551cb4..e4a07af82 100644
--- a/src/lib/modes/aead/gcm/gcm.cpp
+++ b/src/lib/modes/aead/gcm/gcm.cpp
@@ -185,6 +185,16 @@ std::string GCM_Mode::name() const
return (m_cipher_name + "/GCM");
}
+std::string GCM_Mode::provider() const
+ {
+#if defined(BOTAN_HAS_GCM_CLMUL)
+ if(CPUID::has_clmul())
+ return "clmul";
+#endif
+
+ return "base";
+ }
+
size_t GCM_Mode::update_granularity() const
{
return m_BS;
diff --git a/src/lib/modes/aead/gcm/gcm.h b/src/lib/modes/aead/gcm/gcm.h
index ba0d6cad8..3c8bdea3f 100644
--- a/src/lib/modes/aead/gcm/gcm.h
+++ b/src/lib/modes/aead/gcm/gcm.h
@@ -36,6 +36,8 @@ class BOTAN_DLL GCM_Mode : public AEAD_Mode
size_t tag_size() const override { return m_tag_size; }
void clear() override;
+
+ std::string provider() const override;
protected:
GCM_Mode(BlockCipher* cipher, size_t tag_size);
diff --git a/src/lib/modes/cipher_mode.h b/src/lib/modes/cipher_mode.h
index 73a5f7d96..e98f014b7 100644
--- a/src/lib/modes/cipher_mode.h
+++ b/src/lib/modes/cipher_mode.h
@@ -113,14 +113,6 @@ class BOTAN_DLL Cipher_Mode
*/
virtual bool valid_nonce_length(size_t nonce_len) const = 0;
- /**
- * Return some short name describing the provider of this tranformation.
- * Useful in cases where multiple implementations are available (eg,
- * different implementations of AES). Default "core" is used for the
- * 'standard' implementation included in the library.
- */
- virtual std::string provider() const { return "core"; }
-
virtual std::string name() const = 0;
virtual void clear() = 0;
@@ -174,6 +166,12 @@ class BOTAN_DLL Cipher_Mode
key_schedule(key, length);
}
+ /**
+ * @return provider information about this implementation. Default is "base",
+ * might also return "sse2", "avx2", "openssl", or some other arbitrary string.
+ */
+ virtual std::string provider() const { return "base"; }
+
private:
virtual void key_schedule(const byte key[], size_t length) = 0;
};
diff --git a/src/lib/prov/openssl/openssl_block.cpp b/src/lib/prov/openssl/openssl_block.cpp
index c868e8977..8f5ae89b1 100644
--- a/src/lib/prov/openssl/openssl_block.cpp
+++ b/src/lib/prov/openssl/openssl_block.cpp
@@ -25,6 +25,7 @@ class OpenSSL_BlockCipher : public BlockCipher
~OpenSSL_BlockCipher();
void clear() override;
+ std::string provider() const override { return "openssl"; }
std::string name() const override { return m_cipher_name; }
BlockCipher* clone() const override;
diff --git a/src/lib/prov/openssl/openssl_hash.cpp b/src/lib/prov/openssl/openssl_hash.cpp
index c14c551e4..15aebeb94 100644
--- a/src/lib/prov/openssl/openssl_hash.cpp
+++ b/src/lib/prov/openssl/openssl_hash.cpp
@@ -23,6 +23,7 @@ class OpenSSL_HashFunction : public HashFunction
EVP_DigestInit_ex(&m_md, algo, nullptr);
}
+ std::string provider() const override { return "openssl"; }
std::string name() const override { return m_name; }
HashFunction* clone() const override
diff --git a/src/lib/prov/openssl/openssl_rc4.cpp b/src/lib/prov/openssl/openssl_rc4.cpp
index d6246e4ab..2e9f8aab7 100644
--- a/src/lib/prov/openssl/openssl_rc4.cpp
+++ b/src/lib/prov/openssl/openssl_rc4.cpp
@@ -24,6 +24,8 @@ class OpenSSL_RC4 : public StreamCipher
public:
void clear() override { clear_mem(&m_rc4, 1); }
+ std::string provider() const override { return "openssl"; }
+
std::string name() const override
{
switch(m_skip)
diff --git a/src/lib/pubkey/dh/dh.cpp b/src/lib/pubkey/dh/dh.cpp
index 8ed79aa3d..763e1f20b 100644
--- a/src/lib/pubkey/dh/dh.cpp
+++ b/src/lib/pubkey/dh/dh.cpp
@@ -58,7 +58,7 @@ DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng,
}
else
{
- load_check(rng);
+ //load_check(rng);
}
}
@@ -73,7 +73,7 @@ DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id,
if(m_y == 0)
m_y = power_mod(group_g(), m_x, group_p());
- load_check(rng);
+ //load_check(rng);
}
/*
diff --git a/src/lib/stream/chacha/chacha.cpp b/src/lib/stream/chacha/chacha.cpp
index c35363112..6101281a0 100644
--- a/src/lib/stream/chacha/chacha.cpp
+++ b/src/lib/stream/chacha/chacha.cpp
@@ -17,6 +17,18 @@ ChaCha::ChaCha(size_t rounds) : m_rounds(rounds)
throw Invalid_Argument("ChaCha only supports 8, 12 or 20 rounds");
}
+std::string ChaCha::provider() const
+ {
+#if defined(BOTAN_HAS_CHACHA_SSE2)
+ if(CPUID::has_sse2())
+ {
+ return "sse2";
+ }
+#endif
+
+ return "base";
+ }
+
//static
void ChaCha::chacha_x4(byte output[64*4], u32bit input[16], size_t rounds)
{
diff --git a/src/lib/stream/chacha/chacha.h b/src/lib/stream/chacha/chacha.h
index 7e9e54768..eafeac2fd 100644
--- a/src/lib/stream/chacha/chacha.h
+++ b/src/lib/stream/chacha/chacha.h
@@ -26,6 +26,8 @@ class BOTAN_DLL ChaCha final : public StreamCipher
*/
ChaCha(size_t rounds = 20);
+ std::string provider() const override;
+
void cipher(const byte in[], byte out[], size_t length) override;
void set_iv(const byte iv[], size_t iv_len) override;
diff --git a/src/lib/stream/stream_cipher.h b/src/lib/stream/stream_cipher.h
index e08bee0ce..b24a99e39 100644
--- a/src/lib/stream/stream_cipher.h
+++ b/src/lib/stream/stream_cipher.h
@@ -86,6 +86,12 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm
*/
virtual void seek(u64bit offset) = 0;
+ /**
+ * @return provider information about this implementation. Default is "base",
+ * might also return "sse2", "avx2", "openssl", or some other arbitrary string.
+ */
+ virtual std::string provider() const { return "base"; }
+
StreamCipher();
virtual ~StreamCipher();
};
diff --git a/src/lib/utils/cpuid.cpp b/src/lib/utils/cpuid.cpp
index d3def91ed..3fafadab7 100644
--- a/src/lib/utils/cpuid.cpp
+++ b/src/lib/utils/cpuid.cpp
@@ -73,9 +73,8 @@
namespace Botan {
-u64bit CPUID::g_x86_processor_flags[2] = { 0, 0 };
+u64bit CPUID::g_processor_flags[2] = { 0, 0 };
size_t CPUID::g_cache_line_size = BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE;
-bool CPUID::g_altivec_capable = false;
bool CPUID::g_initialized = false;
namespace {
@@ -173,13 +172,14 @@ void CPUID::print(std::ostream& o)
o << "CPUID flags: ";
#define CPUID_PRINT(flag) do { if(has_##flag()) o << #flag << " "; } while(0)
+
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
CPUID_PRINT(sse2);
CPUID_PRINT(ssse3);
CPUID_PRINT(sse41);
CPUID_PRINT(sse42);
CPUID_PRINT(avx2);
CPUID_PRINT(avx512f);
- CPUID_PRINT(altivec);
CPUID_PRINT(rdtsc);
CPUID_PRINT(bmi2);
@@ -189,18 +189,25 @@ void CPUID::print(std::ostream& o)
CPUID_PRINT(rdseed);
CPUID_PRINT(intel_sha);
CPUID_PRINT(adx);
+#endif
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+ CPUID_PRINT(altivec);
+#endif
+
#undef CPUID_PRINT
o << "\n";
}
void CPUID::initialize()
{
- if(g_initialized)
- return;
+ clear_mem(g_processor_flags, 2);
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
- if(altivec_check_sysctl() || altivec_check_pvr_emul())
- g_altivec_capable = true;
+ if(altivec_check_sysctl() || altivec_check_pvr_emul())
+ {
+ g_processor_flags[0] |= CPUID_ALTIVEC_BIT;
+ }
#endif
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
@@ -220,7 +227,7 @@ void CPUID::initialize()
X86_CPUID(1, cpuid);
- g_x86_processor_flags[0] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];
+ g_processor_flags[0] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[3];
if(is_intel)
g_cache_line_size = 8 * get_byte(2, cpuid[1]);
@@ -229,7 +236,7 @@ void CPUID::initialize()
{
clear_mem(cpuid, 4);
X86_CPUID_SUBLEVEL(7, 0, cpuid);
- g_x86_processor_flags[1] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[1];
+ g_processor_flags[1] = (static_cast<u64bit>(cpuid[2]) << 32) | cpuid[1];
}
if(is_amd)
@@ -245,8 +252,8 @@ void CPUID::initialize()
* If we don't have access to CPUID, we can still safely assume that
* any x86-64 processor has SSE2 and RDTSC
*/
- if(g_x86_processor_flags[0] == 0)
- g_x86_processor_flags[0] = (1 << CPUID_SSE2_BIT) | (1 << CPUID_RDTSC_BIT);
+ if(g_processor_flags[0] == 0)
+ g_processor_flags[0] = (1 << CPUID_SSE2_BIT) | (1 << CPUID_RDTSC_BIT);
#endif
g_initialized = true;
diff --git a/src/lib/utils/cpuid.h b/src/lib/utils/cpuid.h
index 3781b6f8e..4e276fabe 100644
--- a/src/lib/utils/cpuid.h
+++ b/src/lib/utils/cpuid.h
@@ -15,6 +15,8 @@ namespace Botan {
/**
* A class handling runtime CPU feature detection
+*
+* Currently this class supports only x86 (via CPUID) and PowerPC (AltiVec detection)
*/
class BOTAN_DLL CPUID
{
@@ -24,6 +26,10 @@ class BOTAN_DLL CPUID
*/
static void initialize();
+ static bool has_simd_32();
+
+ static void print(std::ostream& o);
+
/**
* Return a best guess of the cache line size
*/
@@ -36,136 +42,152 @@ class BOTAN_DLL CPUID
return g_cache_line_size;
}
+ enum CPUID_bits {
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+ // This matches the layout of cpuid(1)
+ CPUID_RDTSC_BIT = 4,
+ CPUID_SSE2_BIT = 26,
+ CPUID_CLMUL_BIT = 33,
+ CPUID_SSSE3_BIT = 41,
+ CPUID_SSE41_BIT = 51,
+ CPUID_SSE42_BIT = 52,
+ CPUID_AESNI_BIT = 57,
+ CPUID_RDRAND_BIT = 62,
+
+ CPUID_AVX2_BIT = 64+5,
+ CPUID_BMI2_BIT = 64+8,
+ CPUID_AVX512F_BIT = 64+16,
+ CPUID_RDSEED_BIT = 64+18,
+ CPUID_ADX_BIT = 64+19,
+ CPUID_SHA_BIT = 64+29,
+#endif
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+ CPUID_ALTIVEC_BIT = 0
+#endif
+
+ // TODO: ARMv8 feature detection
+ };
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
/**
* Check if the processor supports AltiVec/VMX
*/
static bool has_altivec()
- {
- if(!g_initialized)
- {
- initialize();
- }
+ { return has_cpuid_bit(CPUID_ALTIVEC_BIT); }
+#endif
- return g_altivec_capable;
- }
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
/**
* Check if the processor supports RDTSC
*/
static bool has_rdtsc()
- { return x86_processor_flags_has(CPUID_RDTSC_BIT); }
+ { return has_cpuid_bit(CPUID_RDTSC_BIT); }
/**
* Check if the processor supports SSE2
*/
static bool has_sse2()
- { return x86_processor_flags_has(CPUID_SSE2_BIT); }
+ { return has_cpuid_bit(CPUID_SSE2_BIT); }
/**
* Check if the processor supports SSSE3
*/
static bool has_ssse3()
- { return x86_processor_flags_has(CPUID_SSSE3_BIT); }
+ { return has_cpuid_bit(CPUID_SSSE3_BIT); }
/**
* Check if the processor supports SSE4.1
*/
static bool has_sse41()
- { return x86_processor_flags_has(CPUID_SSE41_BIT); }
+ { return has_cpuid_bit(CPUID_SSE41_BIT); }
/**
* Check if the processor supports SSE4.2
*/
static bool has_sse42()
- { return x86_processor_flags_has(CPUID_SSE42_BIT); }
+ { return has_cpuid_bit(CPUID_SSE42_BIT); }
/**
* Check if the processor supports AVX2
*/
static bool has_avx2()
- { return x86_processor_flags_has(CPUID_AVX2_BIT); }
+ { return has_cpuid_bit(CPUID_AVX2_BIT); }
/**
* Check if the processor supports AVX-512F
*/
static bool has_avx512f()
- { return x86_processor_flags_has(CPUID_AVX512F_BIT); }
+ { return has_cpuid_bit(CPUID_AVX512F_BIT); }
/**
* Check if the processor supports BMI2
*/
static bool has_bmi2()
- { return x86_processor_flags_has(CPUID_BMI2_BIT); }
+ { return has_cpuid_bit(CPUID_BMI2_BIT); }
/**
* Check if the processor supports AES-NI
*/
static bool has_aes_ni()
- { return x86_processor_flags_has(CPUID_AESNI_BIT); }
+ { return has_cpuid_bit(CPUID_AESNI_BIT); }
/**
* Check if the processor supports CLMUL
*/
static bool has_clmul()
- { return x86_processor_flags_has(CPUID_CLMUL_BIT); }
+ { return has_cpuid_bit(CPUID_CLMUL_BIT); }
/**
* Check if the processor supports Intel SHA extension
*/
static bool has_intel_sha()
- { return x86_processor_flags_has(CPUID_SHA_BIT); }
+ { return has_cpuid_bit(CPUID_SHA_BIT); }
/**
* Check if the processor supports ADX extension
*/
static bool has_adx()
- { return x86_processor_flags_has(CPUID_ADX_BIT); }
+ { return has_cpuid_bit(CPUID_ADX_BIT); }
/**
* Check if the processor supports RDRAND
*/
static bool has_rdrand()
- { return x86_processor_flags_has(CPUID_RDRAND_BIT); }
+ { return has_cpuid_bit(CPUID_RDRAND_BIT); }
/**
* Check if the processor supports RDSEED
*/
static bool has_rdseed()
- { return x86_processor_flags_has(CPUID_RDSEED_BIT); }
-
- static bool has_simd_32();
-
- static void print(std::ostream& o);
- private:
- enum CPUID_bits {
- CPUID_RDTSC_BIT = 4,
- CPUID_SSE2_BIT = 26,
- CPUID_CLMUL_BIT = 33,
- CPUID_SSSE3_BIT = 41,
- CPUID_SSE41_BIT = 51,
- CPUID_SSE42_BIT = 52,
- CPUID_AESNI_BIT = 57,
- CPUID_RDRAND_BIT = 62,
+ { return has_cpuid_bit(CPUID_RDSEED_BIT); }
+#endif
- CPUID_AVX2_BIT = 64+5,
- CPUID_BMI2_BIT = 64+8,
- CPUID_AVX512F_BIT = 64+16,
- CPUID_RDSEED_BIT = 64+18,
- CPUID_ADX_BIT = 64+19,
- CPUID_SHA_BIT = 64+29,
- };
+ /*
+ * Clear a CPUID bit
+ * Call CPUID::initialize to reset
+ */
+ static void clear_cpuid_bit(CPUID_bits bit)
+ {
+ BOTAN_ASSERT(bit < 128, "CPUID bit within bounds");
+ const uint64_t mask = ~(static_cast<uint64_t>(1) << (bit % 64));
+ g_processor_flags[bit/64] &= mask;
+ }
- static bool x86_processor_flags_has(u64bit bit)
+ static bool has_cpuid_bit(CPUID_bits elem)
{
if(!g_initialized)
initialize();
- return ((g_x86_processor_flags[bit/64] >> (bit % 64)) & 1);
+ const size_t bit = static_cast<size_t>(elem);
+ BOTAN_ASSERT(bit < 128, "CPUID bit within bounds");
+ return ((g_processor_flags[bit/64] >> (bit % 64)) & 1);
}
+ private:
static bool g_initialized;
- static u64bit g_x86_processor_flags[2];
static size_t g_cache_line_size;
- static bool g_altivec_capable;
+ static u64bit g_processor_flags[2];
};
}
diff --git a/src/tests/data/aead/gcm.vec b/src/tests/data/aead/gcm.vec
index 516e828ec..be8250792 100644
--- a/src/tests/data/aead/gcm.vec
+++ b/src/tests/data/aead/gcm.vec
@@ -1,3 +1,6 @@
+
+#test cpuid aesni ssse3 clmul
+
[AES-128/GCM]
# Nist | Test Case 1
Key = 00000000000000000000000000000000
diff --git a/src/tests/data/block/aes.vec b/src/tests/data/block/aes.vec
index 4e0b7399c..50d9cc469 100644
--- a/src/tests/data/block/aes.vec
+++ b/src/tests/data/block/aes.vec
@@ -1,3 +1,6 @@
+
+#test cpuid aesni ssse3
+
[AES-128]
Key = 000102030405060708090A0B0C0D0E0F
In = 00112233445566778899AABBCCDDEEFF
diff --git a/src/tests/data/block/idea.vec b/src/tests/data/block/idea.vec
index 705d02d68..eee5ef5e9 100644
--- a/src/tests/data/block/idea.vec
+++ b/src/tests/data/block/idea.vec
@@ -1,3 +1,6 @@
+
+#test cpuid sse2
+
[IDEA]
Key = ED1BCC9E9267925F3132BA3A8CF9B764
In = 7409000000000000
diff --git a/src/tests/data/block/noekeon.vec b/src/tests/data/block/noekeon.vec
index 2921301c1..08e7cabf3 100644
--- a/src/tests/data/block/noekeon.vec
+++ b/src/tests/data/block/noekeon.vec
@@ -1,3 +1,6 @@
+
+#cpuid simd32
+
[Noekeon]
Key = 00000000000000000000000000000000
In = 00000000000000000000000000000000
diff --git a/src/tests/data/block/serpent.vec b/src/tests/data/block/serpent.vec
index 623ee6be8..8a40c54b7 100644
--- a/src/tests/data/block/serpent.vec
+++ b/src/tests/data/block/serpent.vec
@@ -1,3 +1,6 @@
+
+#test cpuid simd
+
[Serpent]
Key = 00000000000000000000000000000000
In = D29D576FCEA3A3A7ED9099F29273D78E2D62A890CEA3A3A7ED9099F29273D78ED29D576F315C5C58ED9099F29273D78E2D62A890315C5C58ED9099F29273D78ED29D576FCEA3A3A7126F660D9273D78E2D62A890CEA3A3A7126F660D9273D78ED29D576F315C5C58126F660D9273D78E2D62A890315C5C58126F660D9273D78ED29D576FCEA3A3A7ED9099F26D8C28712D62A890CEA3A3A7ED9099F26D8C2871D29D576F315C5C58ED9099F26D8C28712D62A890315C5C58ED9099F26D8C2871D29D576FCEA3A3A7126F660D6D8C28712D62A890CEA3A3A7126F660D6D8C2871D29D576F315C5C58126F660D6D8C2871
diff --git a/src/tests/data/block/threefish.vec b/src/tests/data/block/threefish.vec
index b4e9d8229..dfaccb7ff 100644
--- a/src/tests/data/block/threefish.vec
+++ b/src/tests/data/block/threefish.vec
@@ -1,3 +1,6 @@
+
+#test cpuid avx2
+
[Threefish-512]
Key = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
diff --git a/src/tests/data/hash/sha1.vec b/src/tests/data/hash/sha1.vec
index f5fd82340..e86650f30 100644
--- a/src/tests/data/hash/sha1.vec
+++ b/src/tests/data/hash/sha1.vec
@@ -1,3 +1,5 @@
+#test cpuid sse2
+
[SHA-160]
In =
Out = DA39A3EE5E6B4B0D3255BFEF95601890AFD80709
diff --git a/src/tests/data/stream/chacha.vec b/src/tests/data/stream/chacha.vec
index 47d3aa7fe..f7ba701ba 100644
--- a/src/tests/data/stream/chacha.vec
+++ b/src/tests/data/stream/chacha.vec
@@ -1,3 +1,6 @@
+
+#test cpuid sse2
+
[ChaCha(8)]
# Tests got from the original implementation of Daniel J. Bernstein
diff --git a/src/tests/main.cpp b/src/tests/main.cpp
index 07aaac519..b771d9614 100644
--- a/src/tests/main.cpp
+++ b/src/tests/main.cpp
@@ -228,8 +228,14 @@ class Test_Runner : public Botan_CLI::Command
{
for(auto&& test_name : tests_to_run)
{
- const auto results = Botan_Tests::Test::run_test(test_name, false);
- out << report_out(results, tests_failed, tests_ran) << std::flush;
+ try {
+ const auto results = Botan_Tests::Test::run_test(test_name, false);
+ out << report_out(results, tests_failed, tests_ran) << std::flush;
+ }
+ catch(std::exception& e)
+ {
+ out << "Test " << test_name << " failed with exception " << e.what() << std::flush;
+ }
}
}
else
@@ -250,7 +256,15 @@ class Test_Runner : public Botan_CLI::Command
for(auto&& test_name : tests_to_run)
{
auto run_it = [test_name] {
- return Botan_Tests::Test::run_test(test_name, false);
+ try {
+ return Botan_Tests::Test::run_test(test_name, false);
+ }
+ catch(std::exception& e)
+ {
+ Botan_Tests::Test::Result r(test_name);
+ r.test_failure("Exception thrown", e.what());
+ return std::vector<Botan_Tests::Test::Result>{r};
+ }
};
fut_results.push_back(std::async(std::launch::async, run_it));
diff --git a/src/tests/test_block.cpp b/src/tests/test_block.cpp
index 0863cb891..acbe6702b 100644
--- a/src/tests/test_block.cpp
+++ b/src/tests/test_block.cpp
@@ -30,16 +30,18 @@ class Block_Cipher_Tests : public Text_Based_Test
return result;
}
- for(auto&& provider: providers)
+ for(auto&& provider_ask : providers)
{
- std::unique_ptr<Botan::BlockCipher> cipher(Botan::BlockCipher::create(algo, provider));
+ std::unique_ptr<Botan::BlockCipher> cipher(Botan::BlockCipher::create(algo, provider_ask));
if(!cipher)
{
- result.note_missing(algo + " from " + provider);
+ result.note_missing(algo + " from " + provider_ask);
continue;
}
+ const std::string provider(cipher->provider());
+ result.test_is_nonempty("provider", provider);
result.test_eq(provider, cipher->name(), algo);
result.test_gte(provider, cipher->parallelism(), 1);
result.test_gte(provider, cipher->block_size(), 8);
diff --git a/src/tests/test_hash.cpp b/src/tests/test_hash.cpp
index 811e95727..aca9d7ef6 100644
--- a/src/tests/test_hash.cpp
+++ b/src/tests/test_hash.cpp
@@ -36,16 +36,18 @@ class Hash_Function_Tests : public Text_Based_Test
return result;
}
- for(auto&& provider: providers)
+ for(auto&& provider_ask : providers)
{
- std::unique_ptr<Botan::HashFunction> hash(Botan::HashFunction::create(algo, provider));
+ std::unique_ptr<Botan::HashFunction> hash(Botan::HashFunction::create(algo, provider_ask));
if(!hash)
{
- result.note_missing(algo + " from " + provider);
+ result.note_missing(algo + " from " + provider_ask);
continue;
}
+ const std::string provider(hash->provider());
+ result.test_is_nonempty("provider", provider);
result.test_eq(provider, hash->name(), algo);
hash->update(input);
diff --git a/src/tests/test_mac.cpp b/src/tests/test_mac.cpp
index c7efb7f08..6183e88f7 100644
--- a/src/tests/test_mac.cpp
+++ b/src/tests/test_mac.cpp
@@ -38,16 +38,19 @@ class Message_Auth_Tests : public Text_Based_Test
return result;
}
- for(auto&& provider: providers)
+ for(auto&& provider_ask : providers)
{
- std::unique_ptr<Botan::MessageAuthenticationCode> mac(Botan::MessageAuthenticationCode::create(algo, provider));
+ std::unique_ptr<Botan::MessageAuthenticationCode> mac(Botan::MessageAuthenticationCode::create(algo, provider_ask));
if(!mac)
{
- result.note_missing(algo + " from " + provider);
+ result.note_missing(algo + " from " + provider_ask);
continue;
}
+ const std::string provider(mac->provider());
+
+ result.test_is_nonempty("provider", provider);
result.test_eq(provider, mac->name(), algo);
mac->set_key(key);
diff --git a/src/tests/test_modes.cpp b/src/tests/test_modes.cpp
index 66f537346..ada4d5b82 100644
--- a/src/tests/test_modes.cpp
+++ b/src/tests/test_modes.cpp
@@ -39,6 +39,7 @@ class Cipher_Mode_Tests : public Text_Based_Test
return result;
}
+ result.test_is_nonempty("provider", enc->provider());
result.test_eq("name", enc->name(), algo);
result.test_eq("mode not authenticated", enc->authenticated(), false);
diff --git a/src/tests/test_stream.cpp b/src/tests/test_stream.cpp
index be7b9a548..6097fd3e8 100644
--- a/src/tests/test_stream.cpp
+++ b/src/tests/test_stream.cpp
@@ -41,16 +41,18 @@ class Stream_Cipher_Tests : public Text_Based_Test
return result;
}
- for(auto&& provider: providers)
+ for(auto&& provider_ask : providers)
{
- std::unique_ptr<Botan::StreamCipher> cipher(Botan::StreamCipher::create(algo, provider));
+ std::unique_ptr<Botan::StreamCipher> cipher(Botan::StreamCipher::create(algo, provider_ask));
if(!cipher)
{
- result.note_missing(algo + " from " + provider);
+ result.note_missing(algo + " from " + provider_ask);
continue;
}
+ const std::string provider(cipher->provider());
+ result.test_is_nonempty("provider", provider);
result.test_eq(provider, cipher->name(), algo);
cipher->set_key(key);
diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp
index a6f96144c..b47f2a7ab 100644
--- a/src/tests/tests.cpp
+++ b/src/tests/tests.cpp
@@ -175,6 +175,13 @@ bool Test::Result::test_eq(const char* producer, const std::string& what,
return test_failure(err.str());
}
+bool Test::Result::test_is_nonempty(const std::string& what_is_it, const std::string& to_examine)
+ {
+ if(to_examine.empty())
+ return test_failure(what_is_it + " was empty");
+ return test_success();
+ }
+
bool Test::Result::test_eq(const std::string& what, const std::string& produced, const std::string& expected)
{
return test_is_eq(what, produced, expected);
@@ -527,21 +534,21 @@ Text_Based_Test::Text_Based_Test(const std::string& algo,
std::vector<uint8_t> Text_Based_Test::get_req_bin(const VarMap& vars,
const std::string& key) const
- {
- auto i = vars.find(key);
- if(i == vars.end())
- throw Test_Error("Test missing variable " + key);
+ {
+ auto i = vars.find(key);
+ if(i == vars.end())
+ throw Test_Error("Test missing variable " + key);
- try
- {
- return Botan::hex_decode(i->second);
- }
- catch(std::exception&)
- {
- throw Test_Error("Test invalid hex input '" + i->second + "'" +
- + " for key " + key);
- }
+ try
+ {
+ return Botan::hex_decode(i->second);
}
+ catch(std::exception&)
+ {
+ throw Test_Error("Test invalid hex input '" + i->second + "'" +
+ + " for key " + key);
+ }
+ }
std::string Text_Based_Test::get_opt_str(const VarMap& vars,
const std::string& key, const std::string& def_value) const
@@ -646,9 +653,17 @@ std::string Text_Based_Test::get_next_line()
}
m_cur.reset(new std::ifstream(m_srcs[0]));
+ m_cur_src_name = m_srcs[0];
+
+ // Reinit cpuid on new file if needed
+ if(m_cpu_flags.empty() == false)
+ {
+ m_cpu_flags.clear();
+ Botan::CPUID::initialize();
+ }
if(!m_cur->good())
- throw Test_Error("Could not open input file '" + m_srcs[0]);
+ throw Test_Error("Could not open input file '" + m_cur_src_name);
m_srcs.pop_front();
}
@@ -662,7 +677,12 @@ std::string Text_Based_Test::get_next_line()
continue;
if(line[0] == '#')
- continue;
+ {
+ if(line.compare(0, 6, "#test ") == 0)
+ return line;
+ else
+ continue;
+ }
return line;
}
@@ -685,6 +705,42 @@ std::string strip_ws(const std::string& in)
return in.substr(first_c, last_c - first_c + 1);
}
+std::vector<Botan::CPUID::CPUID_bits> map_cpuid_string(const std::string& tok)
+ {
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+ if(tok == "sse2" || tok == "simd")
+ return {Botan::CPUID::CPUID_SSE2_BIT};
+ if(tok == "ssse3")
+ return {Botan::CPUID::CPUID_SSSE3_BIT};
+ if(tok == "aesni")
+ return {Botan::CPUID::CPUID_AESNI_BIT};
+ if(tok == "clmul")
+ return {Botan::CPUID::CPUID_CLMUL_BIT};
+ if(tok == "avx2")
+ return {Botan::CPUID::CPUID_AVX2_BIT};
+#endif
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+ if(tok == "altivec" || tok == "simd")
+ return {Botan::CPUID::CPUID_ALTIVEC_BIT};
+#endif
+
+ return {};
+ }
+
+std::vector<Botan::CPUID::CPUID_bits>
+parse_cpuid_bits(const std::vector<std::string>& tok)
+ {
+ std::vector<Botan::CPUID::CPUID_bits> bits;
+ for(size_t i = 1; i < tok.size(); ++i)
+ {
+ const std::vector<Botan::CPUID::CPUID_bits> more = map_cpuid_string(tok[i]);
+ bits.insert(bits.end(), more.begin(), more.end());
+ }
+
+ return bits;
+ }
+
}
std::vector<Test::Result> Text_Based_Test::run()
@@ -701,6 +757,23 @@ std::vector<Test::Result> Text_Based_Test::run()
if(line.empty()) // EOF
break;
+ if(line.compare(0, 6, "#test ") == 0)
+ {
+ std::vector<std::string> pragma_tokens = Botan::split_on(line.substr(6), ' ');
+
+ if(pragma_tokens.empty())
+ throw Test_Error("Empty pragma found in " + m_cur_src_name);
+
+ if(pragma_tokens[0] != "cpuid")
+ throw Test_Error("Unknown test pragma '" + line + "' in " + m_cur_src_name);
+
+ m_cpu_flags = parse_cpuid_bits(pragma_tokens);
+
+ continue;
+ }
+ else if(line[0] == '#')
+ throw Test_Error("Unknown test pragma '" + line + "' in " + m_cur_src_name);
+
if(line[0] == '[' && line[line.size()-1] == ']')
{
header = line.substr(1, line.size() - 2);
@@ -736,7 +809,21 @@ std::vector<Test::Result> Text_Based_Test::run()
++test_cnt;
uint64_t start = Test::timestamp();
+
Test::Result result = run_one_test(header, vars);
+ if(m_cpu_flags.size() > 0)
+ {
+ for(auto&& cpuid_bit : m_cpu_flags)
+ {
+ if(Botan::CPUID::has_cpuid_bit(cpuid_bit))
+ {
+ Botan::CPUID::clear_cpuid_bit(cpuid_bit);
+ // now re-run the test
+ result.merge(run_one_test(header, vars));
+ }
+ }
+ Botan::CPUID::initialize();
+ }
result.set_ns_consumed(Test::timestamp() - start);
if(result.tests_failed())
diff --git a/src/tests/tests.h b/src/tests/tests.h
index 39aaf67cd..1ceb24f48 100644
--- a/src/tests/tests.h
+++ b/src/tests/tests.h
@@ -12,6 +12,7 @@
#include <botan/rng.h>
#include <botan/hex.h>
#include <botan/symkey.h>
+#include <botan/cpuid.h>
#if defined(BOTAN_HAS_BIGINT)
#include <botan/bigint.h>
@@ -170,6 +171,8 @@ class Test
bool test_eq(const std::string& what, const char* produced, const char* expected);
+ bool test_is_nonempty(const std::string& what_is_it, const std::string& to_examine);
+
bool test_eq(const std::string& what,
const std::string& produced,
const std::string& expected);
@@ -442,7 +445,9 @@ class Text_Based_Test : public Test
bool m_first = true;
std::unique_ptr<std::ifstream> m_cur;
+ std::string m_cur_src_name;
std::deque<std::string> m_srcs;
+ std::vector<Botan::CPUID::CPUID_bits> m_cpu_flags;
};
}