Add SIMECK-64 SSSE3 implementation (GH #675)

pull/681/head
Jeffrey Walton 2018-07-01 03:11:00 -04:00
parent 4a7814be7e
commit 08e6137082
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
9 changed files with 404 additions and 13 deletions

View File

@ -287,6 +287,7 @@ simple.cpp
simple.h simple.h
siphash.h siphash.h
simeck.cpp simeck.cpp
simeck-simd.cpp
simeck.h simeck.h
simon.cpp simon.cpp
simon-simd.cpp simon-simd.cpp

View File

@ -252,6 +252,7 @@ ifeq ($(findstring -DCRYPTOPP_DISABLE_SSSE3,$(CXXFLAGS)),)
CHAM_FLAG = -mssse3 CHAM_FLAG = -mssse3
LEA_FLAG = -mssse3 LEA_FLAG = -mssse3
SSSE3_FLAG = -mssse3 SSSE3_FLAG = -mssse3
SIMECK_FLAG = -mssse3
SIMON_FLAG = -mssse3 SIMON_FLAG = -mssse3
SPECK_FLAG = -mssse3 SPECK_FLAG = -mssse3
endif endif
@ -293,6 +294,7 @@ ifeq ($(SUN_COMPILER),1)
ARIA_FLAG = -xarch=ssse3 -D__SSSE3__=1 ARIA_FLAG = -xarch=ssse3 -D__SSSE3__=1
CHAM_FLAG = -xarch=ssse3 -D__SSSE3__=1 CHAM_FLAG = -xarch=ssse3 -D__SSSE3__=1
LEA_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 SIMON_FLAG = -xarch=ssse3 -D__SSSE3__=1
SPECK_FLAG = -xarch=ssse3 -D__SSSE3__=1 SPECK_FLAG = -xarch=ssse3 -D__SSSE3__=1
LDFLAGS += -xarch=ssse3 LDFLAGS += -xarch=ssse3
@ -379,6 +381,7 @@ ifeq ($(IS_NEON),1)
ARIA_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon ARIA_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
BLAKE2_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 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 SIMON_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
SPECK_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon SPECK_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
endif endif
@ -391,6 +394,7 @@ ifeq ($(IS_ARMV8),1)
BLAKE2_FLAG = -march=armv8-a BLAKE2_FLAG = -march=armv8-a
LEA_FLAG = -march=armv8-a LEA_FLAG = -march=armv8-a
NEON_FLAG = -march=armv8-a NEON_FLAG = -march=armv8-a
SIMECK_FLAG = -march=armv8-a
SIMON_FLAG = -march=armv8-a SIMON_FLAG = -march=armv8-a
SPECK_FLAG = -march=armv8-a SPECK_FLAG = -march=armv8-a
endif endif
@ -416,6 +420,7 @@ ifneq ($(IS_PPC32)$(IS_PPC64)$(IS_AIX),000)
ARIA_FLAG = -mcpu=power4 -maltivec ARIA_FLAG = -mcpu=power4 -maltivec
BLAKE2_FLAG = -mcpu=power4 -maltivec BLAKE2_FLAG = -mcpu=power4 -maltivec
SIMON_FLAG = -mcpu=power4 -maltivec SIMON_FLAG = -mcpu=power4 -maltivec
SIMECK_FLAG = -mcpu=power4 -maltivec
SPECK_FLAG = -mcpu=power4 -maltivec SPECK_FLAG = -mcpu=power4 -maltivec
endif endif
# GCC and some compatibles # GCC and some compatibles
@ -425,6 +430,7 @@ ifneq ($(IS_PPC32)$(IS_PPC64)$(IS_AIX),000)
AES_FLAG = -mcpu=power8 -maltivec AES_FLAG = -mcpu=power8 -maltivec
GCM_FLAG = -mcpu=power8 -maltivec GCM_FLAG = -mcpu=power8 -maltivec
SHA_FLAG = -mcpu=power8 -maltivec SHA_FLAG = -mcpu=power8 -maltivec
SIMECK_FLAG = -mcpu=power8 -maltivec
SIMON_FLAG = -mcpu=power8 -maltivec SIMON_FLAG = -mcpu=power8 -maltivec
SPECK_FLAG = -mcpu=power8 -maltivec SPECK_FLAG = -mcpu=power8 -maltivec
endif endif
@ -434,6 +440,7 @@ ifneq ($(IS_PPC32)$(IS_PPC64)$(IS_AIX),000)
ALTIVEC_FLAG = -qarch=pwr7 -qaltivec ALTIVEC_FLAG = -qarch=pwr7 -qaltivec
ARIA_FLAG = -qarch=pwr7 -qaltivec ARIA_FLAG = -qarch=pwr7 -qaltivec
BLAKE2_FLAG = -qarch=pwr7 -qaltivec BLAKE2_FLAG = -qarch=pwr7 -qaltivec
SIMECK_FLAG = -qarch=pwr7 -qaltivec
SIMON_FLAG = -qarch=pwr7 -qaltivec SIMON_FLAG = -qarch=pwr7 -qaltivec
SPECK_FLAG = -qarch=pwr7 -qaltivec SPECK_FLAG = -qarch=pwr7 -qaltivec
endif endif
@ -446,6 +453,7 @@ ifneq ($(IS_PPC32)$(IS_PPC64)$(IS_AIX),000)
SHA_FLAG = -qarch=pwr8 -qaltivec SHA_FLAG = -qarch=pwr8 -qaltivec
ARIA_FLAG = -qarch=pwr8 -qaltivec ARIA_FLAG = -qarch=pwr8 -qaltivec
BLAKE2_FLAG = -qarch=pwr8 -qaltivec BLAKE2_FLAG = -qarch=pwr8 -qaltivec
SIMECK_FLAG = -qarch=pwr8 -qaltivec
SIMON_FLAG = -qarch=pwr8 -qaltivec SIMON_FLAG = -qarch=pwr8 -qaltivec
SPECK_FLAG = -qarch=pwr8 -qaltivec SPECK_FLAG = -qarch=pwr8 -qaltivec
endif endif
@ -1096,6 +1104,10 @@ sha-simd.o : sha-simd.cpp
shacal2-simd.o : shacal2-simd.cpp shacal2-simd.o : shacal2-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SHA_FLAG) -c) $< $(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 # SSSE3 or NEON available
simon-simd.o : simon-simd.cpp simon-simd.o : simon-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SIMON_FLAG) -c) $< $(CXX) $(strip $(CXXFLAGS) $(SIMON_FLAG) -c) $<

