Re-add Simon and Speck, enable SSE (GH #585)

This commit re-adds Simon and Speck. The commit includes C++, SSSE3 and SSE4. NEON, Aarch32 and Aarch64 are disabled at the moment.
pull/589/head
Jeffrey Walton 2018-02-18 23:23:50 -05:00
parent e5b9fa6485
commit e416b243d3
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
14 changed files with 3540 additions and 2 deletions

View File

@ -276,6 +276,9 @@ sharkbox.cpp
simple.cpp simple.cpp
simple.h simple.h
siphash.h siphash.h
simon.cpp
simon-simd.cpp
simon.h
skipjack.cpp skipjack.cpp
skipjack.h skipjack.h
sm3.cpp sm3.cpp
@ -287,6 +290,9 @@ socketft.cpp
socketft.h socketft.h
sosemanuk.cpp sosemanuk.cpp
sosemanuk.h sosemanuk.h
speck.cpp
speck-simd.cpp
speck.h
square.cpp square.cpp
square.h square.h
squaretb.cpp squaretb.cpp
@ -466,10 +472,12 @@ TestVectors/sha3_256_fips_202.txt
TestVectors/sha3_384_fips_202.txt TestVectors/sha3_384_fips_202.txt
TestVectors/sha3_512_fips_202.txt TestVectors/sha3_512_fips_202.txt
TestVectors/shacal2.txt TestVectors/shacal2.txt
TestVectors/simon.txt
TestVectors/siphash.txt TestVectors/siphash.txt
TestVectors/sm3.txt TestVectors/sm3.txt
TestVectors/sm4.txt TestVectors/sm4.txt
TestVectors/sosemanuk.txt TestVectors/sosemanuk.txt
TestVectors/speck.txt
TestVectors/tea.txt TestVectors/tea.txt
TestVectors/threefish.txt TestVectors/threefish.txt
TestVectors/ttmac.txt TestVectors/ttmac.txt

View File

@ -250,11 +250,15 @@ ifeq ($(findstring -DCRYPTOPP_DISABLE_SSSE3,$(CXXFLAGS)),)
ifeq ($(HAVE_SSSE3),1) ifeq ($(HAVE_SSSE3),1)
ARIA_FLAG = -mssse3 ARIA_FLAG = -mssse3
SSSE3_FLAG = -mssse3 SSSE3_FLAG = -mssse3
SIMON_FLAG = -mssse3
SPECK_FLAG = -mssse3
endif endif
ifeq ($(findstring -DCRYPTOPP_DISABLE_SSE4,$(CXXFLAGS)),) ifeq ($(findstring -DCRYPTOPP_DISABLE_SSE4,$(CXXFLAGS)),)
HAVE_SSE4 = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -msse4.1 -dM -E - 2>/dev/null | $(GREP) -i -c __SSE4_1__) HAVE_SSE4 = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -msse4.1 -dM -E - 2>/dev/null | $(GREP) -i -c __SSE4_1__)
ifeq ($(HAVE_SSE4),1) ifeq ($(HAVE_SSE4),1)
BLAKE2_FLAG = -msse4.1 BLAKE2_FLAG = -msse4.1
SIMON_FLAG = -msse4.1
SPECK_FLAG = -msse4.1
endif endif
HAVE_SSE4 = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -msse4.2 -dM -E - 2>/dev/null | $(GREP) -i -c __SSE4_2__) HAVE_SSE4 = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -msse4.2 -dM -E - 2>/dev/null | $(GREP) -i -c __SSE4_2__)
ifeq ($(HAVE_SSE4),1) ifeq ($(HAVE_SSE4),1)
@ -285,11 +289,15 @@ ifeq ($(SUN_COMPILER),1)
ifeq ($(COUNT),0) ifeq ($(COUNT),0)
SSSE3_FLAG = -xarch=ssse3 -D__SSSE3__=1 SSSE3_FLAG = -xarch=ssse3 -D__SSSE3__=1
ARIA_FLAG = -xarch=ssse3 -D__SSSE3__=1 ARIA_FLAG = -xarch=ssse3 -D__SSSE3__=1
SIMON_FLAG = -xarch=ssse3 -D__SSSE3__=1
SPECK_FLAG = -xarch=ssse3 -D__SSSE3__=1
LDFLAGS += -xarch=ssse3 LDFLAGS += -xarch=ssse3
endif endif
COUNT := $(shell $(CXX) $(CXXFLAGS) -E -xarch=sse4_1 -xdumpmacros /dev/null 2>&1 | $(GREP) -i -c "illegal") COUNT := $(shell $(CXX) $(CXXFLAGS) -E -xarch=sse4_1 -xdumpmacros /dev/null 2>&1 | $(GREP) -i -c "illegal")
ifeq ($(COUNT),0) ifeq ($(COUNT),0)
BLAKE2_FLAG = -xarch=sse4_1 -D__SSE4_1__=1 BLAKE2_FLAG = -xarch=sse4_1 -D__SSE4_1__=1
SIMON_FLAG = -xarch=sse4_1 -D__SSE4_1__=1
SPECK_FLAG = -xarch=sse4_1 -D__SSE4_1__=1
LDFLAGS += -xarch=sse4_1 LDFLAGS += -xarch=sse4_1
endif endif
COUNT := $(shell $(CXX) $(CXXFLAGS) -E -xarch=sse4_2 -xdumpmacros /dev/null 2>&1 | $(GREP) -i -c "illegal") COUNT := $(shell $(CXX) $(CXXFLAGS) -E -xarch=sse4_2 -xdumpmacros /dev/null 2>&1 | $(GREP) -i -c "illegal")
@ -366,6 +374,8 @@ ifeq ($(IS_NEON),1)
GCM_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon GCM_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
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
SIMON_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
SPECK_FLAG = -march=armv7-a -mfloat-abi=$(FP_ABI) -mfpu=neon
endif endif
endif endif
@ -375,6 +385,8 @@ ifeq ($(IS_ARMV8),1)
ARIA_FLAG = -march=armv8-a ARIA_FLAG = -march=armv8-a
BLAKE2_FLAG = -march=armv8-a BLAKE2_FLAG = -march=armv8-a
NEON_FLAG = -march=armv8-a NEON_FLAG = -march=armv8-a
SIMON_FLAG = -march=armv8-a
SPECK_FLAG = -march=armv8-a
endif endif
HAVE_CRC = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -march=armv8-a+crc -dM -E - 2>/dev/null | $(GREP) -i -c __ARM_FEATURE_CRC32) HAVE_CRC = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -march=armv8-a+crc -dM -E - 2>/dev/null | $(GREP) -i -c __ARM_FEATURE_CRC32)
ifeq ($(HAVE_CRC),1) ifeq ($(HAVE_CRC),1)
@ -397,6 +409,8 @@ ifneq ($(IS_PPC32)$(IS_PPC64)$(IS_AIX),000)
ALTIVEC_FLAG = -mcpu=power4 -maltivec ALTIVEC_FLAG = -mcpu=power4 -maltivec
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
SPECK_FLAG = -mcpu=power4 -maltivec
endif endif
# GCC and some compatibles # GCC and some compatibles
HAVE_CRYPTO = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -mcpu=power8 -maltivec -dM -E - 2>/dev/null | $(GREP) -i -c -E '_ARCH_PWR8|_ARCH_PWR9|__CRYPTO') HAVE_CRYPTO = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -mcpu=power8 -maltivec -dM -E - 2>/dev/null | $(GREP) -i -c -E '_ARCH_PWR8|_ARCH_PWR9|__CRYPTO')
@ -405,6 +419,8 @@ 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
SIMON_FLAG = -mcpu=power8 -maltivec
SPECK_FLAG = -mcpu=power8 -maltivec
endif endif
# IBM XL C/C++ # IBM XL C/C++
HAVE_ALTIVEC = $(shell $(CXX) $(CXXFLAGS) -qshowmacros -qarch=pwr7 -qaltivec -E adhoc.cpp.proto 2>/dev/null | $(GREP) -i -c '__ALTIVEC__') HAVE_ALTIVEC = $(shell $(CXX) $(CXXFLAGS) -qshowmacros -qarch=pwr7 -qaltivec -E adhoc.cpp.proto 2>/dev/null | $(GREP) -i -c '__ALTIVEC__')
@ -412,6 +428,8 @@ 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
SIMON_FLAG = -qarch=pwr7 -qaltivec
SPECK_FLAG = -qarch=pwr7 -qaltivec
endif endif
# IBM XL C/C++ # IBM XL C/C++
HAVE_CRYPTO = $(shell $(CXX) $(CXXFLAGS) -qshowmacros -qarch=pwr8 -qaltivec -E adhoc.cpp.proto 2>/dev/null | $(GREP) -i -c -E '_ARCH_PWR8|_ARCH_PWR9|__CRYPTO') HAVE_CRYPTO = $(shell $(CXX) $(CXXFLAGS) -qshowmacros -qarch=pwr8 -qaltivec -E adhoc.cpp.proto 2>/dev/null | $(GREP) -i -c -E '_ARCH_PWR8|_ARCH_PWR9|__CRYPTO')
@ -422,6 +440,8 @@ 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
SIMON_FLAG = -qarch=pwr8 -qaltivec
SPECK_FLAG = -qarch=pwr8 -qaltivec
endif endif
endif endif
@ -1057,6 +1077,14 @@ 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
simon-simd.o : simon-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SIMON_FLAG) -c) $<
# SSSE3 or NEON available
speck-simd.o : speck-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SPECK_FLAG) -c) $<
# Don't build Rijndael with UBsan. Too much noise due to unaligned data accesses. # Don't build Rijndael with UBsan. Too much noise due to unaligned data accesses.
ifneq ($(findstring -fsanitize=undefined,$(CXXFLAGS)),) ifneq ($(findstring -fsanitize=undefined,$(CXXFLAGS)),)
rijndael.o : rijndael.cpp rijndael.o : rijndael.cpp

