diff --git a/Filelist.txt b/Filelist.txt
index 83acac8d..fd6471ed 100644
--- a/Filelist.txt
+++ b/Filelist.txt
@@ -287,6 +287,7 @@ simple.cpp
simple.h
siphash.h
simeck.cpp
+simeck-simd.cpp
simeck.h
simon.cpp
simon-simd.cpp
diff --git a/GNUmakefile b/GNUmakefile
index cdd798b1..df63a11a 100755
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -252,6 +252,7 @@ ifeq ($(findstring -DCRYPTOPP_DISABLE_SSSE3,$(CXXFLAGS)),)
CHAM_FLAG = -mssse3
LEA_FLAG = -mssse3
SSSE3_FLAG = -mssse3
+ SIMECK_FLAG = -mssse3
SIMON_FLAG = -mssse3
SPECK_FLAG = -mssse3
endif
@@ -293,6 +294,7 @@ ifeq ($(SUN_COMPILER),1)
ARIA_FLAG = -xarch=ssse3 -D__SSSE3__=1
CHAM_FLAG = -xarch=ssse3 -D__SSSE3__=1
LEA_FLAG = -xarch=ssse3 -D__SSSE3__=1
+ SIMECK_FLAG = -xarch=ssse3 -D__SSSE3__=1
SIMON_FLAG = -xarch=ssse3 -D__SSSE3__=1
SPECK_FLAG = -xarch=ssse3 -D__SSSE3__=1
LDFLAGS += -xarch=ssse3
@@ -379,6 +381,7 @@ ifeq ($(IS_NEON),1)
ARIA_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
BLAKE2_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
LEA_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
+ SIMECK_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
SIMON_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
SPECK_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
endif
@@ -391,6 +394,7 @@ ifeq ($(IS_ARMV8),1)
BLAKE2_FLAG = -march=armv8-a
LEA_FLAG = -march=armv8-a
NEON_FLAG = -march=armv8-a
+ SIMECK_FLAG = -march=armv8-a
SIMON_FLAG = -march=armv8-a
SPECK_FLAG = -march=armv8-a
endif
@@ -416,6 +420,7 @@ ifneq ($(IS_PPC32)$(IS_PPC64)$(IS_AIX),000)
ARIA_FLAG = -mcpu=power4 -maltivec
BLAKE2_FLAG = -mcpu=power4 -maltivec
SIMON_FLAG = -mcpu=power4 -maltivec
+ SIMECK_FLAG = -mcpu=power4 -maltivec
SPECK_FLAG = -mcpu=power4 -maltivec
endif
# GCC and some compatibles
@@ -425,6 +430,7 @@ ifneq ($(IS_PPC32)$(IS_PPC64)$(IS_AIX),000)
AES_FLAG = -mcpu=power8 -maltivec
GCM_FLAG = -mcpu=power8 -maltivec
SHA_FLAG = -mcpu=power8 -maltivec
+ SIMECK_FLAG = -mcpu=power8 -maltivec
SIMON_FLAG = -mcpu=power8 -maltivec
SPECK_FLAG = -mcpu=power8 -maltivec
endif
@@ -434,6 +440,7 @@ ifneq ($(IS_PPC32)$(IS_PPC64)$(IS_AIX),000)
ALTIVEC_FLAG = -qarch=pwr7 -qaltivec
ARIA_FLAG = -qarch=pwr7 -qaltivec
BLAKE2_FLAG = -qarch=pwr7 -qaltivec
+ SIMECK_FLAG = -qarch=pwr7 -qaltivec
SIMON_FLAG = -qarch=pwr7 -qaltivec
SPECK_FLAG = -qarch=pwr7 -qaltivec
endif
@@ -446,6 +453,7 @@ ifneq ($(IS_PPC32)$(IS_PPC64)$(IS_AIX),000)
SHA_FLAG = -qarch=pwr8 -qaltivec
ARIA_FLAG = -qarch=pwr8 -qaltivec
BLAKE2_FLAG = -qarch=pwr8 -qaltivec
+ SIMECK_FLAG = -qarch=pwr8 -qaltivec
SIMON_FLAG = -qarch=pwr8 -qaltivec
SPECK_FLAG = -qarch=pwr8 -qaltivec
endif
@@ -1096,6 +1104,10 @@ sha-simd.o : sha-simd.cpp
shacal2-simd.o : shacal2-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SHA_FLAG) -c) $<
+# SSSE3 or NEON available
+simeck-simd.o : simeck-simd.cpp
+ $(CXX) $(strip $(CXXFLAGS) $(SIMECK_FLAG) -c) $<
+
# SSSE3 or NEON available
simon-simd.o : simon-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SIMON_FLAG) -c) $<
diff --git a/bench1.cpp b/bench1.cpp
index 4cee1702..a322e70b 100644
--- a/bench1.cpp
+++ b/bench1.cpp
@@ -525,6 +525,10 @@ void Benchmark2(double t, double hertz)
std::cout << "\n
| Algorithm | MiB/Second" << cpb;
std::cout << " | Microseconds to Setup Key and IV" << cpk;
+ BenchMarkByName("SIMECK-32/CTR", 8, "SIMECK-32(64)/CTR (64-bit key)");
+ BenchMarkByName("SIMECK-64/CTR", 16, "SIMECK-64(128)/CTR (128-bit key)");
+ return;
+
std::cout << "\n";
{
#if CRYPTOPP_AESNI_AVAILABLE
diff --git a/cryptest.nmake b/cryptest.nmake
index f94466ed..b2015dbf 100644
--- a/cryptest.nmake
+++ b/cryptest.nmake
@@ -47,9 +47,9 @@
# If you use 'make sources' from Linux makefile, then add 'winpipes.cpp' to the list below.
-LIB_SRCS = cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2-simd.cpp blake2.cpp blowfish.cpp blumshub.cpp camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp cham.cpp cham-simd.cpp channels.cpp cmac.cpp crc-simd.cpp crc.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp dll.cpp dsa.cpp eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm-simd.cpp gcm.cpp gf256.cpp gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hex.cpp hight.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.cpp lea.cpp lea-simd.cpp luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp nbtheory.cpp neon-simd.cpp network.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp pssr.cpp pubkey.cpp queue.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp rijndael-simd.cpp rijndael.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.cpp simeck.cpp simon.cpp simon-simd.cpp skipjack.cpp sm3.cpp sm4.cpp socketft.cpp sosemanuk.cpp speck.cpp speck-simd.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp trdlocal.cpp ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wait.cpp wake.cpp whrlpool.cpp winpipes.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
+LIB_SRCS = cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2-simd.cpp blake2.cpp blowfish.cpp blumshub.cpp camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp cham.cpp cham-simd.cpp channels.cpp cmac.cpp crc-simd.cpp crc.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp dll.cpp dsa.cpp eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm-simd.cpp gcm.cpp gf256.cpp gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hex.cpp hight.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.cpp lea.cpp lea-simd.cpp luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp nbtheory.cpp neon-simd.cpp network.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp pssr.cpp pubkey.cpp queue.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp rijndael-simd.cpp rijndael.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.cpp simeck-simd.cpp simeck.cpp simon.cpp simon-simd.cpp skipjack.cpp sm3.cpp sm4.cpp socketft.cpp sosemanuk.cpp speck.cpp speck-simd.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp trdlocal.cpp ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wait.cpp wake.cpp whrlpool.cpp winpipes.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
-LIB_OBJS = cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj algparam.obj arc4.obj aria-simd.obj aria.obj ariatab.obj asn.obj authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2-simd.obj blake2.obj blowfish.obj blumshub.obj camellia.obj cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj cham.obj cham-simd.obj channels.obj cmac.obj crc-simd.obj crc.obj default.obj des.obj dessp.obj dh.obj dh2.obj dll.obj dsa.obj eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm-simd.obj gcm.obj gf256.obj gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hex.obj hight.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.obj lea.obj lea-simd.obj luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj nbtheory.obj neon-simd.obj network.obj oaep.obj osrng.obj padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj pssr.obj pubkey.obj queue.obj rabin.obj randpool.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj rijndael-simd.obj rijndael.obj ripemd.obj rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.obj simeck.obj simon.obj simon-simd.obj skipjack.obj sm3.obj sm4.obj socketft.obj sosemanuk.obj speck.obj speck-simd.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj trdlocal.obj ttmac.obj tweetnacl.obj twofish.obj vmac.obj wait.obj wake.obj whrlpool.obj winpipes.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj zlib.obj
+LIB_OBJS = cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj algparam.obj arc4.obj aria-simd.obj aria.obj ariatab.obj asn.obj authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2-simd.obj blake2.obj blowfish.obj blumshub.obj camellia.obj cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj cham.obj cham-simd.obj channels.obj cmac.obj crc-simd.obj crc.obj default.obj des.obj dessp.obj dh.obj dh2.obj dll.obj dsa.obj eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm-simd.obj gcm.obj gf256.obj gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hex.obj hight.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.obj lea.obj lea-simd.obj luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj nbtheory.obj neon-simd.obj network.obj oaep.obj osrng.obj padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj pssr.obj pubkey.obj queue.obj rabin.obj randpool.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj rijndael-simd.obj rijndael.obj ripemd.obj rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.obj simeck-simd.obj simeck.obj simon.obj simon-simd.obj skipjack.obj sm3.obj sm4.obj socketft.obj sosemanuk.obj speck.obj speck-simd.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj trdlocal.obj ttmac.obj tweetnacl.obj twofish.obj vmac.obj wait.obj wake.obj whrlpool.obj winpipes.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj zlib.obj
TEST_SRCS = bench1.cpp bench2.cpp test.cpp validat0.cpp validat1.cpp validat2.cpp validat3.cpp validat4.cpp datatest.cpp regtest1.cpp regtest2.cpp regtest3.cpp fipsalgt.cpp dlltest.cpp fipstest.cpp
diff --git a/cryptlib.vcxproj b/cryptlib.vcxproj
index c217bbf8..a0bff0d4 100644
--- a/cryptlib.vcxproj
+++ b/cryptlib.vcxproj
@@ -296,6 +296,7 @@
+
diff --git a/cryptlib.vcxproj.filters b/cryptlib.vcxproj.filters
index 054aad47..a8478033 100644
--- a/cryptlib.vcxproj.filters
+++ b/cryptlib.vcxproj.filters
@@ -380,6 +380,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/simeck-simd.cpp b/simeck-simd.cpp
new file mode 100644
index 00000000..1994a911
--- /dev/null
+++ b/simeck-simd.cpp
@@ -0,0 +1,323 @@
+// simeck-simd.cpp - written and placed in the public domain by Jeffrey Walton
+//
+// This source file uses intrinsics and built-ins to gain access to
+// SSSE3, ARM NEON and ARMv8a, and Power7 Altivec instructions. A separate
+// source file is needed because additional CXXFLAGS are required to enable
+// the appropriate instructions sets in some build configurations.
+
+#include "pch.h"
+#include "config.h"
+
+#include "simeck.h"
+#include "misc.h"
+#include "adv-simd.h"
+
+// Uncomment for benchmarking C++ against SSE or NEON.
+// Do so in both simon.cpp and simon-simd.cpp.
+// #undef CRYPTOPP_SSSE3_AVAILABLE
+// #undef CRYPTOPP_ARM_NEON_AVAILABLE
+
+#if (CRYPTOPP_SSSE3_AVAILABLE)
+# include
+# include
+#endif
+
+#if defined(__AVX512F__) && defined(__AVX512VL__)
+# define CRYPTOPP_AVX512_ROTATE 1
+# include
+#endif
+
+ANONYMOUS_NAMESPACE_BEGIN
+
+using CryptoPP::word16;
+using CryptoPP::word32;
+
+#if (CRYPTOPP_SSSE3_AVAILABLE)
+
+//////////////////////////////////////////////////////////////////////////
+
+template
+inline __m128i RotateLeft32(const __m128i& val)
+{
+#if defined(CRYPTOPP_AVX512_ROTATE)
+ return _mm_rol_epi32(val, R);
+#else
+ return _mm_or_si128(
+ _mm_slli_epi32(val, R), _mm_srli_epi32(val, 32-R));
+#endif
+}
+
+template
+inline __m128i RotateRight32(const __m128i& val)
+{
+#if defined(CRYPTOPP_AVX512_ROTATE)
+ return _mm_ror_epi32(val, R);
+#else
+ return _mm_or_si128(
+ _mm_slli_epi32(val, 32-R), _mm_srli_epi32(val, R));
+#endif
+}
+
+// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks.
+template <>
+inline __m128i RotateLeft32<8>(const __m128i& val)
+{
+ const __m128i mask = _mm_set_epi8(14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3);
+ return _mm_shuffle_epi8(val, mask);
+}
+
+// Faster than two Shifts and an Or. Thanks to Louis Wingers and Bryan Weeks.
+template <>
+inline __m128i RotateRight32<8>(const __m128i& val)
+{
+ const __m128i mask = _mm_set_epi8(12,15,14,13, 8,11,10,9, 4,7,6,5, 0,3,2,1);
+ return _mm_shuffle_epi8(val, mask);
+}
+
+template
+inline __m128i UnpackXMM(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d)
+{
+ // Should not be instantiated
+ CRYPTOPP_ASSERT(0);;
+ return _mm_setzero_si128();
+}
+
+template <>
+inline __m128i UnpackXMM<0>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d)
+{
+ // The shuffle converts to and from little-endian for SSE. A specialized
+ // SIMECK implementation can avoid the shuffle by framing the data for
+ // encryption, decryption and benchmarks. The library cannot take the
+ // speed-up because of the byte oriented API.
+ const __m128i r1 = _mm_unpacklo_epi32(a, b);
+ const __m128i r2 = _mm_unpacklo_epi32(c, d);
+ return _mm_shuffle_epi8(_mm_unpacklo_epi64(r1, r2),
+ _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3));
+}
+
+template <>
+inline __m128i UnpackXMM<1>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d)
+{
+ // The shuffle converts to and from little-endian for SSE. A specialized
+ // SIMECK implementation can avoid the shuffle by framing the data for
+ // encryption, decryption and benchmarks. The library cannot take the
+ // speed-up because of the byte oriented API.
+ const __m128i r1 = _mm_unpacklo_epi32(a, b);
+ const __m128i r2 = _mm_unpacklo_epi32(c, d);
+ return _mm_shuffle_epi8(_mm_unpackhi_epi64(r1, r2),
+ _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3));
+}
+
+template <>
+inline __m128i UnpackXMM<2>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d)
+{
+ // The shuffle converts to and from little-endian for SSE. A specialized
+ // SIMECK implementation can avoid the shuffle by framing the data for
+ // encryption, decryption and benchmarks. The library cannot take the
+ // speed-up because of the byte oriented API.
+ const __m128i r1 = _mm_unpackhi_epi32(a, b);
+ const __m128i r2 = _mm_unpackhi_epi32(c, d);
+ return _mm_shuffle_epi8(_mm_unpacklo_epi64(r1, r2),
+ _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3));
+}
+
+template <>
+inline __m128i UnpackXMM<3>(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d)
+{
+ // The shuffle converts to and from little-endian for SSE. A specialized
+ // SIMECK implementation can avoid the shuffle by framing the data for
+ // encryption, decryption and benchmarks. The library cannot take the
+ // speed-up because of the byte oriented API.
+ const __m128i r1 = _mm_unpackhi_epi32(a, b);
+ const __m128i r2 = _mm_unpackhi_epi32(c, d);
+ return _mm_shuffle_epi8(_mm_unpackhi_epi64(r1, r2),
+ _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3));
+}
+
+template
+inline __m128i UnpackXMM(const __m128i& v)
+{
+ // Should not be instantiated
+ CRYPTOPP_ASSERT(0);;
+ return _mm_setzero_si128();
+}
+
+template <>
+inline __m128i UnpackXMM<0>(const __m128i& v)
+{
+ return _mm_shuffle_epi8(v, _mm_set_epi8(0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3));
+}
+
+template <>
+inline __m128i UnpackXMM<1>(const __m128i& v)
+{
+ return _mm_shuffle_epi8(v, _mm_set_epi8(4,5,6,7, 4,5,6,7, 4,5,6,7, 4,5,6,7));
+}
+
+template <>
+inline __m128i UnpackXMM<2>(const __m128i& v)
+{
+ return _mm_shuffle_epi8(v, _mm_set_epi8(8,9,10,11, 8,9,10,11, 8,9,10,11, 8,9,10,11));
+}
+
+template <>
+inline __m128i UnpackXMM<3>(const __m128i& v)
+{
+ return _mm_shuffle_epi8(v, _mm_set_epi8(12,13,14,15, 12,13,14,15, 12,13,14,15, 12,13,14,15));
+}
+
+template
+inline __m128i RepackXMM(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d)
+{
+ return UnpackXMM(a, b, c, d);
+}
+
+template
+inline __m128i RepackXMM(const __m128i& v)
+{
+ return UnpackXMM(v);
+}
+
+inline void SIMECK64_Encrypt(__m128i &a, __m128i &b,
+ __m128i &c, __m128i &d, const __m128i key)
+{
+ //temp = left
+ //left = (left & rotlConstant<5>(left)) ^ rotlConstant<1>(left) ^ right ^ key;
+ //right = left
+
+ const __m128i s = a, t = c;
+ a = _mm_xor_si128(_mm_and_si128(a, RotateLeft32<5>(a)), RotateLeft32<1>(a));
+ c = _mm_xor_si128(_mm_and_si128(c, RotateLeft32<5>(c)), RotateLeft32<1>(c));
+ a = _mm_xor_si128(a, _mm_xor_si128(b, key));
+ c = _mm_xor_si128(c, _mm_xor_si128(d, key));
+ b = s; d = t;
+}
+
+inline __m128i SIMECK64_LoadKey(const word32* subkey)
+{
+ float f[2];
+ std::memcpy(f, subkey, 4);
+ return _mm_castps_si128(_mm_load_ps1(f));
+}
+
+inline void SIMECK64_Enc_Block(__m128i &block0,
+ const word32 *subkeys, unsigned int rounds)
+{
+ // Rearrange the data for vectorization. UnpackXMM includes a
+ // little-endian swap for SSE. Thanks to Peter Cordes for help
+ // with packing and unpacking.
+ // [A1 A2 A3 A4][B1 B2 B3 B4] ... => [A1 B1 C1 D1][A2 B2 C2 D2] ...
+ __m128i a = UnpackXMM<0>(block0);
+ __m128i b = UnpackXMM<1>(block0);
+ __m128i c = UnpackXMM<2>(block0);
+ __m128i d = UnpackXMM<3>(block0);
+
+ for (int i=0; i(rounds); ++i)
+ SIMECK64_Encrypt(a, b, c, d, SIMECK64_LoadKey(subkeys + i));
+
+ // [A1 B1 C1 D1][A2 B2 C2 D2] ... => [A1 A2 A3 A4][B1 B2 B3 B4] ...
+ block0 = RepackXMM<0>(a,b,c,d);
+}
+
+inline void SIMECK64_Dec_Block(__m128i &block0,
+ const word32 *subkeys, unsigned int rounds)
+{
+ // SIMECK requires a word swap on the decryption side
+ __m128i w = _mm_shuffle_epi32(block0, _MM_SHUFFLE(2, 3, 0, 1));
+
+ // Rearrange the data for vectorization. UnpackXMM includes a
+ // little-endian swap for SSE. Thanks to Peter Cordes for help
+ // with packing and unpacking.
+ // [A1 A2 A3 A4][B1 B2 B3 B4] ... => [A1 B1 C1 D1][A2 B2 C2 D2] ...
+ __m128i a = UnpackXMM<0>(w);
+ __m128i b = UnpackXMM<1>(w);
+ __m128i c = UnpackXMM<2>(w);
+ __m128i d = UnpackXMM<3>(w);
+
+ for (int i = static_cast(rounds)-1; i >= 0; --i)
+ SIMECK64_Encrypt(a, b, c, d, SIMECK64_LoadKey(subkeys + i));
+
+ // [A1 B1 C1 D1][A2 B2 C2 D2] ... => [A1 A2 A3 A4][B1 B2 B3 B4] ...
+ w = RepackXMM<0>(a,b,c,d);
+
+ block0 = _mm_shuffle_epi32(w, _MM_SHUFFLE(2, 3, 0, 1));
+}
+
+inline void SIMECK64_Enc_4_Blocks(__m128i &block0, __m128i &block1,
+ __m128i &block2, __m128i &block3, const word32 *subkeys, unsigned int rounds)
+{
+ // Rearrange the data for vectorization. UnpackXMM includes a
+ // little-endian swap for SSE. Thanks to Peter Cordes for help
+ // with packing and unpacking.
+ // [A1 A2 A3 A4][B1 B2 B3 B4] ... => [A1 B1 C1 D1][A2 B2 C2 D2] ...
+ __m128i a = UnpackXMM<0>(block0, block1, block2, block3);
+ __m128i b = UnpackXMM<1>(block0, block1, block2, block3);
+ __m128i c = UnpackXMM<2>(block0, block1, block2, block3);
+ __m128i d = UnpackXMM<3>(block0, block1, block2, block3);
+
+ for (int i=0; i(rounds); ++i)
+ SIMECK64_Encrypt(a, b, c, d, SIMECK64_LoadKey(subkeys + i));
+
+ // [A1 B1 C1 D1][A2 B2 C2 D2] ... => [A1 A2 A3 A4][B1 B2 B3 B4] ...
+ block0 = RepackXMM<0>(a, b, c, d);
+ block1 = RepackXMM<1>(a, b, c, d);
+ block2 = RepackXMM<2>(a, b, c, d);
+ block3 = RepackXMM<3>(a, b, c, d);
+}
+
+inline void SIMECK64_Dec_4_Blocks(__m128i &block0, __m128i &block1,
+ __m128i &block2, __m128i &block3, const word32 *subkeys, unsigned int rounds)
+{
+ // SIMECK requires a word swap on the decryption side
+ __m128i w = _mm_shuffle_epi32(block0, _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i x = _mm_shuffle_epi32(block1, _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i y = _mm_shuffle_epi32(block2, _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i z = _mm_shuffle_epi32(block3, _MM_SHUFFLE(2, 3, 0, 1));
+
+ // Rearrange the data for vectorization. UnpackXMM includes a
+ // little-endian swap for SSE. Thanks to Peter Cordes for help
+ // with packing and unpacking.
+ // [A1 A2 A3 A4][B1 B2 B3 B4] ... => [A1 B1 C1 D1][A2 B2 C2 D2] ...
+ __m128i a = UnpackXMM<0>(w, x, y, z);
+ __m128i b = UnpackXMM<1>(w, x, y, z);
+ __m128i c = UnpackXMM<2>(w, x, y, z);
+ __m128i d = UnpackXMM<3>(w, x, y, z);
+
+ for (int i = static_cast(rounds)-1; i >= 0; --i)
+ SIMECK64_Encrypt(a, b, c, d, SIMECK64_LoadKey(subkeys + i));
+
+ // [A1 B1 C1 D1][A2 B2 C2 D2] ... => [A1 A2 A3 A4][B1 B2 B3 B4] ...
+ w = RepackXMM<0>(a, b, c, d);
+ x = RepackXMM<1>(a, b, c, d);
+ y = RepackXMM<2>(a, b, c, d);
+ z = RepackXMM<3>(a, b, c, d);
+
+ block0 = _mm_shuffle_epi32(w, _MM_SHUFFLE(2, 3, 0, 1));
+ block1 = _mm_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1));
+ block2 = _mm_shuffle_epi32(y, _MM_SHUFFLE(2, 3, 0, 1));
+ block3 = _mm_shuffle_epi32(z, _MM_SHUFFLE(2, 3, 0, 1));
+}
+
+#endif // CRYPTOPP_SSSE3_AVAILABLE
+
+ANONYMOUS_NAMESPACE_END
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if defined(CRYPTOPP_SSSE3_AVAILABLE)
+size_t SIMECK64_Enc_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds,
+ const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+ return AdvancedProcessBlocks64_4x1_SSE(SIMECK64_Enc_Block, SIMECK64_Enc_4_Blocks,
+ subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags);
+}
+
+size_t SIMECK64_Dec_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds,
+ const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags)
+{
+ return AdvancedProcessBlocks64_4x1_SSE(SIMECK64_Dec_Block, SIMECK64_Dec_4_Blocks,
+ subKeys, rounds, inBlocks, xorBlocks, outBlocks, length, flags);
+}
+#endif // CRYPTOPP_SSSE3_AVAILABLE
+
+NAMESPACE_END
diff --git a/simeck.cpp b/simeck.cpp
index 6bd99e69..e0d165f0 100644
--- a/simeck.cpp
+++ b/simeck.cpp
@@ -19,13 +19,12 @@ using CryptoPP::rotrConstant;
/// \param key the key for the round or iteration
/// \param left the first value
/// \param right the second value
-/// \param temp a temporary workspace
/// \details SIMECK_Encryption serves as the key schedule, encryption and
/// decryption functions.
template
-inline void SIMECK_Encryption(const T key, T& left, T& right, T& temp)
+inline void SIMECK_Encryption(const T key, T& left, T& right)
{
- temp = left;
+ const T temp = left;
left = (left & rotlConstant<5>(left)) ^ rotlConstant<1>(left) ^ right ^ key;
right = temp;
}
@@ -34,6 +33,16 @@ ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
+#if CRYPTOPP_SIMECK_ADVANCED_PROCESS_BLOCKS
+# if (CRYPTOPP_SSSE3_AVAILABLE)
+extern size_t SIMECK64_Enc_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds,
+ const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
+
+extern size_t SIMECK64_Dec_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds,
+ const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
+# endif // CRYPTOPP_SSSE3_AVAILABLE
+#endif // CRYPTOPP_SIMECK_ADVANCED_PROCESS_BLOCKS
+
void SIMECK32::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)
{
CRYPTOPP_UNUSED(params);
@@ -52,7 +61,7 @@ void SIMECK32::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength
constant |= sequence & 1;
sequence >>= 1;
- SIMECK_Encryption(static_cast(constant), m_t[1], m_t[0], m_t[4]);
+ SIMECK_Encryption(static_cast(constant), m_t[1], m_t[0]);
// rotate the LFSR of m_t
m_t[4] = m_t[1];
@@ -69,7 +78,7 @@ void SIMECK32::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock
iblock(m_t[1])(m_t[0]);
for (int idx = 0; idx < ROUNDS; ++idx)
- SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0], m_t[4]);
+ SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
PutBlock oblock(xorBlock, outBlock);
oblock(m_t[1])(m_t[0]);
@@ -82,7 +91,7 @@ void SIMECK32::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock
iblock(m_t[0])(m_t[1]);
for (int idx = ROUNDS - 1; idx >= 0; --idx)
- SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0], m_t[4]);
+ SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
PutBlock oblock(xorBlock, outBlock);
oblock(m_t[0])(m_t[1]);
@@ -106,7 +115,7 @@ void SIMECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength
constant |= sequence & 1;
sequence >>= 1;
- SIMECK_Encryption(static_cast(constant), m_t[1], m_t[0], m_t[4]);
+ SIMECK_Encryption(static_cast(constant), m_t[1], m_t[0]);
// rotate the LFSR of m_t
m_t[4] = m_t[1];
@@ -123,7 +132,7 @@ void SIMECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock
iblock(m_t[1])(m_t[0]);
for (int idx = 0; idx < ROUNDS; ++idx)
- SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0], m_t[4]);
+ SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
PutBlock oblock(xorBlock, outBlock);
oblock(m_t[1])(m_t[0]);
@@ -136,10 +145,36 @@ void SIMECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock
iblock(m_t[0])(m_t[1]);
for (int idx = ROUNDS - 1; idx >= 0; --idx)
- SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0], m_t[4]);
+ SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
PutBlock oblock(xorBlock, outBlock);
oblock(m_t[0])(m_t[1]);
}
+#if CRYPTOPP_SIMECK_ADVANCED_PROCESS_BLOCKS
+size_t SIMECK64::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
+ byte *outBlocks, size_t length, word32 flags) const
+{
+# if (CRYPTOPP_SSSE3_AVAILABLE)
+ if (HasSSSE3()) {
+ return SIMECK64_Enc_AdvancedProcessBlocks_SSSE3(m_rk, ROUNDS,
+ inBlocks, xorBlocks, outBlocks, length, flags);
+ }
+# endif // CRYPTOPP_SSSE3_AVAILABLE
+ return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
+}
+
+size_t SIMECK64::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
+ byte *outBlocks, size_t length, word32 flags) const
+{
+# if (CRYPTOPP_SSSE3_AVAILABLE)
+ if (HasSSSE3()) {
+ return SIMECK64_Dec_AdvancedProcessBlocks_SSSE3(m_rk, ROUNDS,
+ inBlocks, xorBlocks, outBlocks, length, flags);
+ }
+# endif // CRYPTOPP_SSSE3_AVAILABLE
+ return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
+}
+#endif // CRYPTOPP_SIMECK_ADVANCED_PROCESS_BLOCKS
+
NAMESPACE_END
diff --git a/simeck.h b/simeck.h
index b3345f4d..a6d44293 100644
--- a/simeck.h
+++ b/simeck.h
@@ -14,6 +14,10 @@
#include "secblock.h"
#include "algparam.h"
+#if (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86)
+# define CRYPTOPP_SIMECK_ADVANCED_PROCESS_BLOCKS 1
+#endif
+
NAMESPACE_BEGIN(CryptoPP)
/// \brief SIMECK block cipher information
@@ -57,7 +61,7 @@ public:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms);
FixedSizeSecBlock m_rk;
- mutable FixedSizeSecBlock m_t;
+ mutable FixedSizeSecBlock m_t;
};
/// \brief Provides implementation for encryption transformation
@@ -106,7 +110,7 @@ public:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms);
FixedSizeSecBlock m_rk;
- mutable FixedSizeSecBlock m_t;
+ mutable FixedSizeSecBlock m_t;
};
/// \brief Provides implementation for encryption transformation
@@ -117,6 +121,10 @@ public:
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+#if CRYPTOPP_SIMECK_ADVANCED_PROCESS_BLOCKS
+ size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+#endif
};
/// \brief Provides implementation for encryption transformation
@@ -127,6 +135,10 @@ public:
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+#if CRYPTOPP_SIMECK_ADVANCED_PROCESS_BLOCKS
+ size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+#endif
};
typedef BlockCipherFinal Encryption;
|
|---|