View File

@ -525,6 +525,10 @@ void Benchmark2(double t, double hertz)
std::cout << "\n<TR><TH>Algorithm<TH>MiB/Second" << cpb; std::cout << "\n<TR><TH>Algorithm<TH>MiB/Second" << cpb;
std::cout << "<TH>Microseconds to<BR>Setup Key and IV" << cpk; std::cout << "<TH>Microseconds to<BR>Setup Key and IV" << cpk;
BenchMarkByName<SymmetricCipher>("SIMECK-32/CTR", 8, "SIMECK-32(64)/CTR (64-bit key)");
BenchMarkByName<SymmetricCipher>("SIMECK-64/CTR", 16, "SIMECK-64(128)/CTR (128-bit key)");
return;
std::cout << "\n<TBODY style=\"background: white;\">"; std::cout << "\n<TBODY style=\"background: white;\">";
{ {
#if CRYPTOPP_AESNI_AVAILABLE #if CRYPTOPP_AESNI_AVAILABLE

View File

@ -47,9 +47,9 @@
# If you use 'make sources' from Linux makefile, then add 'winpipes.cpp' to the list below. # 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 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

View File

@ -296,6 +296,7 @@
<ClCompile Include="shark.cpp" /> <ClCompile Include="shark.cpp" />
<ClCompile Include="sharkbox.cpp" /> <ClCompile Include="sharkbox.cpp" />
<ClCompile Include="simeck.cpp" /> <ClCompile Include="simeck.cpp" />
<ClCompile Include="simeck-simd.cpp" />
<ClCompile Include="simon.cpp" /> <ClCompile Include="simon.cpp" />
<ClCompile Include="simon-simd.cpp" /> <ClCompile Include="simon-simd.cpp" />
<ClCompile Include="simple.cpp" /> <ClCompile Include="simple.cpp" />

View File

@ -380,6 +380,9 @@
<ClCompile Include="simeck.cpp"> <ClCompile Include="simeck.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="simeck-simd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="simon.cpp"> <ClCompile Include="simon.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

323
simeck-simd.cpp Normal file
View File

@ -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 <pmmintrin.h>
# include <tmmintrin.h>
#endif
#if defined(__AVX512F__) && defined(__AVX512VL__)
# define CRYPTOPP_AVX512_ROTATE 1
# include <immintrin.h>
#endif
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::word16;
using CryptoPP::word32;
#if (CRYPTOPP_SSSE3_AVAILABLE)
//////////////////////////////////////////////////////////////////////////
template <unsigned int R>
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 <unsigned int R>
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 <unsigned int IDX>
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 <unsigned int IDX>
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 <unsigned int IDX>
inline __m128i RepackXMM(const __m128i& a, const __m128i& b, const __m128i& c, const __m128i& d)
{
return UnpackXMM<IDX>(a, b, c, d);
}
template <unsigned int IDX>
inline __m128i RepackXMM(const __m128i& v)
{
return UnpackXMM<IDX>(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<static_cast<int>(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<int>(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<static_cast<int>(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<int>(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

View File

@ -19,13 +19,12 @@ using CryptoPP::rotrConstant;
/// \param key the key for the round or iteration /// \param key the key for the round or iteration
/// \param left the first value /// \param left the first value
/// \param right the second value /// \param right the second value
/// \param temp a temporary workspace
/// \details SIMECK_Encryption serves as the key schedule, encryption and /// \details SIMECK_Encryption serves as the key schedule, encryption and
/// decryption functions. /// decryption functions.
template <class T> template <class T>
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; left = (left & rotlConstant<5>(left)) ^ rotlConstant<1>(left) ^ right ^ key;
right = temp; right = temp;
} }
@ -34,6 +33,16 @@ ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP) 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 &params) void SIMECK32::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{ {
CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(params);
@ -52,7 +61,7 @@ void SIMECK32::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength
constant |= sequence & 1; constant |= sequence & 1;
sequence >>= 1; sequence >>= 1;
SIMECK_Encryption(static_cast<word16>(constant), m_t[1], m_t[0], m_t[4]); SIMECK_Encryption(static_cast<word16>(constant), m_t[1], m_t[0]);
// rotate the LFSR of m_t // rotate the LFSR of m_t
m_t[4] = m_t[1]; 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]); iblock(m_t[1])(m_t[0]);
for (int idx = 0; idx < ROUNDS; ++idx) 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<word16, BigEndian> oblock(xorBlock, outBlock); PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
oblock(m_t[1])(m_t[0]); 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]); iblock(m_t[0])(m_t[1]);
for (int idx = ROUNDS - 1; idx >= 0; --idx) 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<word16, BigEndian> oblock(xorBlock, outBlock); PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
oblock(m_t[0])(m_t[1]); oblock(m_t[0])(m_t[1]);
@ -106,7 +115,7 @@ void SIMECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength
constant |= sequence & 1; constant |= sequence & 1;
sequence >>= 1; sequence >>= 1;
SIMECK_Encryption(static_cast<word32>(constant), m_t[1], m_t[0], m_t[4]); SIMECK_Encryption(static_cast<word32>(constant), m_t[1], m_t[0]);
// rotate the LFSR of m_t // rotate the LFSR of m_t
m_t[4] = m_t[1]; 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]); iblock(m_t[1])(m_t[0]);
for (int idx = 0; idx < ROUNDS; ++idx) 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<word32, BigEndian> oblock(xorBlock, outBlock); PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
oblock(m_t[1])(m_t[0]); 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]); iblock(m_t[0])(m_t[1]);
for (int idx = ROUNDS - 1; idx >= 0; --idx) 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<word32, BigEndian> oblock(xorBlock, outBlock); PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
oblock(m_t[0])(m_t[1]); 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 NAMESPACE_END