View File

@ -234,12 +234,16 @@ ifeq ($(IS_NEON),1)
GCM_FLAG += -mfpu=neon GCM_FLAG += -mfpu=neon
ARIA_FLAG += -mfpu=neon ARIA_FLAG += -mfpu=neon
BLAKE2_FLAG += -mfpu=neon BLAKE2_FLAG += -mfpu=neon
SIMON_FLAG += -mfpu=neon
SPECK_FLAG += -mfpu=neon
ifeq ($(IS_ANDROID),1) ifeq ($(IS_ANDROID),1)
ifeq ($(findstring -mfloat-abi=softfp,$(CXXFLAGS)),) ifeq ($(findstring -mfloat-abi=softfp,$(CXXFLAGS)),)
NEON_FLAG += -mfloat-abi=softfp NEON_FLAG += -mfloat-abi=softfp
GCM_FLAG += -mfloat-abi=softfp GCM_FLAG += -mfloat-abi=softfp
ARIA_FLAG += -mfloat-abi=softfp ARIA_FLAG += -mfloat-abi=softfp
BLAKE2_FLAG += -mfloat-abi=softfp BLAKE2_FLAG += -mfloat-abi=softfp
SIMON_FLAG += -mfloat-abi=softfp
SPECK_FLAG += -mfloat-abi=softfp
endif endif
endif endif
endif endif
@ -252,6 +256,8 @@ ifneq ($(IS_ARMv8),0)
ARIA_FLAG = -march=armv8-a ARIA_FLAG = -march=armv8-a
BLAKE2_FLAG = -march=armv8-a BLAKE2_FLAG = -march=armv8-a
NEON_FLAG = -march=armv8-a NEON_FLAG = -march=armv8-a
SIMON_FLAG = -march=armv8-a
SPECK_FLAG = -march=armv8-a
endif endif
HAVE_CRC := $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -march=armv8-a+crc -dM -E - 2>/dev/null | $(EGREP) -i -c __ARM_FEATURE_CRC32) HAVE_CRC := $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -march=armv8-a+crc -dM -E - 2>/dev/null | $(EGREP) -i -c __ARM_FEATURE_CRC32)
ifeq ($(HAVE_CRC),1) ifeq ($(HAVE_CRC),1)
@ -271,9 +277,13 @@ ifneq ($(IS_i686)$(IS_x86_64),00)
ifeq ($(HAVE_SSSE3),1) ifeq ($(HAVE_SSSE3),1)
ARIA_FLAG = -mssse3 ARIA_FLAG = -mssse3
SSSE3_FLAG = -mssse3 SSSE3_FLAG = -mssse3
SIMON_FLAG = -mssse3
SPECK_FLAG = -mssse3
endif endif
HAVE_SSE4 = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -msse4.1 -dM -E - 2>/dev/null | $(EGREP) -i -c __SSE4_1__) HAVE_SSE4 = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -msse4.1 -dM -E - 2>/dev/null | $(EGREP) -i -c __SSE4_1__)
ifeq ($(HAVE_SSE4),1) ifeq ($(HAVE_SSE4),1)
SIMON_FLAG = -msse4.1
SPECK_FLAG = -msse4.1
endif endif
HAVE_SSE4 = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -msse4.2 -dM -E - 2>/dev/null | $(EGREP) -i -c __SSE4_2__) HAVE_SSE4 = $(shell echo | $(CXX) -x c++ $(CXXFLAGS) -msse4.2 -dM -E - 2>/dev/null | $(EGREP) -i -c __SSE4_2__)
ifeq ($(HAVE_SSE4),1) ifeq ($(HAVE_SSE4),1)
@ -500,6 +510,14 @@ 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
simon-simd.o : simon-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SIMON_FLAG) -c) $<
# SSSE3 or NEON available
speck-simd.o : speck-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(SPECK_FLAG) -c) $<
%.o : %.cpp %.o : %.cpp
$(CXX) $(strip $(CXXFLAGS) -c) $< $(CXX) $(strip $(CXXFLAGS) -c) $<

