Add CHAM lightweight block cipher (PR #670)

Add CHAM lightweight block cipher
This commit is contained in:
Jeffrey Walton 2018-06-17 23:24:47 -04:00 committed by GitHub
parent 30b2de26f4
commit 54d5100344
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 702 additions and 2 deletions

View File

@ -49,6 +49,8 @@ ccm.cpp
ccm.h
chacha.cpp
chacha.h
cham.cpp
cham.h
channels.cpp
channels.h
cmac.cpp
@ -436,6 +438,7 @@ TestVectors/blake2b.txt
TestVectors/blake2s.txt
TestVectors/aria.txt
TestVectors/camellia.txt
TestVectors/cham.txt
TestVectors/ccm.txt
TestVectors/chacha.txt
TestVectors/cmac.txt

View File

@ -33,6 +33,7 @@ Test: TestVectors/sm4.txt
Test: TestVectors/lea.txt
Test: TestVectors/simon.txt
Test: TestVectors/speck.txt
Test: TestVectors/cham.txt
Test: TestVectors/salsa.txt
Test: TestVectors/chacha.txt
#Test: TestVectors/tls_chacha.txt

215
TestVectors/cham.txt Normal file
View File

@ -0,0 +1,215 @@
AlgorithmType: SymmetricCipher
Name: CHAM-64/ECB
#
Source: CHAM paper, Appendix A, test vector 1
Comment: CHAM-64/ECB, 128-bit key
Key: 0100 0302 0504 0706 0908 0b0a 0d0c 0f0e
Plaintext: 1100 3322 5544 7766
Ciphertext: 453c 63bc dcfa bf4e
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-64/ECB, 128-bit key
Key: 0277 0a9e a270 1fed 460c c269 9163 e519
Plaintext: 704a 4e91 eb9b 688d
Ciphertext: ceda d4dc 00e3 800d
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-64/ECB, 128-bit key
Key: 24cd a3e2 c167 92f3 40b6 0017 cabc 07c4
Plaintext: 115a 31e5 ee65 87f7
Ciphertext: e1af b96f 3079 4233
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-64/ECB, 128-bit key
Key: 0914 eef6 827c 21b9 c697 05ce b28b 7dd5
Plaintext: e722 2e2b 0f2c ee49
Ciphertext: 280d 763b 931b da81
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-64/ECB, 128-bit key
Key: 2fa2 fb02 1cd5 9124 ee27 1ec9 7307 6a13
Plaintext: 9fc0 8c64 f9f9 8163
Ciphertext: 0277 8604 1b15 8cb9
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-64/ECB, 128-bit key
Key: 6035 af8d 6d97 6a47 1bc9 cb88 1a4a f2aa
Plaintext: 657b 5980 aad8 468b
Ciphertext: 5684 2bf7 606d 67f8
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-64/ECB, 128-bit key
Key: be3a cf23 eda6 9014 023e 098b 37c3 9b9e
Plaintext: ff83 911e 2f35 84a5
Ciphertext: 9263 2bf9 9819 783a
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-64/ECB, 128-bit key
Key: ffde 8a15 21c5 fb5e b6b1 1ec9 05aa c629
Plaintext: 7802 c7a5 d52f 1868
Ciphertext: f810 fad0 80f0 19bd
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-64/ECB, 128-bit key
Key: fc25 b83f 5058 9cb6 fe7a 5d6c 1635 5cfd
Plaintext: 1ab2 1791 a5d3 05aa
Ciphertext: e733 fd94 c357 d36c
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-64/ECB, 128-bit key
Key: fae3 5e23 e357 3e33 4468 c725 80e5 4a6e
Plaintext: 5dc5 c55f 6b8d 31e2
Ciphertext: 5bc2 2475 f93f 6cc8
Test: Encrypt
AlgorithmType: SymmetricCipher
Name: CHAM-128/ECB
#
Source: CHAM paper, Appendix A, test vector 2
Comment: CHAM-128/ECB, 128-bit key
Key: 03020100 07060504 0b0a0908 0f0e0d0c
Plaintext: 33221100 77665544 bbaa9988 ffeeddcc
Ciphertext: c3746034 b55700c5 8d64ec32 489332f7
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 128-bit key
Key: a37beb01 15c49898 906f6f1c 73f68cf3
Plaintext: 463e4b34 efe3faa8 d8b74450 967f34d1
Ciphertext: 30269e99 4d70c5de 7b0bc631 a96a1458
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 128-bit key
Key: ad97ae34 49a65961 46872c23 08a85a00
Plaintext: 7c241f66 85111245 83d76a6f 8498946b
Ciphertext: 633b6cb9 00b390d8 d1bb84cb d84b9ccf
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 128-bit key
Key: 012ddb51 d216a550 3b1632f3 69930aac
Plaintext: 440a7ce0 23b8499f 991482fd e6069cbe
Ciphertext: b2b21944 81c5becf 091d3c08 ee6d1749
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 128-bit key
Key: dfd8192b cab7764c 12632c23 95c96b55
Plaintext: a72c2040 1e652249 6ceb83be d90a2816
Ciphertext: 0416aae7 302a5219 cd20a3b8 6d879c22
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 128-bit key
Key: c3fe465e dff5a38c 308bcf68 a6d45ba7
Plaintext: 91167a4b b9641eb2 15195841 f3301521
Ciphertext: 36d1dd06 e42c583d 9aea8e58 08ee2f3b
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 128-bit key
Key: e7365921 729a2e4b 5e9e2d42 6b53c079
Plaintext: 9fd5fb98 d2de3459 42cf3edb 2104e849
Ciphertext: 60f3dd59 406e579e e45a2191 526c5693
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 128-bit key
Key: b880a315 e410aa2d 9d8686e4 ac033a6e
Plaintext: 05251c25 354ded83 67d50c4c 4a73b66f
Ciphertext: e3f879f5 8b41baf8 8b458da7 04343a03
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 128-bit key
Key: f0cb7d27 58d7ac44 937b882d 526fb9f8
Plaintext: 088ede84 315ef415 2e2e22b1 8b45e765
Ciphertext: 4ff2532c 66a12b2e 869f476e aab2d53f
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 128-bit key
Key: 28b841b2 9a5e552c e02170c8 fee72a87
Plaintext: 0fc61c4c fa1db413 9d007659 39df2ba9
Ciphertext: 6fd504e7 091aca2e 32c88718 3e40b4a4
Test: Encrypt
#
Source: CHAM paper, Appendix A, test vector 3
Comment: CHAM-128/ECB, 256-bit key
Key: 03020100 07060504 0b0a0908 0f0e0d0c f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc
Plaintext: 33221100 77665544 bbaa9988 ffeeddcc
Ciphertext: a899c8a0 c929d55c ab670d38 0c4f7ac8
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 256-bit key
Key: 4031c291 53a38799 8e0a6bad 6098a6c4 e4a852f8 7daf676e 873c3524 e1527db8
Plaintext: aac76bc0 ec99e00e 9648a939 1a37c8db
Ciphertext: c993c682 1545b60c 456af36c b97628e7
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 256-bit key
Key: 0c7be271 0ee365ff 061b8e43 5dbc63e3 52a08866 634223c9 8f4bcc4f a1223aee
Plaintext: 49eec4dd eb938769 a359a6bf f69353a9
Ciphertext: 6252cf6f 6524f0ed 0b3a272a 33827bb4
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 256-bit key
Key: 90c69c18 8fcac90f 7c061078 036f3279 5676641c 40358d9f d74867ca 5debd8fa
Plaintext: c27e5d18 985bd57e 25b7164e 5acb6ceb
Ciphertext: c7c15e12 2287fd3d 45875c14 629a042c
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 256-bit key
Key: f7bae93e 170bbccd 42a1d993 a6247a9c ae609194 075045fc 95b22ad9 59e16c9c
Plaintext: 87cc88e7 9f159afe b2e8967b ff1ddd8b
Ciphertext: 0887e541 4b68e67f a46d19ff 948290b6
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 256-bit key
Key: 15747f3e 359c8462 151d0e6d f06abade 06f246e1 c817332b 1fa9102a 52263db4
Plaintext: 5c11eab6 3fa257df 7da90d0e 1bf46991
Ciphertext: 3cabb22e 79c7ad8e d502abf8 74e7d3bf
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 256-bit key
Key: 4c70d578 34042fbd 8f4b7c40 89ac864e 1dee8bac 4093f375 308aa073 655098f1
Plaintext: 68c7097e ab6c6043 87d2bc67 41dece87
Ciphertext: 362a9742 dd8238a8 d916409a 4a3c11a1
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 256-bit key
Key: 073359a0 5e54c5f8 882ef21f 01be08d5 7d5c5b87 533059a5 204e2bcd 5652dfc5
Plaintext: ef94e8fb 7bf2aa7c ac73ef0a 294ad1f8
Ciphertext: 5914594d db44ba25 ac0bfc05 1b92a9fe
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 256-bit key
Key: dc359e46 f5516d84 89885aee 191494fe 25350de0 69275496 1531e563 59f9e0ee
Plaintext: d1c5fbd0 7d1e85fc 7922d741 6a5a44dc
Ciphertext: bbe95a67 06b38ff2 898dfda8 41fe29c7
Test: Encrypt
#
Source: CHAM reference implementation
Comment: CHAM-128/ECB, 256-bit key
Key: faf3682d cf6e656c 53bd8c06 de0f7f71 678c5a2d 34624762 d88daf37 21d5ad6c
Plaintext: 55b32441 7a787fbc 41b91ab2 9a5bf734
Ciphertext: 2a7dab0b 6769e989 61578998 7e4be9a7
Test: Encrypt

View File

@ -592,7 +592,7 @@ void Benchmark2(double t, double hertz)
BenchMarkByName<SymmetricCipher>("Threefish-1024(1024)/CTR", 128);
BenchMarkByName<SymmetricCipher>("Serpent/CTR");
BenchMarkByName<SymmetricCipher>("CAST-128/CTR");
BenchMarkByName<SymmetricCipher>("CAST-256/CTR");
BenchMarkByName<SymmetricCipher>("CAST-256/CTR", 32);
BenchMarkByName<SymmetricCipher>("RC6/CTR");
BenchMarkByName<SymmetricCipher>("MARS/CTR");
BenchMarkByName<SymmetricCipher>("SHACAL-2/CTR", 16);
@ -614,6 +614,13 @@ void Benchmark2(double t, double hertz)
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-512/CTR", 64, "Kalyna-512(512)/CTR (512-bit key)");
}
std::cout << "\n<TBODY style=\"background: yellow;\">";
{
BenchMarkByName<SymmetricCipher>("CHAM-64/CTR", 16, "CHAM-64(128)/CTR (128-bit key)");
BenchMarkByName<SymmetricCipher>("CHAM-128/CTR", 16, "CHAM-128(128)/CTR (128-bit key)");
BenchMarkByName<SymmetricCipher>("CHAM-128/CTR", 32, "CHAM-128(256)/CTR (256-bit key)");
BenchMarkByName<SymmetricCipher>("LEA-128/CTR", 16, "LEA-128(128)/CTR (128-bit key)");
BenchMarkByName<SymmetricCipher>("LEA-128/CTR", 24, "LEA-128(192)/CTR (192-bit key)");
@ -632,7 +639,7 @@ void Benchmark2(double t, double hertz)
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: white;\">";
{
#if CRYPTOPP_AESNI_AVAILABLE
if (HasCLMUL())

302
cham.cpp Normal file
View File

@ -0,0 +1,302 @@
// cham.cpp - written and placed in the public domain by Kim Sung Hee and Jeffrey Walton
// Based on "CHAM: A Family of Lightweight Block Ciphers for
// Resource-Constrained Devices" by Bonwook Koo, Dongyoung Roh,
// Hyeonjin Kim, Younghoon Jung, Dong-Geon Lee, and Daesung Kwon
#include "pch.h"
#include "config.h"
#include "cham.h"
#include "misc.h"
// CHAM table of parameters
// +-------------------------------------------------
// +cipher n k r w k/w
// +-------------------------------------------------
// +CHAM-64/128 64 128 80 16 8
// +CHAM-128/128 128 128 80 32 4
// +CHAM-128/256 128 256 96 32 8
// +-------------------------------------------------
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::rotlConstant;
using CryptoPP::rotrConstant;
/// \brief CHAM encryption round
/// \tparam RR the round number residue
/// \tparam KW the number of key words
/// \tparam T words type
/// \param x the state array
/// \param k the subkey table
/// \param i the round number
/// \details CHAM_EncRound applies the encryption round to the plain text.
/// RR is the "round residue" and it is used modulo 4. ProcessAndXorBlock
/// may provide a fully unrolled encryption transformation, or provide
/// a transformation that loops using multiples of 4 encryption rounds.
/// \details CHAM_EncRound calculates indexes into the x[] array based
/// on the round number residue. There is no need for the assignments
/// that shift values in preparations for the next round.
/// \details CHAM_EncRound depends on the round number. The actual round
/// being executed is passed through the parameter <tt>i</tt>. If
/// ProcessAndXorBlock fully unrolled the loop then the parameter
/// <tt>i</tt> would be unnecessary.
template <unsigned int RR, unsigned int KW, class T>
inline void CHAM_EncRound(T x[4], const T k[KW], unsigned int i)
{
CRYPTOPP_CONSTANT(IDX0 = (RR+0) % 4)
CRYPTOPP_CONSTANT(IDX1 = (RR+1) % 4)
CRYPTOPP_CONSTANT(IDX3 = (RR+3+1) % 4)
CRYPTOPP_CONSTANT(R1 = (RR % 2 == 0) ? 1 : 8)
CRYPTOPP_CONSTANT(R2 = (RR % 2 == 0) ? 8 : 1)
// Follows conventions in the ref impl
const T kk = k[i % KW];
const T aa = x[IDX0] ^ static_cast<T>(i);
const T bb = rotlConstant<R1>(x[IDX1]) ^ kk;
x[IDX3] = rotlConstant<R2>(static_cast<T>(aa + bb));
}
/// \brief CHAM decryption round
/// \tparam RR the round number residue
/// \tparam KW the number of key words
/// \tparam T words type
/// \param x the state array
/// \param k the subkey table
/// \param i the round number
/// \details CHAM_DecRound applies the decryption round to the cipher text.
/// RR is the "round residue" and it is used modulo 4. ProcessAndXorBlock
/// may provide a fully unrolled decryption transformation, or provide
/// a transformation that loops using multiples of 4 decryption rounds.
/// \details CHAM_DecRound calculates indexes into the x[] array based
/// on the round number residue. There is no need for the assignments
/// that shift values in preparations for the next round.
/// \details CHAM_DecRound depends on the round number. The actual round
/// being executed is passed through the parameter <tt>i</tt>. If
/// ProcessAndXorBlock fully unrolled the loop then the parameter
/// <tt>i</tt> would be unnecessary.
template <unsigned int RR, unsigned int KW, class T>
inline void CHAM_DecRound(T x[4], const T k[KW], unsigned int i)
{
CRYPTOPP_CONSTANT(IDX0 = (RR+0) % 4)
CRYPTOPP_CONSTANT(IDX1 = (RR+1) % 4)
CRYPTOPP_CONSTANT(IDX3 = (RR+3+1) % 4)
CRYPTOPP_CONSTANT(R1 = (RR % 2 == 0) ? 8 : 1)
CRYPTOPP_CONSTANT(R2 = (RR % 2 == 0) ? 1 : 8)
// Follows conventions in the ref impl
const T kk = k[i % KW];
const T aa = rotrConstant<R1>(x[IDX3]);
const T bb = rotlConstant<R2>(x[IDX1]) ^ kk;
x[IDX0] = static_cast<T>(aa - bb) ^ static_cast<T>(i);
}
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
void CHAM64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
CRYPTOPP_UNUSED(params);
m_kw = keyLength/sizeof(word16);
m_rk.New(2*m_kw);
for (size_t i = 0; i < m_kw; ++i, userKey += sizeof(word16))
{
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
const word16 rk = GetWord<word16>(false, BIG_ENDIAN_ORDER, userKey);
m_rk[i] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<8>(rk);
m_rk[(i + m_kw) ^ 1] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<11>(rk);
}
}
void CHAM64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
GetBlock<word16, BigEndian> iblock(inBlock);
iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
const unsigned int R = 80;
for (int i = 0; i < R; i+=16)
{
CHAM_EncRound< 0, 16>(m_x.begin(), m_rk.begin(), i+0);
CHAM_EncRound< 1, 16>(m_x.begin(), m_rk.begin(), i+1);
CHAM_EncRound< 2, 16>(m_x.begin(), m_rk.begin(), i+2);
CHAM_EncRound< 3, 16>(m_x.begin(), m_rk.begin(), i+3);
CHAM_EncRound< 4, 16>(m_x.begin(), m_rk.begin(), i+4);
CHAM_EncRound< 5, 16>(m_x.begin(), m_rk.begin(), i+5);
CHAM_EncRound< 6, 16>(m_x.begin(), m_rk.begin(), i+6);
CHAM_EncRound< 7, 16>(m_x.begin(), m_rk.begin(), i+7);
CHAM_EncRound< 8, 16>(m_x.begin(), m_rk.begin(), i+8);
CHAM_EncRound< 9, 16>(m_x.begin(), m_rk.begin(), i+9);
CHAM_EncRound<10, 16>(m_x.begin(), m_rk.begin(), i+10);
CHAM_EncRound<11, 16>(m_x.begin(), m_rk.begin(), i+11);
CHAM_EncRound<12, 16>(m_x.begin(), m_rk.begin(), i+12);
CHAM_EncRound<13, 16>(m_x.begin(), m_rk.begin(), i+13);
CHAM_EncRound<14, 16>(m_x.begin(), m_rk.begin(), i+14);
CHAM_EncRound<15, 16>(m_x.begin(), m_rk.begin(), i+15);
}
PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
}
void CHAM64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
GetBlock<word16, BigEndian> iblock(inBlock);
iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
const unsigned int R = 80;
for (int i = R-1; i >=0 ; i-=16)
{
CHAM_DecRound<15, 16>(m_x.begin(), m_rk.begin(), i-0);
CHAM_DecRound<14, 16>(m_x.begin(), m_rk.begin(), i-1);
CHAM_DecRound<13, 16>(m_x.begin(), m_rk.begin(), i-2);
CHAM_DecRound<12, 16>(m_x.begin(), m_rk.begin(), i-3);
CHAM_DecRound<11, 16>(m_x.begin(), m_rk.begin(), i-4);
CHAM_DecRound<10, 16>(m_x.begin(), m_rk.begin(), i-5);
CHAM_DecRound< 9, 16>(m_x.begin(), m_rk.begin(), i-6);
CHAM_DecRound< 8, 16>(m_x.begin(), m_rk.begin(), i-7);
CHAM_DecRound< 7, 16>(m_x.begin(), m_rk.begin(), i-8);
CHAM_DecRound< 6, 16>(m_x.begin(), m_rk.begin(), i-9);
CHAM_DecRound< 5, 16>(m_x.begin(), m_rk.begin(), i-10);
CHAM_DecRound< 4, 16>(m_x.begin(), m_rk.begin(), i-11);
CHAM_DecRound< 3, 16>(m_x.begin(), m_rk.begin(), i-12);
CHAM_DecRound< 2, 16>(m_x.begin(), m_rk.begin(), i-13);
CHAM_DecRound< 1, 16>(m_x.begin(), m_rk.begin(), i-14);
CHAM_DecRound< 0, 16>(m_x.begin(), m_rk.begin(), i-15);
}
PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
}
void CHAM128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
CRYPTOPP_UNUSED(params);
m_kw = keyLength/sizeof(word32);
m_rk.New(2*m_kw);
for (size_t i = 0; i < m_kw; ++i, userKey += sizeof(word32))
{
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
const word32 rk = GetWord<word32>(false, BIG_ENDIAN_ORDER, userKey);
m_rk[i] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<8>(rk);
m_rk[(i + m_kw) ^ 1] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<11>(rk);
}
}
void CHAM128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
GetBlock<word32, BigEndian> iblock(inBlock);
iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
switch (m_kw)
{
case 4: // 128-bit key
{
const unsigned int R = 80;
for (int i = 0; i < R; i+=8)
{
CHAM_EncRound<0, 8>(m_x.begin(), m_rk.begin(), i+0);
CHAM_EncRound<1, 8>(m_x.begin(), m_rk.begin(), i+1);
CHAM_EncRound<2, 8>(m_x.begin(), m_rk.begin(), i+2);
CHAM_EncRound<3, 8>(m_x.begin(), m_rk.begin(), i+3);
CHAM_EncRound<4, 8>(m_x.begin(), m_rk.begin(), i+4);
CHAM_EncRound<5, 8>(m_x.begin(), m_rk.begin(), i+5);
CHAM_EncRound<6, 8>(m_x.begin(), m_rk.begin(), i+6);
CHAM_EncRound<7, 8>(m_x.begin(), m_rk.begin(), i+7);
}
break;
}
case 8: // 256-bit key
{
const unsigned int R = 96;
for (int i = 0; i < R; i+=16)
{
CHAM_EncRound< 0, 16>(m_x.begin(), m_rk.begin(), i+0);
CHAM_EncRound< 1, 16>(m_x.begin(), m_rk.begin(), i+1);
CHAM_EncRound< 2, 16>(m_x.begin(), m_rk.begin(), i+2);
CHAM_EncRound< 3, 16>(m_x.begin(), m_rk.begin(), i+3);
CHAM_EncRound< 4, 16>(m_x.begin(), m_rk.begin(), i+4);
CHAM_EncRound< 5, 16>(m_x.begin(), m_rk.begin(), i+5);
CHAM_EncRound< 6, 16>(m_x.begin(), m_rk.begin(), i+6);
CHAM_EncRound< 7, 16>(m_x.begin(), m_rk.begin(), i+7);
CHAM_EncRound< 8, 16>(m_x.begin(), m_rk.begin(), i+8);
CHAM_EncRound< 9, 16>(m_x.begin(), m_rk.begin(), i+9);
CHAM_EncRound<10, 16>(m_x.begin(), m_rk.begin(), i+10);
CHAM_EncRound<11, 16>(m_x.begin(), m_rk.begin(), i+11);
CHAM_EncRound<12, 16>(m_x.begin(), m_rk.begin(), i+12);
CHAM_EncRound<13, 16>(m_x.begin(), m_rk.begin(), i+13);
CHAM_EncRound<14, 16>(m_x.begin(), m_rk.begin(), i+14);
CHAM_EncRound<15, 16>(m_x.begin(), m_rk.begin(), i+15);
}
break;
}
default:
CRYPTOPP_ASSERT(0);;
}
PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
}
void CHAM128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
GetBlock<word32, BigEndian> iblock(inBlock);
iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
switch (m_kw)
{
case 4: // 128-bit key
{
const unsigned int R = 80;
for (int i = R-1; i >= 0; i-=8)
{
CHAM_DecRound<7, 8>(m_x.begin(), m_rk.begin(), i-0);
CHAM_DecRound<6, 8>(m_x.begin(), m_rk.begin(), i-1);
CHAM_DecRound<5, 8>(m_x.begin(), m_rk.begin(), i-2);
CHAM_DecRound<4, 8>(m_x.begin(), m_rk.begin(), i-3);
CHAM_DecRound<3, 8>(m_x.begin(), m_rk.begin(), i-4);
CHAM_DecRound<2, 8>(m_x.begin(), m_rk.begin(), i-5);
CHAM_DecRound<1, 8>(m_x.begin(), m_rk.begin(), i-6);
CHAM_DecRound<0, 8>(m_x.begin(), m_rk.begin(), i-7);
}
break;
}
case 8: // 256-bit key
{
const unsigned int R = 96;
for (int i = R-1; i >= 0; i-=16)
{
CHAM_DecRound<15, 16>(m_x.begin(), m_rk.begin(), i-0);
CHAM_DecRound<14, 16>(m_x.begin(), m_rk.begin(), i-1);
CHAM_DecRound<13, 16>(m_x.begin(), m_rk.begin(), i-2);
CHAM_DecRound<12, 16>(m_x.begin(), m_rk.begin(), i-3);
CHAM_DecRound<11, 16>(m_x.begin(), m_rk.begin(), i-4);
CHAM_DecRound<10, 16>(m_x.begin(), m_rk.begin(), i-5);
CHAM_DecRound< 9, 16>(m_x.begin(), m_rk.begin(), i-6);
CHAM_DecRound< 8, 16>(m_x.begin(), m_rk.begin(), i-7);
CHAM_DecRound< 7, 16>(m_x.begin(), m_rk.begin(), i-8);
CHAM_DecRound< 6, 16>(m_x.begin(), m_rk.begin(), i-9);
CHAM_DecRound< 5, 16>(m_x.begin(), m_rk.begin(), i-10);
CHAM_DecRound< 4, 16>(m_x.begin(), m_rk.begin(), i-11);
CHAM_DecRound< 3, 16>(m_x.begin(), m_rk.begin(), i-12);
CHAM_DecRound< 2, 16>(m_x.begin(), m_rk.begin(), i-13);
CHAM_DecRound< 1, 16>(m_x.begin(), m_rk.begin(), i-14);
CHAM_DecRound< 0, 16>(m_x.begin(), m_rk.begin(), i-15);
}
break;
}
default:
CRYPTOPP_ASSERT(0);;
}
PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
}
NAMESPACE_END