View File

@ -14,6 +14,10 @@
#include "secblock.h" #include "secblock.h"
#include "algparam.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) NAMESPACE_BEGIN(CryptoPP)
/// \brief SIMECK block cipher information /// \brief SIMECK block cipher information
@ -57,7 +61,7 @@ public:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params); void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
FixedSizeSecBlock<word16, ROUNDS> m_rk; FixedSizeSecBlock<word16, ROUNDS> m_rk;
mutable FixedSizeSecBlock<word16, 5> m_t; mutable FixedSizeSecBlock<word16, 4> m_t;
}; };
/// \brief Provides implementation for encryption transformation /// \brief Provides implementation for encryption transformation
@ -106,7 +110,7 @@ public:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params); void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
FixedSizeSecBlock<word32, ROUNDS> m_rk; FixedSizeSecBlock<word32, ROUNDS> m_rk;
mutable FixedSizeSecBlock<word32, 5> m_t; mutable FixedSizeSecBlock<word32, 4> m_t;
}; };
/// \brief Provides implementation for encryption transformation /// \brief Provides implementation for encryption transformation
@ -117,6 +121,10 @@ public:
{ {
public: public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; 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 /// \brief Provides implementation for encryption transformation
@ -127,6 +135,10 @@ public:
{ {
public: public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; 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, Enc> Encryption; typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;