View File

@ -614,6 +614,18 @@ void Benchmark2(double t, double hertz)
BenchMarkByName<SymmetricCipher>("Kalyna-256/CTR", 32, "Kalyna-256(256)/CTR (256-bit key)"); BenchMarkByName<SymmetricCipher>("Kalyna-256/CTR", 32, "Kalyna-256(256)/CTR (256-bit key)");
BenchMarkByName<SymmetricCipher>("Kalyna-256/CTR", 64, "Kalyna-256(512)/CTR (512-bit key)"); BenchMarkByName<SymmetricCipher>("Kalyna-256/CTR", 64, "Kalyna-256(512)/CTR (512-bit key)");
BenchMarkByName<SymmetricCipher>("Kalyna-512/CTR", 64, "Kalyna-512(512)/CTR (512-bit key)"); BenchMarkByName<SymmetricCipher>("Kalyna-512/CTR", 64, "Kalyna-512(512)/CTR (512-bit key)");
BenchMarkByName<SymmetricCipher>("SIMON-64/CTR", 12, "SIMON-64(96)/CTR (96-bit key)");
BenchMarkByName<SymmetricCipher>("SIMON-64/CTR", 16, "SIMON-64(128)/CTR (128-bit key)");
BenchMarkByName<SymmetricCipher>("SIMON-128/CTR", 16, "SIMON-128(128)/CTR (128-bit key)");
BenchMarkByName<SymmetricCipher>("SIMON-128/CTR", 24, "SIMON-128(192)/CTR (192-bit key)");
BenchMarkByName<SymmetricCipher>("SIMON-128/CTR", 32, "SIMON-128(256)/CTR (256-bit key)");
BenchMarkByName<SymmetricCipher>("SPECK-64/CTR", 12, "SPECK-64(96)/CTR (96-bit key)");
BenchMarkByName<SymmetricCipher>("SPECK-64/CTR", 16, "SPECK-64(128)/CTR (128-bit key)");
BenchMarkByName<SymmetricCipher>("SPECK-128/CTR", 16, "SPECK-128(128)/CTR (128-bit key)");
BenchMarkByName<SymmetricCipher>("SPECK-128/CTR", 24, "SPECK-128(192)/CTR (192-bit key)");
BenchMarkByName<SymmetricCipher>("SPECK-128/CTR", 32, "SPECK-128(256)/CTR (256-bit key)");
} }
std::cout << "\n<TBODY style=\"background: yellow;\">"; std::cout << "\n<TBODY style=\"background: yellow;\">";

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 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 hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.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 seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.cpp skipjack.cpp sm3.cpp sm4.cpp socketft.cpp sosemanuk.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 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 hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.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 seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.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 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 hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.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 seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.obj skipjack.obj sm3.obj sm4.obj socketft.obj sosemanuk.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 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 hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.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 seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.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

@ -288,12 +288,16 @@
<ClCompile Include="shacal2-simd.cpp" /> <ClCompile Include="shacal2-simd.cpp" />
<ClCompile Include="shark.cpp" /> <ClCompile Include="shark.cpp" />
<ClCompile Include="sharkbox.cpp" /> <ClCompile Include="sharkbox.cpp" />
<ClCompile Include="simon.cpp" />
<ClCompile Include="simon-simd.cpp" />
<ClCompile Include="simple.cpp" /> <ClCompile Include="simple.cpp" />
<ClCompile Include="skipjack.cpp" /> <ClCompile Include="skipjack.cpp" />
<ClCompile Include="sm3.cpp" /> <ClCompile Include="sm3.cpp" />
<ClCompile Include="sm4.cpp" /> <ClCompile Include="sm4.cpp" />
<ClCompile Include="socketft.cpp" /> <ClCompile Include="socketft.cpp" />
<ClCompile Include="sosemanuk.cpp" /> <ClCompile Include="sosemanuk.cpp" />
<ClCompile Include="speck.cpp" />
<ClCompile Include="speck-simd.cpp" />
<ClCompile Include="square.cpp" /> <ClCompile Include="square.cpp" />
<ClCompile Include="squaretb.cpp" /> <ClCompile Include="squaretb.cpp" />
<ClCompile Include="sse-simd.cpp" /> <ClCompile Include="sse-simd.cpp" />
@ -474,6 +478,7 @@
<ClInclude Include="shacal2.h" /> <ClInclude Include="shacal2.h" />
<ClInclude Include="shark.h" /> <ClInclude Include="shark.h" />
<ClInclude Include="simple.h" /> <ClInclude Include="simple.h" />
<ClInclude Include="simon.h" />
<ClInclude Include="siphash.h" /> <ClInclude Include="siphash.h" />
<ClInclude Include="skipjack.h" /> <ClInclude Include="skipjack.h" />
<ClInclude Include="sm3.h" /> <ClInclude Include="sm3.h" />
@ -481,6 +486,7 @@
<ClInclude Include="smartptr.h" /> <ClInclude Include="smartptr.h" />
<ClInclude Include="socketft.h" /> <ClInclude Include="socketft.h" />
<ClInclude Include="sosemanuk.h" /> <ClInclude Include="sosemanuk.h" />
<ClInclude Include="speck.h" />
<ClInclude Include="square.h" /> <ClInclude Include="square.h" />
<ClInclude Include="stdcpp.h" /> <ClInclude Include="stdcpp.h" />
<ClInclude Include="strciphr.h" /> <ClInclude Include="strciphr.h" />

View File

@ -359,6 +359,12 @@
<ClCompile Include="sharkbox.cpp"> <ClCompile Include="sharkbox.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="simon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="simon-simd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="simple.cpp"> <ClCompile Include="simple.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -371,6 +377,12 @@
<ClCompile Include="sm4.cpp"> <ClCompile Include="sm4.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="speck.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="speck-simd.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="socketft.cpp"> <ClCompile Include="socketft.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -816,6 +828,9 @@
<ClInclude Include="shark.h"> <ClInclude Include="shark.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="simon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="simple.h"> <ClInclude Include="simple.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -834,6 +849,9 @@
<ClInclude Include="smartptr.h"> <ClInclude Include="smartptr.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="speck.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="socketft.h"> <ClInclude Include="socketft.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>

View File

@ -32,6 +32,8 @@
#include "mars.h" #include "mars.h"
#include "kalyna.h" #include "kalyna.h"
#include "threefish.h" #include "threefish.h"
#include "simon.h"
#include "speck.h"
#include "sm4.h" #include "sm4.h"
#include "des.h" #include "des.h"
#include "idea.h" #include "idea.h"
@ -161,6 +163,19 @@ void RegisterFactories2()
RegisterSymmetricCipherDefaultFactories<CTR_Mode<Threefish512> >(); // Benchmarks RegisterSymmetricCipherDefaultFactories<CTR_Mode<Threefish512> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<CTR_Mode<Threefish1024> >(); // Benchmarks RegisterSymmetricCipherDefaultFactories<CTR_Mode<Threefish1024> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<ECB_Mode<SIMON64> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CBC_Mode<SIMON64> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<ECB_Mode<SIMON128> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CBC_Mode<SIMON128> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CTR_Mode<SIMON64> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<CTR_Mode<SIMON128> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<ECB_Mode<SPECK64> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CBC_Mode<SPECK64> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<ECB_Mode<SPECK128> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CBC_Mode<SPECK128> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CTR_Mode<SPECK64> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<CTR_Mode<SPECK128> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<ECB_Mode<SM4> >(); // Test Vectors RegisterSymmetricCipherDefaultFactories<ECB_Mode<SM4> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CBC_Mode<SM4> >(); // Test Vectors RegisterSymmetricCipherDefaultFactories<CBC_Mode<SM4> >(); // Test Vectors

1141
simon-simd.cpp Normal file

File diff suppressed because it is too large Load Diff

463
simon.cpp Normal file
View File

@ -0,0 +1,463 @@
// simon.h - written and placed in the public domain by Jeffrey Walton
#include "pch.h"
#include "config.h"
#include "simon.h"
#include "misc.h"
#include "cpu.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_SSE41_AVAILABLE
// #undef CRYPTOPP_ARM_NEON_AVAILABLE
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::word32;
using CryptoPP::word64;
using CryptoPP::rotlConstant;
using CryptoPP::rotrConstant;
/// \brief Round transformation helper
/// \tparam W word type
/// \param v value
template <class W>
inline W f(const W v)
{
return (rotlConstant<1>(v) & rotlConstant<8>(v)) ^ rotlConstant<2>(v);
}
/// \brief Round transformation
/// \tparam W word type
/// \param x value
/// \param y value
/// \param k value
/// \param l value
template <class W>
inline void R2(W& x, W& y, const W k, const W l)
{
y ^= f(x); y ^= k;
x ^= f(y); x ^= l;
}
/// \brief Forward transformation
/// \tparam W word type
/// \tparam R number of rounds
/// \param c output array
/// \param p input array
/// \param k subkey array
template <class W, unsigned int R>
inline void SIMON_Encrypt(W c[2], const W p[2], const W k[R])
{
c[0]=p[0]; c[1]=p[1];
for (int i = 0; i < static_cast<int>(R-1); i += 2)
R2(c[0], c[1], k[i], k[i + 1]);
if (R & 1)
{
c[1] ^= f(c[0]); c[1] ^= k[R-1];
W t = c[0]; c[0] = c[1]; c[1] = t;
}
}
/// \brief Reverse transformation
/// \tparam W word type
/// \tparam R number of rounds
/// \param p output array
/// \param c input array
/// \param k subkey array
template <class W, unsigned int R>
inline void SIMON_Decrypt(W p[2], const W c[2], const W k[R])
{
p[0]=c[0]; p[1]=c[1];
unsigned int rounds = R;
if (R & 1)
{
const W t = p[1]; p[1] = p[0]; p[0] = t;
p[1] ^= k[R - 1]; p[1] ^= f(p[0]);
rounds--;
}
for (int i = static_cast<int>(rounds - 2); i >= 0; i -= 2)
R2(p[1], p[0], k[i + 1], k[i]);
}
/// \brief Subkey generation function
/// \details Used for SIMON-64 with 96-bit key and 42 rounds. A template was
/// not worthwhile because all instantiations would need specialization.
/// \param key empty subkey array
/// \param k user key array
inline void SIMON64_ExpandKey_3W(word32 key[42], const word32 k[3])
{
const word32 c = 0xfffffffc;
word64 z = W64LIT(0x7369f885192c0ef5);
key[0] = k[2]; key[1] = k[1]; key[2] = k[0];
for (size_t i = 3; i<42; ++i)
{
key[i] = c ^ (z & 1) ^ key[i - 3] ^ rotrConstant<3>(key[i - 1]) ^ rotrConstant<4>(key[i - 1]);
z >>= 1;
}
}
/// \brief Subkey generation function
/// \details Used for SIMON-64 with 128-bit key and 44 rounds. A template was
/// not worthwhile because all instantiations would need specialization.
/// \param key empty subkey array
/// \param k user key array
inline void SIMON64_ExpandKey_4W(word32 key[44], const word32 k[4])
{
const word32 c = 0xfffffffc;
word64 z = W64LIT(0xfc2ce51207a635db);
key[0] = k[3]; key[1] = k[2]; key[2] = k[1]; key[3] = k[0];
for (size_t i = 4; i<44; ++i)
{
key[i] = c ^ (z & 1) ^ key[i - 4] ^ rotrConstant<3>(key[i - 1]) ^ key[i - 3] ^ rotrConstant<4>(key[i - 1]) ^ rotrConstant<1>(key[i - 3]);
z >>= 1;
}
}
/// \brief Subkey generation function
/// \details Used for SIMON-128 with 128-bit key and 68 rounds. A template was
/// not worthwhile because all instantiations would need specialization.
/// \param key empty subkey array
/// \param k user key array
inline void SIMON128_ExpandKey_2W(word64 key[68], const word64 k[2])
{
const word64 c = W64LIT(0xfffffffffffffffc);
word64 z = W64LIT(0x7369f885192c0ef5);
key[0] = k[1]; key[1] = k[0];
for (size_t i=2; i<66; ++i)
{
key[i] = c ^ (z & 1) ^ key[i - 2] ^ rotrConstant<3>(key[i - 1]) ^ rotrConstant<4>(key[i - 1]);
z>>=1;
}
key[66] = c ^ 1 ^ key[64] ^ rotrConstant<3>(key[65]) ^ rotrConstant<4>(key[65]);
key[67] = c^key[65] ^ rotrConstant<3>(key[66]) ^ rotrConstant<4>(key[66]);
}
/// \brief Subkey generation function
/// \details Used for SIMON-128 with 192-bit key and 69 rounds. A template was
/// not worthwhile because all instantiations would need specialization.
/// \param key empty subkey array
/// \param k user key array
inline void SIMON128_ExpandKey_3W(word64 key[69], const word64 k[3])
{
const word64 c = W64LIT(0xfffffffffffffffc);
word64 z = W64LIT(0xfc2ce51207a635db);
key[0]=k[2]; key[1]=k[1]; key[2]=k[0];
for (size_t i=3; i<67; ++i)
{
key[i] = c ^ (z & 1) ^ key[i - 3] ^ rotrConstant<3>(key[i - 1]) ^ rotrConstant<4>(key[i - 1]);
z>>=1;
}
key[67] = c^key[64] ^ rotrConstant<3>(key[66]) ^ rotrConstant<4>(key[66]);
key[68] = c ^ 1 ^ key[65] ^ rotrConstant<3>(key[67]) ^ rotrConstant<4>(key[67]);
}
/// \brief Subkey generation function
/// \details Used for SIMON-128 with 256-bit key and 72 rounds. A template was
/// not worthwhile because all instantiations would need specialization.
/// \param key empty subkey array
/// \param k user key array
inline void SIMON128_ExpandKey_4W(word64 key[72], const word64 k[4])
{
const word64 c = W64LIT(0xfffffffffffffffc);
word64 z = W64LIT(0xfdc94c3a046d678b);
key[0]=k[3]; key[1]=k[2]; key[2]=k[1]; key[3]=k[0];
for (size_t i=4; i<68; ++i)
{
key[i] = c ^ (z & 1) ^ key[i - 4] ^ rotrConstant<3>(key[i - 1]) ^ key[i - 3] ^ rotrConstant<4>(key[i - 1]) ^ rotrConstant<1>(key[i - 3]);
z>>=1;
}
key[68] = c^key[64] ^ rotrConstant<3>(key[67]) ^ key[65] ^ rotrConstant<4>(key[67]) ^ rotrConstant<1>(key[65]);
key[69] = c ^ 1 ^ key[65] ^ rotrConstant<3>(key[68]) ^ key[66] ^ rotrConstant<4>(key[68]) ^ rotrConstant<1>(key[66]);
key[70] = c^key[66] ^ rotrConstant<3>(key[69]) ^ key[67] ^ rotrConstant<4>(key[69]) ^ rotrConstant<1>(key[67]);
key[71] = c^key[67] ^ rotrConstant<3>(key[70]) ^ key[68] ^ rotrConstant<4>(key[70]) ^ rotrConstant<1>(key[68]);
}
ANONYMOUS_NAMESPACE_END
///////////////////////////////////////////////////////////
NAMESPACE_BEGIN(CryptoPP)
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
extern size_t SIMON64_Enc_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
extern size_t SIMON64_Dec_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
#endif
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
extern size_t SIMON128_Enc_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
extern size_t SIMON128_Dec_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
#endif
#if defined(CRYPTOPP_SSE41_AVAILABLE)
extern size_t SIMON64_Enc_AdvancedProcessBlocks_SSE41(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
extern size_t SIMON64_Dec_AdvancedProcessBlocks_SSE41(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
#endif
#if defined(CRYPTOPP_SSSE3_AVAILABLE)
extern size_t SIMON128_Enc_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
extern size_t SIMON128_Dec_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
#endif
void SIMON64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16);
CRYPTOPP_UNUSED(params);
// Building the key schedule table requires {3,4} words workspace.
// Encrypting and decrypting requires 4 words workspace.
m_kwords = keyLength/sizeof(word32);
m_wspace.New(4U);
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word32, LittleEndian, false> KeyBlock;
KeyBlock kblk(userKey);
switch (m_kwords)
{
case 3:
m_rkeys.New((m_rounds = 42));
kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SIMON64_ExpandKey_3W(m_rkeys, m_wspace);
break;
case 4:
m_rkeys.New((m_rounds = 44));
kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SIMON64_ExpandKey_4W(m_rkeys, m_wspace);
break;
default:
CRYPTOPP_ASSERT(0);;
}
}
void SIMON64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word32, LittleEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
switch (m_rounds)
{
case 42:
SIMON_Encrypt<word32, 42>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 44:
SIMON_Encrypt<word32, 44>(m_wspace+2, m_wspace+0, m_rkeys);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Do the endian gyrations from the paper and align pointers
typedef PutBlock<word32, LittleEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
}
void SIMON64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word32, LittleEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
switch (m_rounds)
{
case 42:
SIMON_Decrypt<word32, 42>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 44:
SIMON_Decrypt<word32, 44>(m_wspace+2, m_wspace+0, m_rkeys);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Do the endian gyrations from the paper and align pointers
typedef PutBlock<word32, LittleEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
}
///////////////////////////////////////////////////////////
void SIMON128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32);
CRYPTOPP_UNUSED(params);
// Building the key schedule table requires {2,3,4} words workspace.
// Encrypting and decrypting requires 4 words workspace.
m_kwords = keyLength/sizeof(word64);
m_wspace.New(4U);
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word64, LittleEndian, false> KeyBlock;
KeyBlock kblk(userKey);
switch (m_kwords)
{
case 2:
m_rkeys.New((m_rounds = 68));
kblk(m_wspace[1])(m_wspace[0]);
SIMON128_ExpandKey_2W(m_rkeys, m_wspace);
break;
case 3:
m_rkeys.New((m_rounds = 69));
kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SIMON128_ExpandKey_3W(m_rkeys, m_wspace);
break;
case 4:
m_rkeys.New((m_rounds = 72));
kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SIMON128_ExpandKey_4W(m_rkeys, m_wspace);
break;
default:
CRYPTOPP_ASSERT(0);;
}
}
void SIMON128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word64, LittleEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
switch (m_rounds)
{
case 68:
SIMON_Encrypt<word64, 68>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 69:
SIMON_Encrypt<word64, 69>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 72:
SIMON_Encrypt<word64, 72>(m_wspace+2, m_wspace+0, m_rkeys);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Do the endian gyrations from the paper and align pointers
typedef PutBlock<word64, LittleEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
}
void SIMON128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word64, LittleEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
switch (m_rounds)
{
case 68:
SIMON_Decrypt<word64, 68>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 69:
SIMON_Decrypt<word64, 69>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 72:
SIMON_Decrypt<word64, 72>(m_wspace+2, m_wspace+0, m_rkeys);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Do the endian gyrations from the paper and align pointers
typedef PutBlock<word64, LittleEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
}
#if defined(CRYPTOPP_SIMON64_ADVANCED_PROCESS_BLOCKS)
size_t SIMON64::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
byte *outBlocks, size_t length, word32 flags) const
{
#if defined(CRYPTOPP_SSE41_AVAILABLE)
if (HasSSE41())
return SIMON64_Enc_AdvancedProcessBlocks_SSE41(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
return SIMON64_Enc_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
}
size_t SIMON64::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
byte *outBlocks, size_t length, word32 flags) const
{
#if defined(CRYPTOPP_SSE41_AVAILABLE)
if (HasSSE41())
return SIMON64_Dec_AdvancedProcessBlocks_SSE41(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
return SIMON64_Dec_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
}
#endif // CRYPTOPP_SIMON64_ADVANCED_PROCESS_BLOCKS
#if defined(CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS)
size_t SIMON128::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
byte *outBlocks, size_t length, word32 flags) const
{
#if defined(CRYPTOPP_SSSE3_AVAILABLE)
if (HasSSSE3())
return SIMON128_Enc_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
return SIMON128_Enc_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
}
size_t SIMON128::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
byte *outBlocks, size_t length, word32 flags) const
{
#if defined(CRYPTOPP_SSSE3_AVAILABLE)
if (HasSSSE3())
return SIMON128_Dec_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
return SIMON128_Dec_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
}
#endif // CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS
NAMESPACE_END

180
simon.h Normal file
View File

@ -0,0 +1,180 @@
// simon.h - written and placed in the public domain by Jeffrey Walton
/// \file simon.h
/// \brief Classes for the Simon block cipher
/// \details Simon is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith,
/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers.
/// \sa <A HREF="http://eprint.iacr.org/2013/404">The SIMON and SPECK Families of
/// Lightweight Block Ciphers</A>, <A HREF="http://iadgov.github.io/simon-speck/">
/// The Simon and Speck GitHub</A> and <A HREF="https://www.cryptopp.com/wiki/SIMON">
/// SIMON</A> on the Crypto++ wiki.
/// \since Crypto++ 6.0
#ifndef CRYPTOPP_SIMON_H
#define CRYPTOPP_SIMON_H
#include "config.h"
#include "seckey.h"
#include "secblock.h"
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86
# define CRYPTOPP_SIMON64_ADVANCED_PROCESS_BLOCKS 1
#endif
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86
# define CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS 1
#endif
NAMESPACE_BEGIN(CryptoPP)
/// \brief SIMON block cipher information
/// \tparam L block size of the cipher, in bytes
/// \tparam D default key length, in bytes
/// \tparam N minimum key length, in bytes
/// \tparam M maximum key length, in bytes
/// \since Crypto++ 6.0
template <unsigned int L, unsigned int D, unsigned int N, unsigned int M>
struct SIMON_Info : public FixedBlockSize<L>, VariableKeyLength<D, N, M>
{
static const std::string StaticAlgorithmName()
{
// Format is Cipher-Blocksize(Keylength)
return "SIMON-" + IntToString(L*8);
}
};
/// \brief SIMON block cipher base class
/// \tparam W the word type
/// \details User code should use SIMON64 or SIMON128
/// \sa SIMON64, SIMON128, <a href="http://www.cryptopp.com/wiki/SIMON">SIMON</a> on the Crypto++ wiki
/// \since Crypto++ 6.0
template <class W>
struct SIMON_Base
{
virtual ~SIMON_Base() {}
SIMON_Base() : m_kwords(0), m_rounds(0) {}
typedef SecBlock<W, AllocatorWithCleanup<W, true> > AlignedSecBlock;
mutable AlignedSecBlock m_wspace; // workspace
AlignedSecBlock m_rkeys; // round keys
unsigned int m_kwords; // number of key words
unsigned int m_rounds; // number of rounds
};
/// \brief SIMON 64-bit block cipher
/// \details Simon is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith,
/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers.
/// \details SIMON64 provides 64-bit block size. The valid key sizes are 96-bit and 128-bit.
/// \sa SIMON64, SIMON128, <A HREF="http://eprint.iacr.org/2013/404">The SIMON and SIMON
/// Families of Lightweight Block Ciphers</A>, <A HREF="http://iadgov.github.io/simon-speck/">
/// The Simon and Speck GitHub</A>, <a href="http://www.cryptopp.com/wiki/SIMON">SIMON</a> on the
/// Crypto++ wiki
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE SIMON64 : public SIMON_Info<8, 12, 12, 16>, public BlockCipherDocumentation
{
public:
/// \brief SIMON block cipher transformation functions
/// \details Provides implementation common to encryption and decryption
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Base : protected SIMON_Base<word32>, public BlockCipherImpl<SIMON_Info<8, 12, 12, 16> >
{
public:
std::string AlgorithmName() const {
return StaticAlgorithmName() + (m_kwords == 0 ? "" :
"(" + IntToString(m_kwords*sizeof(word32)*8) + ")");
}
protected:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
};
/// \brief Provides implementation for encryption transformation
/// \details Enc provides implementation for encryption transformation. All key
/// sizes are supported.
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Enc : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
#if CRYPTOPP_SIMON64_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
/// \details Dec provides implementation for decryption transformation. All key
/// sizes are supported.
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Dec : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
#if CRYPTOPP_SIMON64_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<DECRYPTION, Dec> Decryption;
};
/// \brief SIMON 128-bit block cipher
/// \details Simon is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith,
/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers.
/// \details SIMON128 provides 128-bit block size. The valid key sizes are 128-bit, 192-bit and 256-bit.
/// \sa SIMON64, SIMON128, <A HREF="http://eprint.iacr.org/2013/404">The SIMON and SIMON
/// Families of Lightweight Block Ciphers</A>, <A HREF="http://iadgov.github.io/simon-speck/">
/// The Simon and Speck GitHub</A>, <a href="http://www.cryptopp.com/wiki/SIMON">SIMON</a> on the
/// Crypto++ wiki
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE SIMON128 : public SIMON_Info<16, 16, 16, 32>, public BlockCipherDocumentation
{
public:
/// \brief SIMON block cipher transformation functions
/// \details Provides implementation common to encryption and decryption
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Base : protected SIMON_Base<word64>, public BlockCipherImpl<SIMON_Info<16, 16, 16, 32> >
{
public:
std::string AlgorithmName() const {
return StaticAlgorithmName() + (m_kwords == 0 ? "" :
"(" + IntToString(m_kwords*sizeof(word64)*8) + ")");
}
protected:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
};
/// \brief Provides implementation for encryption transformation
/// \details Enc provides implementation for encryption transformation. All key
/// sizes are supported.
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Enc : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
#if CRYPTOPP_SIMON128_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
/// \details Dec provides implementation for decryption transformation. All key
/// sizes are supported.
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Dec : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
#if CRYPTOPP_SIMON128_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<DECRYPTION, Dec> Decryption;
};
NAMESPACE_END
#endif // CRYPTOPP_SIMON_H