144
cham.h Normal file
View File

@ -0,0 +1,144 @@
// cham.h - written and placed in the public domain by Kim Sung Hee and Jeffrey Walton
// Based on "CHAM: A Family of Lightweight Block Ciphers for
// Resource-Constrained Devices" by Bonwook Koo, Dongyoung Roh,
// Hyeonjin Kim, Younghoon Jung, Dong-Geon Lee, and Daesung Kwon
/// \file cham.h
/// \brief Classes for the CHAM block cipher
/// \since Crypto++ 7.1
#ifndef CRYPTOPP_CHAM_H
#define CRYPTOPP_CHAM_H
#include "config.h"
#include "seckey.h"
#include "secblock.h"
#include "algparam.h"
NAMESPACE_BEGIN(CryptoPP)
/// \brief CHAM block cipher information
/// \since Crypto++ 7.1
struct CHAM64_Info : public FixedBlockSize<8>, FixedKeyLength<16>
{
static const std::string StaticAlgorithmName()
{
// Format is Cipher-Blocksize
return "CHAM-64";
}
};
/// \brief CHAM block cipher information
/// \since Crypto++ 7.1
struct CHAM128_Info : public FixedBlockSize<16>, VariableKeyLength<16,16,32,16>
{
static const std::string StaticAlgorithmName()
{
// Format is Cipher-Blocksize
return "CHAM-128";
}
};
/// \brief CHAM 64-bit block cipher
/// \details CHAM64 provides 64-bit block size. The valid key size is 128-bit.
/// \note Crypto++ provides a byte oriented implementation
/// \sa CHAM128, <a href="http://www.cryptopp.com/wiki/CHAM">CHAM</a>, <a href=
/// "https://pdfs.semanticscholar.org/2f57/61b5c2614cffd58a09cc83c375a2b32a2ed3.pdf">
/// CHAM: A Family of Lightweight Block Ciphers for Resource-Constrained Devices</a>
/// \since Crypto++ 7.1
class CRYPTOPP_NO_VTABLE CHAM64 : public CHAM64_Info, public BlockCipherDocumentation
{
public:
/// \brief CHAM block cipher transformation functions
/// \details Provides implementation common to encryption and decryption
/// \since Crypto++ 7.1
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<CHAM64_Info>
{
protected:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
SecBlock<word16> m_rk;
mutable FixedSizeSecBlock<word16, 4> m_x;
unsigned int m_kw;
};
/// \brief Provides implementation for encryption transformation
/// \details Enc provides implementation for encryption transformation. All key and block
/// sizes are supported.
/// \since Crypto++ 7.1
class CRYPTOPP_NO_VTABLE Enc : public Base
{
public:
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 and block
/// sizes are supported.
/// \since Crypto++ 7.1
class CRYPTOPP_NO_VTABLE Dec : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
};
typedef CHAM64::Encryption CHAM64Encryption;
typedef CHAM64::Decryption CHAM64Decryption;
/// \brief CHAM 128-bit block cipher
/// \details CHAM128 provides 128-bit block size. The valid key size is 128-bit and 256-bit.
/// \note Crypto++ provides a byte oriented implementation
/// \sa CHAM128, <a href="http://www.cryptopp.com/wiki/CHAM">CHAM</a>, <a href=
/// "https://pdfs.semanticscholar.org/2f57/61b5c2614cffd58a09cc83c375a2b32a2ed3.pdf">
/// CHAM: A Family of Lightweight Block Ciphers for Resource-Constrained Devices</a>
/// \since Crypto++ 7.1
class CRYPTOPP_NO_VTABLE CHAM128 : public CHAM128_Info, public BlockCipherDocumentation
{
public:
/// \brief CHAM block cipher transformation functions
/// \details Provides implementation common to encryption and decryption
/// \since Crypto++ 7.1
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<CHAM128_Info>
{
protected:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
SecBlock<word32> m_rk;
mutable FixedSizeSecBlock<word32, 4> m_x;
unsigned int m_kw;
};
/// \brief Provides implementation for encryption transformation
/// \details Enc provides implementation for encryption transformation. All key and block
/// sizes are supported.
/// \since Crypto++ 7.1
class CRYPTOPP_NO_VTABLE Enc : public Base
{
public:
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 and block
/// sizes are supported.
/// \since Crypto++ 7.1
class CRYPTOPP_NO_VTABLE Dec : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
};
typedef CHAM128::Encryption CHAM128Encryption;
typedef CHAM128::Decryption CHAM128Decryption;
NAMESPACE_END
#endif // CRYPTOPP_CHAM_H

View File

@ -232,6 +232,7 @@
<None Include="TestVectors\camellia.txt" />
<None Include="TestVectors\ccm.txt" />
<None Include="TestVectors\chacha.txt" />
<None Include="TestVectors\cham.txt" />
<None Include="TestVectors\cmac.txt" />
<None Include="TestVectors\dlies.txt" />
<None Include="TestVectors\dsa.txt" />

View File

@ -50,6 +50,9 @@
<None Include="TestVectors\chacha.txt">
<Filter>TestVectors</Filter>
</None>
<None Include="TestVectors\cham.txt">
<Filter>TestVectors</Filter>
</None>
<None Include="TestVectors\cmac.txt">
<Filter>TestVectors</Filter>
</None>

View File

@ -191,6 +191,7 @@
<ClCompile Include="cbcmac.cpp" />
<ClCompile Include="ccm.cpp" />
<ClCompile Include="chacha.cpp" />
<ClCompile Include="cham.cpp" />
<ClCompile Include="channels.cpp" />
<ClCompile Include="cmac.cpp" />
<ClCompile Include="crc.cpp" />
@ -383,6 +384,7 @@
<ClInclude Include="cbcmac.h" />
<ClInclude Include="ccm.h" />
<ClInclude Include="chacha.h" />
<ClInclude Include="cham.h" />
<ClInclude Include="channels.h" />
<ClInclude Include="cmac.h" />
<ClInclude Include="config.h" />

View File

@ -86,6 +86,9 @@
<ClCompile Include="chacha.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="cham.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="channels.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -543,6 +546,9 @@
<ClInclude Include="ccm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cham.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="channels.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -12,6 +12,7 @@
#include "seal.h"
#include "ttmac.h"
#include "aria.h"
#include "cham.h"
#include "camellia.h"
#include "shacal2.h"
#include "tea.h"
@ -181,6 +182,11 @@ void RegisterFactories2()
RegisterSymmetricCipherDefaultFactories<CTR_Mode<SPECK64> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<CTR_Mode<SPECK128> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<ECB_Mode<CHAM64> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<ECB_Mode<CHAM128> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CTR_Mode<CHAM64> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<CTR_Mode<CHAM128> >(); // Benchmarks
RegisterSymmetricCipherDefaultFactories<ECB_Mode<SM4> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CBC_Mode<SM4> >(); // Test Vectors
RegisterSymmetricCipherDefaultFactories<CTR_Mode<SM4> >(); // Benchmarks

View File

@ -949,6 +949,7 @@ bool Validate(int alg, bool thorough, const char *seedInput)
case 80: result = ValidateHashDRBG(); break;
case 81: result = ValidateHmacDRBG(); break;
case 82: result = ValidateNaCl(); break;
case 83: result = ValidateCHAM(); break;
#if defined(CRYPTOPP_EXTENDED_VALIDATION)
// http://github.com/weidai11/cryptopp/issues/92

View File

@ -171,6 +171,7 @@ bool ValidateAll(bool thorough)
pass=ValidateSerpent() && pass;
pass=ValidateSHACAL2() && pass;
pass=ValidateARIA() && pass;
pass=ValidateCHAM() && pass;
pass=ValidateLEA() && pass;
pass=ValidateCamellia() && pass;
pass=ValidateSalsa() && pass;
@ -3388,6 +3389,13 @@ bool ValidateARIA()
return pass1 && pass2 && pass3;
}
bool ValidateCHAM()
{
std::cout << "\nCHAM validation suite running...\n";
return RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/cham.txt");
}
bool ValidateLEA()
{
std::cout << "\nLEA validation suite running...\n";

View File

@ -81,6 +81,7 @@ bool ValidateTwofish();
bool ValidateSerpent();
bool ValidateSHACAL2();
bool ValidateARIA();
bool ValidateCHAM();
bool ValidateLEA();
bool ValidateCamellia();
bool ValidateSalsa();