diff --git a/Filelist.txt b/Filelist.txt index 7a2be2c2..49264165 100644 --- a/Filelist.txt +++ b/Filelist.txt @@ -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 diff --git a/TestVectors/all.txt b/TestVectors/all.txt index 069140d1..1cc01481 100644 --- a/TestVectors/all.txt +++ b/TestVectors/all.txt @@ -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 diff --git a/TestVectors/cham.txt b/TestVectors/cham.txt new file mode 100644 index 00000000..0620a5bf --- /dev/null +++ b/TestVectors/cham.txt @@ -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 diff --git a/bench1.cpp b/bench1.cpp index d5dee986..f41b0372 100644 --- a/bench1.cpp +++ b/bench1.cpp @@ -592,7 +592,7 @@ void Benchmark2(double t, double hertz) BenchMarkByName("Threefish-1024(1024)/CTR", 128); BenchMarkByName("Serpent/CTR"); BenchMarkByName("CAST-128/CTR"); - BenchMarkByName("CAST-256/CTR"); + BenchMarkByName("CAST-256/CTR", 32); BenchMarkByName("RC6/CTR"); BenchMarkByName("MARS/CTR"); BenchMarkByName("SHACAL-2/CTR", 16); @@ -614,6 +614,13 @@ void Benchmark2(double t, double hertz) BenchMarkByName("Kalyna-256/CTR", 32, "Kalyna-256(256)/CTR (256-bit key)"); BenchMarkByName("Kalyna-256/CTR", 64, "Kalyna-256(512)/CTR (512-bit key)"); BenchMarkByName("Kalyna-512/CTR", 64, "Kalyna-512(512)/CTR (512-bit key)"); + } + + std::cout << "\n"; + { + BenchMarkByName("CHAM-64/CTR", 16, "CHAM-64(128)/CTR (128-bit key)"); + BenchMarkByName("CHAM-128/CTR", 16, "CHAM-128(128)/CTR (128-bit key)"); + BenchMarkByName("CHAM-128/CTR", 32, "CHAM-128(256)/CTR (256-bit key)"); BenchMarkByName("LEA-128/CTR", 16, "LEA-128(128)/CTR (128-bit key)"); BenchMarkByName("LEA-128/CTR", 24, "LEA-128(192)/CTR (192-bit key)"); @@ -632,7 +639,7 @@ void Benchmark2(double t, double hertz) BenchMarkByName("SPECK-128/CTR", 32, "SPECK-128(256)/CTR (256-bit key)"); } - std::cout << "\n"; + std::cout << "\n"; { #if CRYPTOPP_AESNI_AVAILABLE if (HasCLMUL()) diff --git a/cham.cpp b/cham.cpp new file mode 100644 index 00000000..53fe3c16 --- /dev/null +++ b/cham.cpp @@ -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 i. If +/// ProcessAndXorBlock fully unrolled the loop then the parameter +/// i would be unnecessary. +template +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(i); + const T bb = rotlConstant(x[IDX1]) ^ kk; + x[IDX3] = rotlConstant(static_cast(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 i. If +/// ProcessAndXorBlock fully unrolled the loop then the parameter +/// i would be unnecessary. +template +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(x[IDX3]); + const T bb = rotlConstant(x[IDX1]) ^ kk; + x[IDX0] = static_cast(aa - bb) ^ static_cast(i); +} + +ANONYMOUS_NAMESPACE_END + +NAMESPACE_BEGIN(CryptoPP) + +void CHAM64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms) +{ + 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(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 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 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 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 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 ¶ms) +{ + 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(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 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 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 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 oblock(xorBlock, outBlock); + oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]); +} + +NAMESPACE_END diff --git a/cham.h b/cham.h new file mode 100644 index 00000000..52edc4dc --- /dev/null +++ b/cham.h @@ -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, CHAM, +/// CHAM: A Family of Lightweight Block Ciphers for Resource-Constrained Devices +/// \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 + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + + SecBlock m_rk; + mutable FixedSizeSecBlock 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; + typedef BlockCipherFinal 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, CHAM, +/// CHAM: A Family of Lightweight Block Ciphers for Resource-Constrained Devices +/// \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 + { + protected: + void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms); + + SecBlock m_rk; + mutable FixedSizeSecBlock 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; + typedef BlockCipherFinal Decryption; +}; + +typedef CHAM128::Encryption CHAM128Encryption; +typedef CHAM128::Decryption CHAM128Decryption; + +NAMESPACE_END + +#endif // CRYPTOPP_CHAM_H diff --git a/cryptest.vcxproj b/cryptest.vcxproj index b6496874..6a65a69b 100644 --- a/cryptest.vcxproj +++ b/cryptest.vcxproj @@ -232,6 +232,7 @@ + diff --git a/cryptest.vcxproj.filters b/cryptest.vcxproj.filters index d7c93a59..65208f32 100644 --- a/cryptest.vcxproj.filters +++ b/cryptest.vcxproj.filters @@ -50,6 +50,9 @@ TestVectors + + TestVectors + TestVectors diff --git a/cryptlib.vcxproj b/cryptlib.vcxproj index 7b8700cf..774705cc 100644 --- a/cryptlib.vcxproj +++ b/cryptlib.vcxproj @@ -191,6 +191,7 @@ + @@ -383,6 +384,7 @@ + diff --git a/cryptlib.vcxproj.filters b/cryptlib.vcxproj.filters index 29c9cce4..954a74ce 100644 --- a/cryptlib.vcxproj.filters +++ b/cryptlib.vcxproj.filters @@ -86,6 +86,9 @@ Source Files + + Source Files + Source Files @@ -543,6 +546,9 @@ Header Files + + Header Files + Header Files diff --git a/regtest2.cpp b/regtest2.cpp index ffcb3e4b..22833c41 100644 --- a/regtest2.cpp +++ b/regtest2.cpp @@ -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 >(); // Benchmarks RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors RegisterSymmetricCipherDefaultFactories >(); // Test Vectors RegisterSymmetricCipherDefaultFactories >(); // Benchmarks diff --git a/test.cpp b/test.cpp index 109ca6c6..f9c79e34 100644 --- a/test.cpp +++ b/test.cpp @@ -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 diff --git a/validat1.cpp b/validat1.cpp index 7a6d60d8..02e5ef95 100644 --- a/validat1.cpp +++ b/validat1.cpp @@ -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"; diff --git a/validate.h b/validate.h index 5362de3c..a01a2b4a 100644 --- a/validate.h +++ b/validate.h @@ -81,6 +81,7 @@ bool ValidateTwofish(); bool ValidateSerpent(); bool ValidateSHACAL2(); bool ValidateARIA(); +bool ValidateCHAM(); bool ValidateLEA(); bool ValidateCamellia(); bool ValidateSalsa();