1031
speck-simd.cpp Normal file

File diff suppressed because it is too large Load Diff

438
speck.cpp Normal file
View File

@ -0,0 +1,438 @@
// speck.cpp - written and placed in the public domain by Jeffrey Walton
#include "pch.h"
#include "config.h"
#include "speck.h"
#include "misc.h"
#include "cpu.h"
// Uncomment for benchmarking C++ against SSE or NEON.
// Do so in both speck.cpp and speck-simd.cpp.
// #undef CRYPTOPP_SSSE3_AVAILABLE
// #undef CRYPTOPP_SSE41_AVAILABLE
// #undef CRYPTOPP_ARM_NEON_AVAILABLE
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::word32;
using CryptoPP::word64;
using CryptoPP::rotlConstant;
using CryptoPP::rotrConstant;
/// \brief Forward round transformation
/// \tparam W word type
/// \details TF83() is the forward round transformation using a=8 and b=3 rotations.
/// The initial test implementation provided template parameters, but they were
/// removed because SPECK32 using a=7 and b=2 was not on the road map. The
/// additional template parameters also made calling SPECK_Encrypt and SPECK_Decrypt
/// kind of messy.
template <class W>
inline void TF83(W& x, W& y, const W k)
{
x = rotrConstant<8>(x);
x += y; x ^= k;
y = rotlConstant<3>(y);
y ^= x;
}
/// \brief Reverse round transformation
/// \tparam W word type
/// \details TR83() is the reverse round transformation using a=8 and b=3 rotations.
/// The initial test implementation provided template parameters, but they were
/// removed because SPECK32 using a=7 and b=2 was not on the road map. The
/// additional template parameters also made calling SPECK_Encrypt and SPECK_Decrypt
/// kind of messy.
template <class W>
inline void TR83(W& x, W& y, const W k)
{
y ^= x;
y = rotrConstant<3>(y);
x ^= k; x -= y;
x = rotlConstant<8>(x);
}
/// \brief Forward transformation
/// \tparam W word type
/// \tparam R number of rounds
/// \param c output array
/// \param p input array
/// \param k subkey array
template <class W, unsigned int R>
inline void SPECK_Encrypt(W c[2], const W p[2], const W k[R])
{
c[0]=p[0]; c[1]=p[1];
// Don't unroll this loop. Things slow down.
for (int i = 0; i < static_cast<int>(R); ++i)
TF83(c[0], c[1], k[i]);
}
/// \brief Reverse transformation
/// \tparam W word type
/// \tparam R number of rounds
/// \param p output array
/// \param c input array
/// \param k subkey array
template <class W, unsigned int R>
inline void SPECK_Decrypt(W p[2], const W c[2], const W k[R])
{
p[0]=c[0]; p[1]=c[1];
// Don't unroll this loop. Things slow down.
for (int i = static_cast<int>(R-1); i >= 0; --i)
TR83(p[0], p[1], k[i]);
}
/// \brief Subkey generation function
/// \details Used when the user key consists of 2 words
/// \tparam W word type
/// \tparam R number of rounds
/// \param key empty subkey array
/// \param k user key array
template <class W, unsigned int R>
inline void SPECK_ExpandKey_2W(W key[R], const W k[2])
{
CRYPTOPP_ASSERT(R==32);
W i=0, B=k[0], A=k[1];
while (i<R-1)
{
key[i]=A; TF83(B, A, i);
i++;
}
key[R-1]=A;
}
/// \brief Subkey generation function
/// \details Used when the user key consists of 3 words
/// \tparam W word type
/// \tparam R number of rounds
/// \param key empty subkey array
/// \param k user key array
template <class W, unsigned int R>
inline void SPECK_ExpandKey_3W(W key[R], const W k[3])
{
CRYPTOPP_ASSERT(R==33 || R==26);
W i=0, C=k[0], B=k[1], A=k[2];
unsigned int blocks = R/2;
while (blocks--)
{
key[i+0]=A; TF83(B, A, i+0);
key[i+1]=A; TF83(C, A, i+1);
i+=2;
}
// The constexpr residue should allow the optimizer to remove unneeded statements
if(R%2 == 1)
{
key[R-1]=A;
}
}
/// \brief Subkey generation function
/// \details Used when the user key consists of 4 words
/// \tparam W word type
/// \tparam R number of rounds
/// \param key empty subkey array
/// \param k user key array
template <class W, unsigned int R>
inline void SPECK_ExpandKey_4W(W key[R], const W k[4])
{
CRYPTOPP_ASSERT(R==34 || R==27);
W i=0, D=k[0], C=k[1], B=k[2], A=k[3];
unsigned int blocks = R/3;
while (blocks--)
{
key[i+0]=A; TF83(B, A, i+0);
key[i+1]=A; TF83(C, A, i+1);
key[i+2]=A; TF83(D, A, i+2);
i+=3;
}
// The constexpr residue should allow the optimizer to remove unneeded statements
if(R%3 == 1)
{
key[R-1]=A;
}
else if(R%3 == 2)
{
key[R-2]=A; TF83(B, A, W(R-2));
key[R-1]=A;
}
}
ANONYMOUS_NAMESPACE_END
///////////////////////////////////////////////////////////
NAMESPACE_BEGIN(CryptoPP)
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
extern size_t SPECK64_Enc_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
extern size_t SPECK64_Dec_AdvancedProcessBlocks_NEON(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
extern size_t SPECK128_Enc_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
extern size_t SPECK128_Dec_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
#endif
#if defined(CRYPTOPP_SSE41_AVAILABLE)
extern size_t SPECK64_Enc_AdvancedProcessBlocks_SSE41(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
extern size_t SPECK64_Dec_AdvancedProcessBlocks_SSE41(const word32* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
#endif
#if defined(CRYPTOPP_SSSE3_AVAILABLE)
extern size_t SPECK128_Enc_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
extern size_t SPECK128_Dec_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds,
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
#endif
void SPECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16);
CRYPTOPP_UNUSED(params);
// Building the key schedule table requires {3,4} words workspace.
// Encrypting and decrypting requires 4 words workspace.
m_kwords = keyLength/sizeof(word32);
m_wspace.New(4U);
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word32, LittleEndian, false> KeyBlock;
KeyBlock kblk(userKey);
switch (m_kwords)
{
case 3:
m_rkeys.New((m_rounds = 26));
kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_ExpandKey_3W<word32, 26>(m_rkeys, m_wspace);
break;
case 4:
m_rkeys.New((m_rounds = 27));
kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_ExpandKey_4W<word32, 27>(m_rkeys, m_wspace);
break;
default:
CRYPTOPP_ASSERT(0);;
}
}
void SPECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word32, LittleEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
switch (m_rounds)
{
case 26:
SPECK_Encrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 27:
SPECK_Encrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkeys);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Do the endian gyrations from the paper and align pointers
typedef PutBlock<word32, LittleEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
}
void SPECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word32, LittleEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
switch (m_rounds)
{
case 26:
SPECK_Decrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 27:
SPECK_Decrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkeys);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Do the endian gyrations from the paper and align pointers
typedef PutBlock<word32, LittleEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
}
///////////////////////////////////////////////////////////
void SPECK128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32);
CRYPTOPP_UNUSED(params);
// Building the key schedule table requires {2,3,4} words workspace.
// Encrypting and decrypting requires 4 words workspace.
m_kwords = keyLength/sizeof(word64);
m_wspace.New(4U);
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word64, LittleEndian, false> KeyBlock;
KeyBlock kblk(userKey);
switch (m_kwords)
{
case 2:
m_rkeys.New((m_rounds = 32));
kblk(m_wspace[1])(m_wspace[0]);
SPECK_ExpandKey_2W<word64, 32>(m_rkeys, m_wspace);
break;
case 3:
m_rkeys.New((m_rounds = 33));
kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_ExpandKey_3W<word64, 33>(m_rkeys, m_wspace);
break;
case 4:
m_rkeys.New((m_rounds = 34));
kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_ExpandKey_4W<word64, 34>(m_rkeys, m_wspace);
break;
default:
CRYPTOPP_ASSERT(0);;
}
}
void SPECK128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word64, LittleEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
switch (m_rounds)
{
case 32:
SPECK_Encrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 33:
SPECK_Encrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 34:
SPECK_Encrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkeys);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Do the endian gyrations from the paper and align pointers
typedef PutBlock<word64, LittleEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
}
void SPECK128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do the endian gyrations from the paper and align pointers
typedef GetBlock<word64, LittleEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
switch (m_rounds)
{
case 32:
SPECK_Decrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 33:
SPECK_Decrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkeys);
break;
case 34:
SPECK_Decrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkeys);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Do the endian gyrations from the paper and align pointers
typedef PutBlock<word64, LittleEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
}
#if defined(CRYPTOPP_SPECK64_ADVANCED_PROCESS_BLOCKS)
size_t SPECK64::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
byte *outBlocks, size_t length, word32 flags) const
{
#if defined(CRYPTOPP_SSE41_AVAILABLE)
if (HasSSE41())
return SPECK64_Enc_AdvancedProcessBlocks_SSE41(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
return SPECK64_Enc_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
}
size_t SPECK64::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
byte *outBlocks, size_t length, word32 flags) const
{
#if defined(CRYPTOPP_SSE41_AVAILABLE)
if (HasSSE41())
return SPECK64_Dec_AdvancedProcessBlocks_SSE41(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
return SPECK64_Dec_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
}
#endif // CRYPTOPP_SPECK64_ADVANCED_PROCESS_BLOCKS
#if defined(CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS)
size_t SPECK128::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
byte *outBlocks, size_t length, word32 flags) const
{
#if defined(CRYPTOPP_SSSE3_AVAILABLE)
if (HasSSSE3())
return SPECK128_Enc_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
return SPECK128_Enc_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
}
size_t SPECK128::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
byte *outBlocks, size_t length, word32 flags) const
{
#if defined(CRYPTOPP_SSSE3_AVAILABLE)
if (HasSSSE3())
return SPECK128_Dec_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
#if defined(CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
return SPECK128_Dec_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
inBlocks, xorBlocks, outBlocks, length, flags);
#endif
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
}
#endif // CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS
NAMESPACE_END

