parent
93fb412215
commit
4b3560baef
|
|
@ -14,9 +14,9 @@ Currently the library contains the following algorithms:
|
||||||
AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent,
|
AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent,
|
||||||
CAST-256
|
CAST-256
|
||||||
|
|
||||||
ARIA, IDEA, Triple-DES (DES-EDE2 and DES-EDE3),
|
ARIA, IDEA, Blowfish, Triple-DES (DES-EDE2 and
|
||||||
other block ciphers Camellia, SEED, Kalyna, RC5, Blowfish, TEA, XTEA,
|
other block ciphers DES-EDE3), Camellia, SEED, Kalyna, RC5, SPECK-64,
|
||||||
Threefish, Skipjack, SHACAL-2
|
SPECK-128, Threefish, Skipjack, SHACAL-2, TEA, XTEA
|
||||||
|
|
||||||
block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
|
block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
|
||||||
CFB, OFB, counter mode (CTR)
|
CFB, OFB, counter mode (CTR)
|
||||||
|
|
|
||||||
392
speck.cpp
392
speck.cpp
|
|
@ -18,108 +18,138 @@ using CryptoPP::rotrFixed;
|
||||||
using CryptoPP::rotlVariable;
|
using CryptoPP::rotlVariable;
|
||||||
using CryptoPP::rotrVariable;
|
using CryptoPP::rotrVariable;
|
||||||
|
|
||||||
|
//! \brief Forward round transformation
|
||||||
|
//! \tparam W word type
|
||||||
template <class W>
|
template <class W>
|
||||||
inline void TF83(W& x, W& y, const W& k)
|
inline void TF83(W& x, W& y, const W& k)
|
||||||
{
|
{
|
||||||
x = rotrFixed(x, 8);
|
x = rotrFixed(x, 8);
|
||||||
x += y; x ^= k;
|
x += y; x ^= k;
|
||||||
y = rotlFixed(y, 3);
|
y = rotlFixed(y, 3);
|
||||||
y ^= x;
|
y ^= x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! \brief Reverse round transformation
|
||||||
|
//! \tparam W word type
|
||||||
template <class W>
|
template <class W>
|
||||||
inline void TR83(W& x, W& y, const W& k)
|
inline void TR83(W& x, W& y, const W& k)
|
||||||
{
|
{
|
||||||
y^=x;
|
y^=x;
|
||||||
y=rotrFixed(y,3);
|
y=rotrFixed(y,3);
|
||||||
x^=k;
|
x^=k; x-=y;
|
||||||
x-=y;
|
x=rotlFixed(x,8);
|
||||||
x=rotlFixed(x,8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// W is word type
|
//! \brief Forward transformation
|
||||||
// R is number of rounds
|
//! \tparam W word type
|
||||||
// p = plain text, k = key, c = cipher text
|
//! \tparam R number of rounds
|
||||||
|
//! \param c output array
|
||||||
|
//! \param p input array
|
||||||
|
//! \param k subkey array
|
||||||
template <class W, unsigned int R>
|
template <class W, unsigned int R>
|
||||||
inline void SPECK_Encrypt(W c[2], const W p[2], const W k[R])
|
inline void SPECK_Encrypt(W c[2], const W p[2], const W k[R])
|
||||||
{
|
{
|
||||||
c[0]=p[0]; c[1]=p[1];
|
c[0]=p[0]; c[1]=p[1];
|
||||||
|
|
||||||
// Don't unroll this loop. Things slow down.
|
// Don't unroll this loop. Things slow down.
|
||||||
for(W i=0; static_cast<int>(i)<R; ++i)
|
for(W i=0; static_cast<int>(i)<R; ++i)
|
||||||
TF83(c[0], c[1], k[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>
|
template <class W, unsigned int R>
|
||||||
inline void SPECK_Decrypt(W p[2], const W c[2], const W k[R])
|
inline void SPECK_Decrypt(W p[2], const W c[2], const W k[R])
|
||||||
{
|
{
|
||||||
p[0]=c[0]; p[1]=c[1];
|
p[0]=c[0]; p[1]=c[1];
|
||||||
|
|
||||||
// Don't unroll this loop. Things slow down.
|
// Don't unroll this loop. Things slow down.
|
||||||
for(W i=R-1; static_cast<int>(i)>=0; --i)
|
for(W i=R-1; static_cast<int>(i)>=0; --i)
|
||||||
TR83(p[0], p[1], k[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>
|
template <class W, unsigned int R>
|
||||||
inline void SPECK_RoundKeys_2W(W key[R], const W k[2])
|
inline void SPECK_RoundKeys_2W(W key[R], const W k[2])
|
||||||
{
|
{
|
||||||
CRYPTOPP_ASSERT(R==32);
|
CRYPTOPP_ASSERT(R==32);
|
||||||
W i=0, B=k[1], A=k[0];
|
W i=0, B=k[1], A=k[0];
|
||||||
|
|
||||||
while(i<R-1)
|
while(i<R-1)
|
||||||
{
|
{
|
||||||
key[i]=A; TF83(B, A, i);
|
key[i]=A; TF83(B, A, i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
key[R-1]=A;
|
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>
|
template <class W, unsigned int R>
|
||||||
inline void SPECK_RoundKeys_3W(W key[R], const W k[3])
|
inline void SPECK_RoundKeys_3W(W key[R], const W k[3])
|
||||||
{
|
{
|
||||||
CRYPTOPP_ASSERT(R==33 || R==26);
|
CRYPTOPP_ASSERT(R==33 || R==26);
|
||||||
W i=0, C=k[2], B=k[1], A=k[0];
|
W i=0, C=k[2], B=k[1], A=k[0];
|
||||||
|
|
||||||
unsigned int blocks = R/2;
|
unsigned int blocks = R/2;
|
||||||
while(blocks--)
|
while(blocks--)
|
||||||
{
|
{
|
||||||
key[i+0]=A; TF83(B, A, i+0);
|
key[i+0]=A; TF83(B, A, i+0);
|
||||||
key[i+1]=A; TF83(C, A, i+1);
|
key[i+1]=A; TF83(C, A, i+1);
|
||||||
i+=2;
|
i+=2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The constexpr residue should allow the optimizer to remove unneeded statements
|
// The constexpr residue should allow the optimizer to remove unneeded statements
|
||||||
if(R%2 == 1)
|
if(R%2 == 1)
|
||||||
{
|
{
|
||||||
key[R-1]=A;
|
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>
|
template <class W, unsigned int R>
|
||||||
inline void SPECK_RoundKeys_4W(W key[R], const W k[4])
|
inline void SPECK_RoundKeys_4W(W key[R], const W k[4])
|
||||||
{
|
{
|
||||||
CRYPTOPP_ASSERT(R==34 || R==27);
|
CRYPTOPP_ASSERT(R==34 || R==27);
|
||||||
W i=0, D=k[3], C=k[2], B=k[1], A=k[0];
|
W i=0, D=k[3], C=k[2], B=k[1], A=k[0];
|
||||||
|
|
||||||
unsigned int blocks = R/3;
|
unsigned int blocks = R/3;
|
||||||
while(blocks--)
|
while(blocks--)
|
||||||
{
|
{
|
||||||
key[i+0]=A; TF83(B, A, i+0);
|
key[i+0]=A; TF83(B, A, i+0);
|
||||||
key[i+1]=A; TF83(C, A, i+1);
|
key[i+1]=A; TF83(C, A, i+1);
|
||||||
key[i+2]=A; TF83(D, A, i+2);
|
key[i+2]=A; TF83(D, A, i+2);
|
||||||
i+=3;
|
i+=3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The constexpr residue should allow the optimizer to remove unneeded statements
|
// The constexpr residue should allow the optimizer to remove unneeded statements
|
||||||
if(R%3 == 1)
|
if(R%3 == 1)
|
||||||
{
|
{
|
||||||
key[R-1]=A;
|
key[R-1]=A;
|
||||||
}
|
}
|
||||||
else if(R%3 == 2)
|
else if(R%3 == 2)
|
||||||
{
|
{
|
||||||
key[R-2]=A; TF83(B, A, W(R-2));
|
key[R-2]=A; TF83(B, A, W(R-2));
|
||||||
key[R-1]=A;
|
key[R-1]=A;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ANONYMOUS_NAMESPACE_END
|
ANONYMOUS_NAMESPACE_END
|
||||||
|
|
@ -128,169 +158,169 @@ NAMESPACE_BEGIN(CryptoPP)
|
||||||
|
|
||||||
void SPECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)
|
void SPECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)
|
||||||
{
|
{
|
||||||
CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16);
|
CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16);
|
||||||
|
|
||||||
// Building the key schedule table requires {3,4} words workspace.
|
// Building the key schedule table requires {3,4} words workspace.
|
||||||
// Encrypting and decrypting requires 4 words workspace.
|
// Encrypting and decrypting requires 4 words workspace.
|
||||||
m_kwords = keyLength/sizeof(word32);
|
m_kwords = keyLength/sizeof(word32);
|
||||||
m_wspace.New(STDMAX(m_kwords,4U));
|
m_wspace.New(STDMAX(m_kwords,4U));
|
||||||
|
|
||||||
// Avoid GetUserKey. SPECK does unusual things with key string and word ordering
|
// Avoid GetUserKey. SPECK does unusual things with key string and word ordering
|
||||||
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
|
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
|
||||||
typedef GetBlock<word32, BigEndian, false> InBlock;
|
typedef GetBlock<word32, BigEndian, false> InBlock;
|
||||||
InBlock iblk(userKey);
|
InBlock iblk(userKey);
|
||||||
|
|
||||||
switch (m_kwords)
|
switch (m_kwords)
|
||||||
{
|
{
|
||||||
case 3:
|
case 3:
|
||||||
m_rkey.New(26);
|
m_rkey.New(26);
|
||||||
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
||||||
SPECK_RoundKeys_3W<word32, 26>(m_rkey, m_wspace);
|
SPECK_RoundKeys_3W<word32, 26>(m_rkey, m_wspace);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
m_rkey.New(27);
|
m_rkey.New(27);
|
||||||
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
||||||
SPECK_RoundKeys_4W<word32, 27>(m_rkey, m_wspace);
|
SPECK_RoundKeys_4W<word32, 27>(m_rkey, m_wspace);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CRYPTOPP_ASSERT(0);;
|
CRYPTOPP_ASSERT(0);;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
void SPECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||||
{
|
{
|
||||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||||
typedef GetBlock<word32, BigEndian, false> InBlock;
|
typedef GetBlock<word32, BigEndian, false> InBlock;
|
||||||
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
||||||
|
|
||||||
switch (m_kwords)
|
switch (m_kwords)
|
||||||
{
|
{
|
||||||
case 3:
|
case 3:
|
||||||
SPECK_Encrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Encrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
SPECK_Encrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Encrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CRYPTOPP_ASSERT(0);;
|
CRYPTOPP_ASSERT(0);;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||||
typedef PutBlock<word32, BigEndian, false> OutBlock;
|
typedef PutBlock<word32, BigEndian, false> OutBlock;
|
||||||
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
void SPECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||||
{
|
{
|
||||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||||
typedef GetBlock<word32, BigEndian, false> InBlock;
|
typedef GetBlock<word32, BigEndian, false> InBlock;
|
||||||
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
||||||
|
|
||||||
switch (m_kwords)
|
switch (m_kwords)
|
||||||
{
|
{
|
||||||
case 3:
|
case 3:
|
||||||
SPECK_Decrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Decrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
SPECK_Decrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Decrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CRYPTOPP_ASSERT(0);;
|
CRYPTOPP_ASSERT(0);;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||||
typedef PutBlock<word32, BigEndian, false> OutBlock;
|
typedef PutBlock<word32, BigEndian, false> OutBlock;
|
||||||
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void SPECK128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)
|
void SPECK128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)
|
||||||
{
|
{
|
||||||
CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32);
|
CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32);
|
||||||
|
|
||||||
// Building the key schedule table requires {2,3,4} words workspace.
|
// Building the key schedule table requires {2,3,4} words workspace.
|
||||||
// Encrypting and decrypting requires 4 words workspace.
|
// Encrypting and decrypting requires 4 words workspace.
|
||||||
m_kwords = keyLength/sizeof(word64);
|
m_kwords = keyLength/sizeof(word64);
|
||||||
m_wspace.New(STDMAX(m_kwords,4U));
|
m_wspace.New(STDMAX(m_kwords,4U));
|
||||||
|
|
||||||
// Avoid GetUserKey. SPECK does unusual things with key string and word ordering
|
// Avoid GetUserKey. SPECK does unusual things with key string and word ordering
|
||||||
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
|
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
|
||||||
typedef GetBlock<word64, BigEndian, false> InBlock;
|
typedef GetBlock<word64, BigEndian, false> InBlock;
|
||||||
InBlock iblk(userKey);
|
InBlock iblk(userKey);
|
||||||
|
|
||||||
switch (m_kwords)
|
switch (m_kwords)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
m_rkey.New(32);
|
m_rkey.New(32);
|
||||||
iblk(m_wspace[1])(m_wspace[0]);
|
iblk(m_wspace[1])(m_wspace[0]);
|
||||||
SPECK_RoundKeys_2W<word64, 32>(m_rkey, m_wspace);
|
SPECK_RoundKeys_2W<word64, 32>(m_rkey, m_wspace);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
m_rkey.New(33);
|
m_rkey.New(33);
|
||||||
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
||||||
SPECK_RoundKeys_3W<word64, 33>(m_rkey, m_wspace);
|
SPECK_RoundKeys_3W<word64, 33>(m_rkey, m_wspace);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
m_rkey.New(34);
|
m_rkey.New(34);
|
||||||
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
|
||||||
SPECK_RoundKeys_4W<word64, 34>(m_rkey, m_wspace);
|
SPECK_RoundKeys_4W<word64, 34>(m_rkey, m_wspace);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CRYPTOPP_ASSERT(0);;
|
CRYPTOPP_ASSERT(0);;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPECK128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
void SPECK128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||||
{
|
{
|
||||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||||
typedef GetBlock<word64, BigEndian, false> InBlock;
|
typedef GetBlock<word64, BigEndian, false> InBlock;
|
||||||
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
||||||
|
|
||||||
switch (m_kwords)
|
switch (m_kwords)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
SPECK_Encrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Encrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
SPECK_Encrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Encrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
SPECK_Encrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Encrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CRYPTOPP_ASSERT(0);;
|
CRYPTOPP_ASSERT(0);;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||||
typedef PutBlock<word64, BigEndian, false> OutBlock;
|
typedef PutBlock<word64, BigEndian, false> OutBlock;
|
||||||
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPECK128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
void SPECK128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||||
{
|
{
|
||||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||||
typedef GetBlock<word64, BigEndian, false> InBlock;
|
typedef GetBlock<word64, BigEndian, false> InBlock;
|
||||||
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
|
||||||
|
|
||||||
switch (m_kwords)
|
switch (m_kwords)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
SPECK_Decrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Decrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
SPECK_Decrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Decrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
SPECK_Decrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkey);
|
SPECK_Decrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkey);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CRYPTOPP_ASSERT(0);;
|
CRYPTOPP_ASSERT(0);;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
// Reverse bytes on LittleEndian; align pointer on BigEndian
|
||||||
typedef PutBlock<word64, BigEndian, false> OutBlock;
|
typedef PutBlock<word64, BigEndian, false> OutBlock;
|
||||||
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
NAMESPACE_END
|
NAMESPACE_END
|
||||||
|
|
|
||||||
87
speck.h
87
speck.h
|
|
@ -21,6 +21,9 @@ NAMESPACE_BEGIN(CryptoPP)
|
||||||
//! \class SPECK_Info
|
//! \class SPECK_Info
|
||||||
//! \brief SPECK block cipher information
|
//! \brief SPECK block cipher information
|
||||||
//! \tparam BS block size of the cipher, in bytes
|
//! \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
|
//! \since Crypto++ 6.0
|
||||||
template <unsigned int BS, unsigned int D, unsigned int N, unsigned int M>
|
template <unsigned int BS, unsigned int D, unsigned int N, unsigned int M>
|
||||||
struct SPECK_Info : public FixedBlockSize<BS>, VariableKeyLength<D, N, M>
|
struct SPECK_Info : public FixedBlockSize<BS>, VariableKeyLength<D, N, M>
|
||||||
|
|
@ -35,23 +38,25 @@ struct SPECK_Info : public FixedBlockSize<BS>, VariableKeyLength<D, N, M>
|
||||||
//! \class SPECK_Base
|
//! \class SPECK_Base
|
||||||
//! \brief SPECK block cipher base class
|
//! \brief SPECK block cipher base class
|
||||||
//! \tparam BS block size of the cipher, in bytes
|
//! \tparam BS block size of the cipher, in bytes
|
||||||
//! \details User code should use SPECK128, SPECK512, SPECK1024
|
//! \details User code should use SPECK64 or SPECK128
|
||||||
//! \sa SPECK32, SPECK48, SPECK64, SPECK96, SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
|
//! \sa SPECK64, SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
|
||||||
//! \since Crypto++ 6.0
|
//! \since Crypto++ 6.0
|
||||||
template <class W>
|
template <class W>
|
||||||
struct SPECK_Base
|
struct SPECK_Base
|
||||||
{
|
{
|
||||||
|
virtual ~SPECK_Base() {}
|
||||||
|
|
||||||
typedef SecBlock<W, AllocatorWithCleanup<W, true> > AlignedSecBlock;
|
typedef SecBlock<W, AllocatorWithCleanup<W, true> > AlignedSecBlock;
|
||||||
mutable AlignedSecBlock m_wspace; // workspace
|
mutable AlignedSecBlock m_wspace; // workspace
|
||||||
AlignedSecBlock m_rkey; // round keys
|
AlignedSecBlock m_rkey; // round keys
|
||||||
unsigned int m_kwords; // number of key words
|
unsigned int m_kwords; // number of key words
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \class SPECK64
|
//! \class SPECK64
|
||||||
//! \brief SPECK 64-bit block cipher
|
//! \brief SPECK 64-bit block cipher
|
||||||
//! \details SPECK64 provides 64-bit block size. The valid key sizes are 98-bit and 128-bit.
|
//! \details SPECK64 provides 64-bit block size. The valid key sizes are 98-bit and 128-bit.
|
||||||
//! \note Crypto++ provides a byte oriented implementation
|
//! \note Crypto++ provides a byte oriented implementation
|
||||||
//! \sa SPECK32, SPECK64, and SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
|
//! \sa SPECK64, SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
|
||||||
//! \since Crypto++ 6.0
|
//! \since Crypto++ 6.0
|
||||||
class CRYPTOPP_NO_VTABLE SPECK64 : public SPECK_Info<8, 12, 12, 16>, public BlockCipherDocumentation
|
class CRYPTOPP_NO_VTABLE SPECK64 : public SPECK_Info<8, 12, 12, 16>, public BlockCipherDocumentation
|
||||||
{
|
{
|
||||||
|
|
@ -61,26 +66,34 @@ public:
|
||||||
//! \since Crypto++ 6.0
|
//! \since Crypto++ 6.0
|
||||||
class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base<word32>, public BlockCipherImpl<SPECK_Info<8, 12, 12, 16> >
|
class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base<word32>, public BlockCipherImpl<SPECK_Info<8, 12, 12, 16> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string AlgorithmName() const {
|
std::string AlgorithmName() const {
|
||||||
return StaticAlgorithmName() + "(" + IntToString(m_kwords*sizeof(word32)*8) + ")";
|
return StaticAlgorithmName() + "(" + IntToString(m_kwords*sizeof(word32)*8) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms);
|
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CRYPTOPP_NO_VTABLE Enc : public Base
|
//! \brief Provides implementation for encryption transformation
|
||||||
{
|
//! \details Enc provides implementation for encryption transformation. All key
|
||||||
protected:
|
//! sizes are supported.
|
||||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
//! \since Crypto++ 6.0
|
||||||
};
|
class CRYPTOPP_NO_VTABLE Enc : public Base
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||||
|
};
|
||||||
|
|
||||||
class CRYPTOPP_NO_VTABLE Dec : public Base
|
//! \brief Provides implementation for encryption transformation
|
||||||
{
|
//! \details Dec provides implementation for decryption transformation. All key
|
||||||
protected:
|
//! sizes are supported.
|
||||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
//! \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<ENCRYPTION, Enc> Encryption;
|
||||||
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
|
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
|
||||||
|
|
@ -90,7 +103,7 @@ public:
|
||||||
//! \brief SPECK 128-bit block cipher
|
//! \brief SPECK 128-bit block cipher
|
||||||
//! \details SPECK128 provides 128-bit block size. The valid key sizes are 128-bit, 192-bit and 256-bit.
|
//! \details SPECK128 provides 128-bit block size. The valid key sizes are 128-bit, 192-bit and 256-bit.
|
||||||
//! \note Crypto++ provides a byte oriented implementation
|
//! \note Crypto++ provides a byte oriented implementation
|
||||||
//! \sa SPECK32, SPECK64, and SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
|
//! \sa SPECK64, SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
|
||||||
//! \since Crypto++ 6.0
|
//! \since Crypto++ 6.0
|
||||||
class CRYPTOPP_NO_VTABLE SPECK128 : public SPECK_Info<16, 16, 16, 32>, public BlockCipherDocumentation
|
class CRYPTOPP_NO_VTABLE SPECK128 : public SPECK_Info<16, 16, 16, 32>, public BlockCipherDocumentation
|
||||||
{
|
{
|
||||||
|
|
@ -100,26 +113,34 @@ public:
|
||||||
//! \since Crypto++ 6.0
|
//! \since Crypto++ 6.0
|
||||||
class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base<word64>, public BlockCipherImpl<SPECK_Info<16, 16, 16, 32> >
|
class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base<word64>, public BlockCipherImpl<SPECK_Info<16, 16, 16, 32> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string AlgorithmName() const {
|
std::string AlgorithmName() const {
|
||||||
return StaticAlgorithmName() + "(" + IntToString(sizeof(word64)*8) + ")";
|
return StaticAlgorithmName() + "(" + IntToString(sizeof(word64)*8) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms);
|
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CRYPTOPP_NO_VTABLE Enc : public Base
|
//! \brief Provides implementation for encryption transformation
|
||||||
{
|
//! \details Enc provides implementation for encryption transformation. All key
|
||||||
protected:
|
//! sizes are supported.
|
||||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
//! \since Crypto++ 6.0
|
||||||
};
|
class CRYPTOPP_NO_VTABLE Enc : public Base
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||||
|
};
|
||||||
|
|
||||||
class CRYPTOPP_NO_VTABLE Dec : public Base
|
//! \brief Provides implementation for encryption transformation
|
||||||
{
|
//! \details Dec provides implementation for decryption transformation. All key
|
||||||
protected:
|
//! sizes are supported.
|
||||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
//! \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<ENCRYPTION, Enc> Encryption;
|
||||||
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
|
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue