Add SIMECK-64 SSSE3 implementation (GH #675)
parent
4a7814be7e
commit
08e6137082
|
|
@ -287,6 +287,7 @@ simple.cpp
|
|||
simple.h
|
||||
siphash.h
|
||||
simeck.cpp
|
||||
simeck-simd.cpp
|
||||
simeck.h
|
||||
simon.cpp
|
||||
simon-simd.cpp
|
||||
|
|
|
|||
12
GNUmakefile
12
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) $<
|
||||
|
|
|
|||
|
|
@ -525,6 +525,10 @@ void Benchmark2(double t, double hertz)
|
|||
std::cout << "\n<TR><TH>Algorithm<TH>MiB/Second" << cpb;
|
||||
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;\">";
|
||||
{
|
||||
#if CRYPTOPP_AESNI_AVAILABLE
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -296,6 +296,7 @@
|
|||
<ClCompile Include="shark.cpp" />
|
||||
<ClCompile Include="sharkbox.cpp" />
|
||||
<ClCompile Include="simeck.cpp" />
|
||||
<ClCompile Include="simeck-simd.cpp" />
|
||||
<ClCompile Include="simon.cpp" />
|
||||
<ClCompile Include="simon-simd.cpp" />
|
||||
<ClCompile Include="simple.cpp" />
|
||||
|
|
|
|||
|
|
@ -380,6 +380,9 @@
|
|||
<ClCompile Include="simeck.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="simeck-simd.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="simon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
53
simeck.cpp
53
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 <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;
|
||||
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<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
|
||||
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<word16, BigEndian> 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<word16, BigEndian> 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<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
|
||||
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<word32, BigEndian> 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<word32, BigEndian> 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
|
||||
|
|
|
|||
16
simeck.h
16
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<word16, ROUNDS> m_rk;
|
||||
mutable FixedSizeSecBlock<word16, 5> m_t;
|
||||
mutable FixedSizeSecBlock<word16, 4> 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<word32, ROUNDS> m_rk;
|
||||
mutable FixedSizeSecBlock<word32, 5> m_t;
|
||||
mutable FixedSizeSecBlock<word32, 4> 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, Enc> Encryption;
|
||||
|
|
|
|||
Loading…
Reference in New Issue