Add SIMON-64 and SIMON-128 lightweight block ciphers (GH #539)
parent
5007c13fbd
commit
3970a066e3
|
|
@ -275,6 +275,8 @@ simple.h
|
|||
siphash.h
|
||||
skipjack.cpp
|
||||
skipjack.h
|
||||
simon.cpp
|
||||
simon.h
|
||||
smartptr.h
|
||||
socketft.cpp
|
||||
socketft.h
|
||||
|
|
@ -456,6 +458,7 @@ TestVectors/sha3_256_fips_202.txt
|
|||
TestVectors/sha3_384_fips_202.txt
|
||||
TestVectors/sha3_512_fips_202.txt
|
||||
TestVectors/shacal2.txt
|
||||
TestVectors/simon.txt
|
||||
TestVectors/siphash.txt
|
||||
TestVectors/sosemanuk.txt
|
||||
TestVectors/speck.txt
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
AlgorithmType: SymmetricCipher
|
||||
Name: SIMON-64/ECB
|
||||
#
|
||||
Source: Simon and Speck paper, Appendix B
|
||||
Comment: Simon64/96
|
||||
Key: 13121110 0b0a0908 03020100
|
||||
Plaintext: 6f722067 6e696c63
|
||||
Ciphertext: 5ca2e27f 111a8fc8
|
||||
Test: Encrypt
|
||||
#
|
||||
Source: Simon and Speck paper, Appendix B
|
||||
Comment: Simon64/128
|
||||
Key: 1b1a1918 13121110 0b0a0908 03020100
|
||||
Plaintext: 656b696c 20646e75
|
||||
Ciphertext: 44c8fc20 b9dfa07a
|
||||
Test: Encrypt
|
||||
|
||||
|
||||
AlgorithmType: SymmetricCipher
|
||||
Name: SIMON-128/ECB
|
||||
#
|
||||
Source: Simon and Speck paper, Appendix B
|
||||
Comment: Simon128/128
|
||||
Key: 0f0e0d0c0b0a0908 0706050403020100
|
||||
Plaintext: 6373656420737265 6c6c657661727420
|
||||
Ciphertext: 49681b1e1e54fe3f 65aa832af84e0bbc
|
||||
Test: Encrypt
|
||||
#
|
||||
Source: Simon and Speck paper, Appendix B
|
||||
Comment: Simon128/192
|
||||
Key: 1716151413121110 0f0e0d0c0b0a0908 0706050403020100
|
||||
Plaintext: 206572656874206e 6568772065626972
|
||||
Ciphertext: c4ac61effcdc0d4f 6c9c8d6e2597b85b
|
||||
Test: Encrypt
|
||||
#
|
||||
Source: Simon and Speck paper, Appendix B
|
||||
Comment: Simon128/256
|
||||
Key: 1f1e1d1c1b1a1918 1716151413121110 0f0e0d0c0b0a0908 0706050403020100
|
||||
Plaintext: 74206e69206d6f6f 6d69732061207369
|
||||
Ciphertext: 8d2b5579afc8a3a0 3bf72a87efe7b868
|
||||
Test: Encrypt
|
||||
|
|
@ -604,6 +604,12 @@ void Benchmark2(double t, double hertz)
|
|||
BenchMarkByName<SymmetricCipher>("Kalyna/CTR", 64, "Kalyna-256(512) (512-bit key)", MakeParameters(Name::BlockSize(), 32));
|
||||
BenchMarkByName<SymmetricCipher>("Kalyna/CTR", 64, "Kalyna-512(512) (512-bit key)", MakeParameters(Name::BlockSize(), 64));
|
||||
|
||||
BenchMarkByName<SymmetricCipher>("SIMON-64/CTR", 12, "SIMON-64(96) (96-bit key)");
|
||||
BenchMarkByName<SymmetricCipher>("SIMON-64/CTR", 16, "SIMON-64(128) (128-bit key)");
|
||||
BenchMarkByName<SymmetricCipher>("SIMON-128/CTR", 16, "SIMON-128(128) (128-bit key)");
|
||||
BenchMarkByName<SymmetricCipher>("SIMON-128/CTR", 24, "SIMON-128(192) (192-bit key)");
|
||||
BenchMarkByName<SymmetricCipher>("SIMON-128/CTR", 32, "SIMON-128(256) (256-bit key)");
|
||||
|
||||
BenchMarkByName<SymmetricCipher>("SPECK-64/CTR", 12, "SPECK-64(96) (96-bit key)");
|
||||
BenchMarkByName<SymmetricCipher>("SPECK-64/CTR", 16, "SPECK-64(128) (128-bit key)");
|
||||
BenchMarkByName<SymmetricCipher>("SPECK-128/CTR", 16, "SPECK-128(128) (128-bit key)");
|
||||
|
|
|
|||
|
|
@ -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 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 socketft.cpp sosemanuk.cpp speck.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp trdlocal.cpp ttmac.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 skipjack.cpp socketft.cpp sosemanuk.cpp speck.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp trdlocal.cpp ttmac.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 socketft.obj sosemanuk.obj speck.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj trdlocal.obj ttmac.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 skipjack.obj socketft.obj sosemanuk.obj speck.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj trdlocal.obj ttmac.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 datatest.cpp regtest1.cpp regtest2.cpp regtest3.cpp fipsalgt.cpp dlltest.cpp fipstest.cpp
|
||||
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@
|
|||
<None Include="TestVectors\sha2.txt" />
|
||||
<None Include="TestVectors\sha3.txt" />
|
||||
<None Include="TestVectors\shacal2.txt" />
|
||||
<None Include="TestVectors\simon.txt" />
|
||||
<None Include="TestVectors\siphash.txt" />
|
||||
<None Include="TestVectors\sosemanuk.txt" />
|
||||
<None Include="TestVectors\speck.txt" />
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@
|
|||
<None Include="TestVectors\siphash.txt">
|
||||
<Filter>TestVectors</Filter>
|
||||
</None>
|
||||
<None Include="TestVectors\simon.txt">
|
||||
<Filter>TestVectors</Filter>
|
||||
</None>
|
||||
<None Include="TestVectors\sosemanuk.txt">
|
||||
<Filter>TestVectors</Filter>
|
||||
</None>
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@
|
|||
<ClCompile Include="shacal2-simd.cpp" />
|
||||
<ClCompile Include="shark.cpp" />
|
||||
<ClCompile Include="sharkbox.cpp" />
|
||||
<ClCompile Include="simon.cpp" />
|
||||
<ClCompile Include="simple.cpp" />
|
||||
<ClCompile Include="skipjack.cpp" />
|
||||
<ClCompile Include="socketft.cpp" />
|
||||
|
|
@ -470,6 +471,7 @@
|
|||
<ClInclude Include="shacal2.h" />
|
||||
<ClInclude Include="shark.h" />
|
||||
<ClInclude Include="simple.h" />
|
||||
<ClInclude Include="simon.h" />
|
||||
<ClInclude Include="siphash.h" />
|
||||
<ClInclude Include="skipjack.h" />
|
||||
<ClInclude Include="smartptr.h" />
|
||||
|
|
|
|||
|
|
@ -362,6 +362,9 @@
|
|||
<ClCompile Include="simple.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="simon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="skipjack.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -807,6 +810,9 @@
|
|||
<ClInclude Include="simple.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="simon.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="siphash.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
11
regtest2.cpp
11
regtest2.cpp
|
|
@ -32,6 +32,7 @@
|
|||
#include "mars.h"
|
||||
#include "kalyna.h"
|
||||
#include "threefish.h"
|
||||
#include "simon.h"
|
||||
#include "speck.h"
|
||||
#include "des.h"
|
||||
#include "idea.h"
|
||||
|
|
@ -140,6 +141,7 @@ void RegisterFactories2()
|
|||
RegisterSymmetricCipherDefaultFactories<CTR_Mode<Blowfish> >();
|
||||
RegisterSymmetricCipherDefaultFactories<ECB_Mode<SEED> >();
|
||||
RegisterSymmetricCipherDefaultFactories<CTR_Mode<SEED> >();
|
||||
|
||||
RegisterSymmetricCipherDefaultFactories<ECB_Mode<Kalyna> >(); // Test Vectors
|
||||
RegisterSymmetricCipherDefaultFactories<CBC_Mode<Kalyna> >(); // Test Vectors
|
||||
RegisterSymmetricCipherDefaultFactories<CTR_Mode<Kalyna> >(); // Benchmarks
|
||||
|
|
@ -150,16 +152,21 @@ void RegisterFactories2()
|
|||
RegisterSymmetricCipherDefaultFactories<CBC_Mode<Threefish512> >(); // Test Vectors
|
||||
RegisterSymmetricCipherDefaultFactories<ECB_Mode<Threefish1024> >(); // Test Vectors
|
||||
RegisterSymmetricCipherDefaultFactories<CBC_Mode<Threefish1024> >(); // Test Vectors
|
||||
|
||||
RegisterSymmetricCipherDefaultFactories<CTR_Mode<Threefish256> >(); // Benchmarks
|
||||
RegisterSymmetricCipherDefaultFactories<CTR_Mode<Threefish512> >(); // 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
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,365 @@
|
|||
// simon.h - written and placed in the public domain by Jeffrey Walton
|
||||
|
||||
#include "pch.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "simon.h"
|
||||
#include "misc.h"
|
||||
|
||||
ANONYMOUS_NAMESPACE_BEGIN
|
||||
|
||||
using CryptoPP::word32;
|
||||
using CryptoPP::word64;
|
||||
using CryptoPP::rotlFixed;
|
||||
using CryptoPP::rotrFixed;
|
||||
|
||||
//! \brief Round transformation helper
|
||||
//! \tparam W word type
|
||||
//! \param v value
|
||||
template <class W>
|
||||
inline W f(const W v)
|
||||
{
|
||||
return (rotlFixed(v, 1) & rotlFixed(v, 8)) ^ rotlFixed(v, 2);
|
||||
}
|
||||
|
||||
//! \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 (size_t i = 0; static_cast<int>(i) < R-1; i += 2)
|
||||
R2(c[0], c[1], k[i], k[i + 1]);
|
||||
|
||||
// The constexpr residue should allow the optimizer to remove unneeded statements
|
||||
if (R%2 == 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];
|
||||
|
||||
// The constexpr residue should allow the optimizer to remove unneeded statements
|
||||
if (R % 2 == 0)
|
||||
{
|
||||
for (size_t i = R-2; static_cast<int>(i) >= 0; i -= 2)
|
||||
R2(p[1], p[0], k[i+1], k[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const W t = p[1]; p[1] = p[0];
|
||||
p[0] = t; p[1] ^= k[R-1]; p[1] ^= f(p[0]);
|
||||
|
||||
for (size_t i = R-3; static_cast<int>(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 worthwile because all instantiations would need specialization.
|
||||
//! \param key empty subkey array
|
||||
//! \param k user key array
|
||||
inline void SPECK64_ExpandKey_42R3K(word32 key[42], const word32 k[3])
|
||||
{
|
||||
const word32 c = 0xfffffffc;
|
||||
word64 z = 0x7369f885192c0ef5LL;
|
||||
|
||||
key[0] = k[0]; key[1] = k[1]; key[2] = k[2];
|
||||
for (size_t i = 3; i<42; ++i)
|
||||
{
|
||||
key[i] = c ^ (z & 1) ^ key[i-3] ^ rotrFixed(key[i-1], 3) ^ rotrFixed(key[i-1], 4);
|
||||
z >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//! \brief Subkey generation function
|
||||
//! \details Used for SIMON-64 with 128-bit key and 44 rounds. A template was
|
||||
//! not worthwile because all instantiations would need specialization.
|
||||
//! \param key empty subkey array
|
||||
//! \param k user key array
|
||||
inline void SPECK64_ExpandKey_44R4K(word32 key[44], const word32 k[4])
|
||||
{
|
||||
const word32 c = 0xfffffffc;
|
||||
word64 z = W64LIT(0xfc2ce51207a635db);
|
||||
|
||||
key[0] = k[0]; key[1] = k[1]; key[2] = k[2]; key[3] = k[3];
|
||||
for (size_t i = 4; i<44; ++i)
|
||||
{
|
||||
key[i] = c ^ (z & 1) ^ key[i-4] ^ rotrFixed(key[i-1], 3) ^ key[i-3] ^ rotrFixed(key[i-1], 4) ^ rotrFixed(key[i-3], 1);
|
||||
z >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//! \brief Subkey generation function
|
||||
//! \details Used for SIMON-128 with 128-bit key and 68 rounds. A template was
|
||||
//! not worthwile because all instantiations would need specialization.
|
||||
//! \param key empty subkey array
|
||||
//! \param k user key array
|
||||
inline void SIMON128_ExpandKey_68R2K(word64 key[68], const word64 k[2])
|
||||
{
|
||||
const word64 c = W64LIT(0xfffffffffffffffc);
|
||||
word64 z = W64LIT(0x7369f885192c0ef5);
|
||||
|
||||
key[0] = k[0]; key[1] = k[1];
|
||||
for (size_t i=2; i<66; ++i)
|
||||
{
|
||||
key[i] = c^(z&1)^key[i-2]^rotrFixed(key[i-1],3)^rotrFixed(key[i-1],4);
|
||||
z>>=1;
|
||||
}
|
||||
|
||||
key[66] = c^1^key[64]^rotrFixed(key[65],3)^rotrFixed(key[65],4);
|
||||
key[67] = c^key[65]^rotrFixed(key[66],3)^rotrFixed(key[66],4);
|
||||
}
|
||||
|
||||
//! \brief Subkey generation function
|
||||
//! \details Used for SIMON-128 with 192-bit key and 69 rounds. A template was
|
||||
//! not worthwile because all instantiations would need specialization.
|
||||
//! \param key empty subkey array
|
||||
//! \param k user key array
|
||||
inline void SIMON128_ExpandKey_69R3K(word64 key[69], const word64 k[3])
|
||||
{
|
||||
const word64 c = W64LIT(0xfffffffffffffffc);
|
||||
word64 z = W64LIT(0xfc2ce51207a635db);
|
||||
|
||||
key[0]=k[0]; key[1]=k[1]; key[2]=k[2];
|
||||
for (size_t i=3; i<67; ++i)
|
||||
{
|
||||
key[i] = c^(z&1)^key[i-3]^rotrFixed(key[i-1],3)^rotrFixed(key[i-1],4);
|
||||
z>>=1;
|
||||
}
|
||||
|
||||
key[67] = c^key[64]^rotrFixed(key[66],3)^rotrFixed(key[66],4);
|
||||
key[68] = c^1^key[65]^rotrFixed(key[67],3)^rotrFixed(key[67],4);
|
||||
}
|
||||
|
||||
//! \brief Subkey generation function
|
||||
//! \details Used for SIMON-128 with 256-bit key and 72 rounds. A template was
|
||||
//! not worthwile because all instantiations would need specialization.
|
||||
//! \param key empty subkey array
|
||||
//! \param k user key array
|
||||
inline void SIMON128_ExpandKey_72R4K(word64 key[72], const word64 k[4])
|
||||
{
|
||||
const word64 c = W64LIT(0xfffffffffffffffc);
|
||||
word64 z = W64LIT(0xfdc94c3a046d678b);
|
||||
|
||||
key[0]=k[0]; key[1]=k[1]; key[2]=k[2]; key[3]=k[3];
|
||||
for (size_t i=4; i<68; ++i)
|
||||
{
|
||||
key[i] = c^(z&1)^key[i-4]^rotrFixed(key[i-1],3)^key[i-3]^rotrFixed(key[i-1],4)^rotrFixed(key[i-3],1);
|
||||
z>>=1;
|
||||
}
|
||||
|
||||
key[68] = c^key[64]^rotrFixed(key[67],3)^key[65]^rotrFixed(key[67],4)^rotrFixed(key[65],1);
|
||||
key[69] = c^1^key[65]^rotrFixed(key[68],3)^key[66]^rotrFixed(key[68],4)^rotrFixed(key[66],1);
|
||||
key[70] = c^key[66]^rotrFixed(key[69],3)^key[67]^rotrFixed(key[69],4)^rotrFixed(key[67],1);
|
||||
key[71] = c^key[67]^rotrFixed(key[70],3)^key[68]^rotrFixed(key[70],4)^rotrFixed(key[68],1);
|
||||
}
|
||||
|
||||
ANONYMOUS_NAMESPACE_END
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#if 1
|
||||
void SIMON64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)
|
||||
{
|
||||
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(STDMAX(m_kwords,4U));
|
||||
|
||||
// Avoid GetUserKey. SIMON does unusual things with key string and word ordering
|
||||
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
|
||||
typedef GetBlock<word32, BigEndian, false> InBlock;
|
||||
InBlock iblk(userKey);
|
||||
|
||||
switch (m_kwords)
|
||||
{
|
||||
case 3:
|
||||
m_rkey.New(42);
|
||||
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
||||
SPECK64_ExpandKey_42R3K(m_rkey, m_wspace);
|
||||
break;
|
||||
case 4:
|
||||
m_rkey.New(44);
|
||||
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
||||
SPECK64_ExpandKey_44R4K(m_rkey, m_wspace);
|
||||
break;
|
||||
default:
|
||||
CRYPTOPP_ASSERT(0);;
|
||||
}
|
||||
}
|
||||
|
||||
void SIMON64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||
typedef GetBlock<word32, BigEndian, false> InBlock;
|
||||
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
||||
|
||||
switch (m_kwords)
|
||||
{
|
||||
case 3:
|
||||
SIMON_Encrypt<word32, 42>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
case 4:
|
||||
SIMON_Encrypt<word32, 44>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
default:
|
||||
CRYPTOPP_ASSERT(0);;
|
||||
}
|
||||
|
||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||
typedef PutBlock<word32, BigEndian, false> OutBlock;
|
||||
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
||||
}
|
||||
|
||||
void SIMON64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||
typedef GetBlock<word32, BigEndian, false> InBlock;
|
||||
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
||||
|
||||
switch (m_kwords)
|
||||
{
|
||||
case 3:
|
||||
SIMON_Decrypt<word32, 42>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
case 4:
|
||||
SIMON_Decrypt<word32, 44>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
default:
|
||||
CRYPTOPP_ASSERT(0);;
|
||||
}
|
||||
|
||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||
typedef PutBlock<word32, BigEndian, false> OutBlock;
|
||||
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
void SIMON128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)
|
||||
{
|
||||
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(STDMAX(m_kwords,4U));
|
||||
|
||||
// Avoid GetUserKey. SIMON does unusual things with key string and word ordering
|
||||
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
|
||||
typedef GetBlock<word64, BigEndian, false> InBlock;
|
||||
InBlock iblk(userKey);
|
||||
|
||||
switch (m_kwords)
|
||||
{
|
||||
case 2:
|
||||
m_rkey.New(68);
|
||||
iblk(m_wspace[1])(m_wspace[0]);
|
||||
SIMON128_ExpandKey_68R2K(m_rkey, m_wspace);
|
||||
break;
|
||||
case 3:
|
||||
m_rkey.New(69);
|
||||
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
||||
SIMON128_ExpandKey_69R3K(m_rkey, m_wspace);
|
||||
break;
|
||||
case 4:
|
||||
m_rkey.New(72);
|
||||
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
||||
SIMON128_ExpandKey_72R4K(m_rkey, m_wspace);
|
||||
break;
|
||||
default:
|
||||
CRYPTOPP_ASSERT(0);;
|
||||
}
|
||||
}
|
||||
|
||||
void SIMON128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||
typedef GetBlock<word64, BigEndian, false> InBlock;
|
||||
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
||||
|
||||
switch (m_kwords)
|
||||
{
|
||||
case 2:
|
||||
SIMON_Encrypt<word64, 68>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
case 3:
|
||||
SIMON_Encrypt<word64, 69>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
case 4:
|
||||
SIMON_Encrypt<word64, 72>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
default:
|
||||
CRYPTOPP_ASSERT(0);;
|
||||
}
|
||||
|
||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||
typedef PutBlock<word64, BigEndian, false> OutBlock;
|
||||
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
||||
}
|
||||
|
||||
void SIMON128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||
typedef GetBlock<word64, BigEndian, false> InBlock;
|
||||
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
||||
|
||||
switch (m_kwords)
|
||||
{
|
||||
case 2:
|
||||
SIMON_Decrypt<word64, 68>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
case 3:
|
||||
SIMON_Decrypt<word64, 69>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
case 4:
|
||||
SIMON_Decrypt<word64, 72>(m_wspace+2, m_wspace+0, m_rkey);
|
||||
break;
|
||||
default:
|
||||
CRYPTOPP_ASSERT(0);;
|
||||
}
|
||||
|
||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||
typedef PutBlock<word64, BigEndian, false> OutBlock;
|
||||
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
// 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 SIMON Families of
|
||||
//! Lightweight Block Ciphers</A> and <A HREF="http://iadgov.github.io/simon-simon/">
|
||||
//! The Simon and Simon GitHub</A>
|
||||
//! \since Crypto++ 6.0
|
||||
|
||||
#ifndef CRYPTOPP_SIMON_H
|
||||
#define CRYPTOPP_SIMON_H
|
||||
|
||||
#include "config.h"
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! \class SIMON_Info
|
||||
//! \brief SIMON block cipher information
|
||||
//! \tparam BS 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 BS, unsigned int D, unsigned int N, unsigned int M>
|
||||
struct SIMON_Info : public FixedBlockSize<BS>, VariableKeyLength<D, N, M>
|
||||
{
|
||||
static const std::string StaticAlgorithmName()
|
||||
{
|
||||
// Format is Cipher-Blocksize(Keylength)
|
||||
return "SIMON-" + IntToString(BS*8);
|
||||
}
|
||||
};
|
||||
|
||||
//! \class SIMON_Base
|
||||
//! \brief SIMON block cipher base class
|
||||
//! \tparam BS block size of the cipher, in bytes
|
||||
//! \details User code should use SIMON64 or SIMON128
|
||||
//! \sa SIMON64, SIMON128, <a href="http://www.cryptopp.com/wiki/SIMON">SIMON</a>
|
||||
//! \since Crypto++ 6.0
|
||||
template <class W>
|
||||
struct SIMON_Base
|
||||
{
|
||||
virtual ~SIMON_Base() {}
|
||||
|
||||
typedef SecBlock<W, AllocatorWithCleanup<W, true> > AlignedSecBlock;
|
||||
mutable AlignedSecBlock m_wspace; // workspace
|
||||
AlignedSecBlock m_rkey; // round keys
|
||||
unsigned int m_kwords; // number of key words
|
||||
};
|
||||
|
||||
#if 1
|
||||
|
||||
//! \class SIMON64
|
||||
//! \brief SIMON 64-bit block cipher
|
||||
//! \details SIMON64 provides 64-bit block size. The valid key sizes are 98-bit and 128-bit.
|
||||
//! \note Crypto++ provides a byte oriented implementation
|
||||
//! \sa SIMON64, SIMON128, <a href="http://www.cryptopp.com/wiki/SIMON">SIMON</a>
|
||||
//! \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() + "(" + IntToString(m_kwords*sizeof(word32)*8) + ")";
|
||||
}
|
||||
|
||||
protected:
|
||||
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms);
|
||||
};
|
||||
|
||||
//! \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;
|
||||
};
|
||||
|
||||
//! \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;
|
||||
};
|
||||
|
||||
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
|
||||
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
|
||||
};
|
||||
#endif
|
||||
|
||||
//! \class SIMON128
|
||||
//! \brief SIMON 128-bit block cipher
|
||||
//! \details SIMON128 provides 128-bit block size. The valid key sizes are 128-bit, 192-bit and 256-bit.
|
||||
//! \note Crypto++ provides a byte oriented implementation
|
||||
//! \sa SIMON64, SIMON128, <a href="http://www.cryptopp.com/wiki/SIMON">SIMON</a>
|
||||
//! \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() + "(" + IntToString(sizeof(word64)*8) + ")";
|
||||
}
|
||||
|
||||
protected:
|
||||
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms);
|
||||
};
|
||||
|
||||
//! \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;
|
||||
};
|
||||
|
||||
//! \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;
|
||||
};
|
||||
|
||||
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
|
||||
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // CRYPTOPP_SIMON_H
|
||||
|
|
@ -171,6 +171,7 @@ bool ValidateAll(bool thorough)
|
|||
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/seed.txt") && pass;
|
||||
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/threefish.txt") && pass;
|
||||
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/kalyna.txt") && pass;
|
||||
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/simon.txt") && pass;
|
||||
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/speck.txt") && pass;
|
||||
pass=ValidateVMAC() && pass;
|
||||
pass=ValidateCCM() && pass;
|
||||
|
|
|
|||
Loading…
Reference in New Issue