180
speck.h Normal file
View File

@ -0,0 +1,180 @@
// speck.h - written and placed in the public domain by Jeffrey Walton
/// \file speck.h
/// \brief Classes for the Speck block cipher
/// \details Speck is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith,
/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers.
/// \sa <A HREF="http://eprint.iacr.org/2013/404">The SIMON and SPECK Families of
/// Lightweight Block Ciphers</A>, <A HREF="http://iadgov.github.io/simon-speck/">
/// The Simon and Speck GitHub</A> and <A HREF="https://www.cryptopp.com/wiki/SPECK">
/// SPECK</A> on the Crypto++ wiki.
/// \since Crypto++ 6.0
#ifndef CRYPTOPP_SPECK_H
#define CRYPTOPP_SPECK_H
#include "config.h"
#include "seckey.h"
#include "secblock.h"
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86
# define CRYPTOPP_SPECK64_ADVANCED_PROCESS_BLOCKS 1
#endif
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86
# define CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS 1
#endif
NAMESPACE_BEGIN(CryptoPP)
/// \brief SPECK block cipher information
/// \tparam L block size of the cipher, in bytes
/// \tparam D default key length, in bytes
/// \tparam N minimum key length, in bytes
/// \tparam M maximum key length, in bytes
/// \since Crypto++ 6.0
template <unsigned int L, unsigned int D, unsigned int N, unsigned int M>
struct SPECK_Info : public FixedBlockSize<L>, VariableKeyLength<D, N, M>
{
static const std::string StaticAlgorithmName()
{
// Format is Cipher-Blocksize(Keylength)
return "SPECK-" + IntToString(L*8);
}
};
/// \brief SPECK block cipher base class
/// \tparam W the word type
/// \details User code should use SPECK64 or SPECK128
/// \sa SPECK64, SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
/// \since Crypto++ 6.0
template <class W>
struct SPECK_Base
{
virtual ~SPECK_Base() {}
SPECK_Base() : m_kwords(0), m_rounds(0) {}
typedef SecBlock<W, AllocatorWithCleanup<W, true> > AlignedSecBlock;
mutable AlignedSecBlock m_wspace; // workspace
AlignedSecBlock m_rkeys; // round keys
unsigned int m_kwords; // number of key words
unsigned int m_rounds; // number of rounds
};
/// \brief SPECK 64-bit block cipher
/// \details Speck is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith,
/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers.
/// \details SPECK64 provides 64-bit block size. The valid key sizes are 96-bit and 128-bit.
/// \sa SPECK64, SPECK128, <A HREF="http://eprint.iacr.org/2013/404">The SIMON and SPECK
/// Families of Lightweight Block Ciphers</A>, <A HREF="http://iadgov.github.io/simon-speck/">
/// The Simon and Speck GitHub</A>, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a> on the
/// Crypto++ wiki
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE SPECK64 : public SPECK_Info<8, 12, 12, 16>, public BlockCipherDocumentation
{
public:
/// \brief SPECK block cipher transformation functions
/// \details Provides implementation common to encryption and decryption
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base<word32>, public BlockCipherImpl<SPECK_Info<8, 12, 12, 16> >
{
public:
std::string AlgorithmName() const {
return StaticAlgorithmName() + (m_kwords == 0 ? "" :
"(" + IntToString(m_kwords*sizeof(word32)*8) + ")");
}
protected:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
};
/// \brief Provides implementation for encryption transformation
/// \details Enc provides implementation for encryption transformation. All key
/// sizes are supported.
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Enc : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
#if CRYPTOPP_SPECK64_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
/// \details Dec provides implementation for decryption transformation. All key
/// sizes are supported.
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Dec : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
#if CRYPTOPP_SPECK64_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<DECRYPTION, Dec> Decryption;
};
/// \brief SPECK 128-bit block cipher
/// \details Speck is a block cipher designed by Ray Beaulieu, Douglas Shors, Jason Smith,
/// Stefan Treatman-Clark, Bryan Weeks and Louis Wingers.
/// \details SPECK128 provides 128-bit block size. The valid key sizes are 128-bit, 192-bit and 256-bit.
/// \sa SPECK64, SPECK128, <A HREF="http://eprint.iacr.org/2013/404">The SIMON and SPECK
/// Families of Lightweight Block Ciphers</A>, <A HREF="http://iadgov.github.io/simon-speck/">
/// The Simon and Speck GitHub</A>, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a> on the
/// Crypto++ wiki
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE SPECK128 : public SPECK_Info<16, 16, 16, 32>, public BlockCipherDocumentation
{
public:
/// \brief SPECK block cipher transformation functions
/// \details Provides implementation common to encryption and decryption
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base<word64>, public BlockCipherImpl<SPECK_Info<16, 16, 16, 32> >
{
public:
std::string AlgorithmName() const {
return StaticAlgorithmName() + (m_kwords == 0 ? "" :
"(" + IntToString(m_kwords*sizeof(word64)*8) + ")");
}
protected:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
};
/// \brief Provides implementation for encryption transformation
/// \details Enc provides implementation for encryption transformation. All key
/// sizes are supported.
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Enc : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
#if CRYPTOPP_SPECK128_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
/// \details Dec provides implementation for decryption transformation. All key
/// sizes are supported.
/// \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Dec : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
#if CRYPTOPP_SPECK128_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<DECRYPTION, Dec> Decryption;
};
NAMESPACE_END
#endif // CRYPTOPP_SPECK_H