Path: blob/a-new-beginning/SharedDependencies/Sources/cryptopp/cham.cpp
2 views
// cham.cpp - written and placed in the public domain by Kim Sung Hee and Jeffrey Walton1// Based on "CHAM: A Family of Lightweight Block Ciphers for2// Resource-Constrained Devices" by Bonwook Koo, Dongyoung Roh,3// Hyeonjin Kim, Younghoon Jung, Dong-Geon Lee, and Daesung Kwon45#include "pch.h"6#include "config.h"78#include "cham.h"9#include "misc.h"10#include "cpu.h"1112// CHAM table of parameters13// +-------------------------------------------------14// +cipher n k r w k/w15// +-------------------------------------------------16// +CHAM-64/128 64 128 80 16 817// +CHAM-128/128 128 128 80 32 418// +CHAM-128/256 128 256 96 32 819// +-------------------------------------------------2021ANONYMOUS_NAMESPACE_BEGIN2223using CryptoPP::rotlConstant;24using CryptoPP::rotrConstant;2526/// \brief CHAM encryption round27/// \tparam RR the round number residue28/// \tparam KW the number of key words29/// \tparam T words type30/// \param x the state array31/// \param k the subkey table32/// \param i the round number33/// \details CHAM_EncRound applies the encryption round to the plain text.34/// RR is the "round residue" and it is used modulo 4. ProcessAndXorBlock35/// may provide a fully unrolled encryption transformation, or provide36/// a transformation that loops using multiples of 4 encryption rounds.37/// \details CHAM_EncRound calculates indexes into the x[] array based38/// on the round number residue. There is no need for the assignments39/// that shift values in preparations for the next round.40/// \details CHAM_EncRound depends on the round number. The actual round41/// being executed is passed through the parameter <tt>i</tt>. If42/// ProcessAndXorBlock fully unrolled the loop then the parameter43/// <tt>i</tt> would be unnecessary.44template <unsigned int RR, unsigned int KW, class T>45inline void CHAM_EncRound(T x[4], const T k[KW], unsigned int i)46{47CRYPTOPP_CONSTANT(IDX0 = (RR+0) % 4);48CRYPTOPP_CONSTANT(IDX1 = (RR+1) % 4);49CRYPTOPP_CONSTANT(IDX3 = (RR+3+1) % 4);50CRYPTOPP_CONSTANT(R1 = (RR % 2 == 0) ? 1 : 8);51CRYPTOPP_CONSTANT(R2 = (RR % 2 == 0) ? 8 : 1);5253// Follows conventions in the ref impl54const T kk = k[i % KW];55const T aa = x[IDX0] ^ static_cast<T>(i);56const T bb = rotlConstant<R1>(x[IDX1]) ^ kk;57x[IDX3] = rotlConstant<R2>(static_cast<T>(aa + bb));58}5960/// \brief CHAM decryption round61/// \tparam RR the round number residue62/// \tparam KW the number of key words63/// \tparam T words type64/// \param x the state array65/// \param k the subkey table66/// \param i the round number67/// \details CHAM_DecRound applies the decryption round to the cipher text.68/// RR is the "round residue" and it is used modulo 4. ProcessAndXorBlock69/// may provide a fully unrolled decryption transformation, or provide70/// a transformation that loops using multiples of 4 decryption rounds.71/// \details CHAM_DecRound calculates indexes into the x[] array based72/// on the round number residue. There is no need for the assignments73/// that shift values in preparations for the next round.74/// \details CHAM_DecRound depends on the round number. The actual round75/// being executed is passed through the parameter <tt>i</tt>. If76/// ProcessAndXorBlock fully unrolled the loop then the parameter77/// <tt>i</tt> would be unnecessary.78template <unsigned int RR, unsigned int KW, class T>79inline void CHAM_DecRound(T x[4], const T k[KW], unsigned int i)80{81CRYPTOPP_CONSTANT(IDX0 = (RR+0) % 4);82CRYPTOPP_CONSTANT(IDX1 = (RR+1) % 4);83CRYPTOPP_CONSTANT(IDX3 = (RR+3+1) % 4);84CRYPTOPP_CONSTANT(R1 = (RR % 2 == 0) ? 8 : 1);85CRYPTOPP_CONSTANT(R2 = (RR % 2 == 0) ? 1 : 8);8687// Follows conventions in the ref impl88const T kk = k[i % KW];89const T aa = rotrConstant<R1>(x[IDX3]);90const T bb = rotlConstant<R2>(x[IDX1]) ^ kk;91x[IDX0] = static_cast<T>(aa - bb) ^ static_cast<T>(i);92}9394ANONYMOUS_NAMESPACE_END9596NAMESPACE_BEGIN(CryptoPP)9798#if CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS99# if (CRYPTOPP_SSSE3_AVAILABLE)100extern size_t CHAM64_Enc_AdvancedProcessBlocks_SSSE3(const word16* subKeys, size_t rounds,101const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);102103extern size_t CHAM64_Dec_AdvancedProcessBlocks_SSSE3(const word16* subKeys, size_t rounds,104const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);105106extern size_t CHAM128_Enc_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds,107const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);108109extern size_t CHAM128_Dec_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds,110const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);111# endif // CRYPTOPP_SSSE3_AVAILABLE112#endif // CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS113114void CHAM64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)115{116CRYPTOPP_UNUSED(params);117m_kw = keyLength/sizeof(word16);118m_rk.New(2*m_kw);119120for (size_t i = 0; i < m_kw; userKey += sizeof(word32))121{122// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.123const word32 rk = GetWord<word32>(false, BIG_ENDIAN_ORDER, userKey);124125const word16 rk1 = static_cast<word16>(rk >> 16);126m_rk[i] = rk1 ^ rotlConstant<1>(rk1) ^ rotlConstant<8>(rk1);127m_rk[(i + m_kw) ^ 1] = rk1 ^ rotlConstant<1>(rk1) ^ rotlConstant<11>(rk1);128i++;129130const word16 rk2 = static_cast<word16>(rk & 0xffff);131m_rk[i] = rk2 ^ rotlConstant<1>(rk2) ^ rotlConstant<8>(rk2);132m_rk[(i + m_kw) ^ 1] = rk2 ^ rotlConstant<1>(rk2) ^ rotlConstant<11>(rk2);133i++;134}135}136137void CHAM64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const138{139// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.140GetBlock<word16, BigEndian> iblock(inBlock);141iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);142143const int R = 80;144for (int i = 0; i < R; i+=16)145{146CHAM_EncRound< 0, 16>(m_x.begin(), m_rk.begin(), i+0);147CHAM_EncRound< 1, 16>(m_x.begin(), m_rk.begin(), i+1);148CHAM_EncRound< 2, 16>(m_x.begin(), m_rk.begin(), i+2);149CHAM_EncRound< 3, 16>(m_x.begin(), m_rk.begin(), i+3);150CHAM_EncRound< 4, 16>(m_x.begin(), m_rk.begin(), i+4);151CHAM_EncRound< 5, 16>(m_x.begin(), m_rk.begin(), i+5);152CHAM_EncRound< 6, 16>(m_x.begin(), m_rk.begin(), i+6);153CHAM_EncRound< 7, 16>(m_x.begin(), m_rk.begin(), i+7);154CHAM_EncRound< 8, 16>(m_x.begin(), m_rk.begin(), i+8);155CHAM_EncRound< 9, 16>(m_x.begin(), m_rk.begin(), i+9);156CHAM_EncRound<10, 16>(m_x.begin(), m_rk.begin(), i+10);157CHAM_EncRound<11, 16>(m_x.begin(), m_rk.begin(), i+11);158CHAM_EncRound<12, 16>(m_x.begin(), m_rk.begin(), i+12);159CHAM_EncRound<13, 16>(m_x.begin(), m_rk.begin(), i+13);160CHAM_EncRound<14, 16>(m_x.begin(), m_rk.begin(), i+14);161CHAM_EncRound<15, 16>(m_x.begin(), m_rk.begin(), i+15);162}163164PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);165oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);166}167168void CHAM64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const169{170// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.171GetBlock<word16, BigEndian> iblock(inBlock);172iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);173174const int R = 80;175for (int i = R-1; i >=0 ; i-=16)176{177CHAM_DecRound<15, 16>(m_x.begin(), m_rk.begin(), i-0);178CHAM_DecRound<14, 16>(m_x.begin(), m_rk.begin(), i-1);179CHAM_DecRound<13, 16>(m_x.begin(), m_rk.begin(), i-2);180CHAM_DecRound<12, 16>(m_x.begin(), m_rk.begin(), i-3);181CHAM_DecRound<11, 16>(m_x.begin(), m_rk.begin(), i-4);182CHAM_DecRound<10, 16>(m_x.begin(), m_rk.begin(), i-5);183CHAM_DecRound< 9, 16>(m_x.begin(), m_rk.begin(), i-6);184CHAM_DecRound< 8, 16>(m_x.begin(), m_rk.begin(), i-7);185CHAM_DecRound< 7, 16>(m_x.begin(), m_rk.begin(), i-8);186CHAM_DecRound< 6, 16>(m_x.begin(), m_rk.begin(), i-9);187CHAM_DecRound< 5, 16>(m_x.begin(), m_rk.begin(), i-10);188CHAM_DecRound< 4, 16>(m_x.begin(), m_rk.begin(), i-11);189CHAM_DecRound< 3, 16>(m_x.begin(), m_rk.begin(), i-12);190CHAM_DecRound< 2, 16>(m_x.begin(), m_rk.begin(), i-13);191CHAM_DecRound< 1, 16>(m_x.begin(), m_rk.begin(), i-14);192CHAM_DecRound< 0, 16>(m_x.begin(), m_rk.begin(), i-15);193}194195PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);196oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);197}198199std::string CHAM128::Base::AlgorithmProvider() const200{201#if defined(CRYPTOPP_SSSE3_AVAILABLE)202if (HasSSSE3())203return "SSSE3";204#endif205return "C++";206}207208void CHAM128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)209{210CRYPTOPP_UNUSED(params);211m_kw = keyLength/sizeof(word32);212m_rk.New(2*m_kw);213214for (size_t i = 0; i < m_kw; userKey += sizeof(word32))215{216// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.217const word32 rk = GetWord<word32>(false, BIG_ENDIAN_ORDER, userKey);218m_rk[i] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<8>(rk);219m_rk[(i + m_kw) ^ 1] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<11>(rk);220i++;221}222}223224void CHAM128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const225{226// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.227GetBlock<word32, BigEndian> iblock(inBlock);228iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);229230switch (m_kw)231{232case 4: // 128-bit key233{234const int R = 80;235for (int i = 0; i < R; i+=8)236{237CHAM_EncRound<0, 8>(m_x.begin(), m_rk.begin(), i+0);238CHAM_EncRound<1, 8>(m_x.begin(), m_rk.begin(), i+1);239CHAM_EncRound<2, 8>(m_x.begin(), m_rk.begin(), i+2);240CHAM_EncRound<3, 8>(m_x.begin(), m_rk.begin(), i+3);241CHAM_EncRound<4, 8>(m_x.begin(), m_rk.begin(), i+4);242CHAM_EncRound<5, 8>(m_x.begin(), m_rk.begin(), i+5);243CHAM_EncRound<6, 8>(m_x.begin(), m_rk.begin(), i+6);244CHAM_EncRound<7, 8>(m_x.begin(), m_rk.begin(), i+7);245}246break;247}248case 8: // 256-bit key249{250const int R = 96;251for (int i = 0; i < R; i+=16)252{253CHAM_EncRound< 0, 16>(m_x.begin(), m_rk.begin(), i+0);254CHAM_EncRound< 1, 16>(m_x.begin(), m_rk.begin(), i+1);255CHAM_EncRound< 2, 16>(m_x.begin(), m_rk.begin(), i+2);256CHAM_EncRound< 3, 16>(m_x.begin(), m_rk.begin(), i+3);257CHAM_EncRound< 4, 16>(m_x.begin(), m_rk.begin(), i+4);258CHAM_EncRound< 5, 16>(m_x.begin(), m_rk.begin(), i+5);259CHAM_EncRound< 6, 16>(m_x.begin(), m_rk.begin(), i+6);260CHAM_EncRound< 7, 16>(m_x.begin(), m_rk.begin(), i+7);261CHAM_EncRound< 8, 16>(m_x.begin(), m_rk.begin(), i+8);262CHAM_EncRound< 9, 16>(m_x.begin(), m_rk.begin(), i+9);263CHAM_EncRound<10, 16>(m_x.begin(), m_rk.begin(), i+10);264CHAM_EncRound<11, 16>(m_x.begin(), m_rk.begin(), i+11);265CHAM_EncRound<12, 16>(m_x.begin(), m_rk.begin(), i+12);266CHAM_EncRound<13, 16>(m_x.begin(), m_rk.begin(), i+13);267CHAM_EncRound<14, 16>(m_x.begin(), m_rk.begin(), i+14);268CHAM_EncRound<15, 16>(m_x.begin(), m_rk.begin(), i+15);269}270break;271}272default:273CRYPTOPP_ASSERT(0);274}275276PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);277oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);278}279280void CHAM128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const281{282// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.283GetBlock<word32, BigEndian> iblock(inBlock);284iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);285286switch (m_kw)287{288case 4: // 128-bit key289{290const int R = 80;291for (int i = R-1; i >= 0; i-=8)292{293CHAM_DecRound<7, 8>(m_x.begin(), m_rk.begin(), i-0);294CHAM_DecRound<6, 8>(m_x.begin(), m_rk.begin(), i-1);295CHAM_DecRound<5, 8>(m_x.begin(), m_rk.begin(), i-2);296CHAM_DecRound<4, 8>(m_x.begin(), m_rk.begin(), i-3);297CHAM_DecRound<3, 8>(m_x.begin(), m_rk.begin(), i-4);298CHAM_DecRound<2, 8>(m_x.begin(), m_rk.begin(), i-5);299CHAM_DecRound<1, 8>(m_x.begin(), m_rk.begin(), i-6);300CHAM_DecRound<0, 8>(m_x.begin(), m_rk.begin(), i-7);301}302break;303}304case 8: // 256-bit key305{306const int R = 96;307for (int i = R-1; i >= 0; i-=16)308{309CHAM_DecRound<15, 16>(m_x.begin(), m_rk.begin(), i-0);310CHAM_DecRound<14, 16>(m_x.begin(), m_rk.begin(), i-1);311CHAM_DecRound<13, 16>(m_x.begin(), m_rk.begin(), i-2);312CHAM_DecRound<12, 16>(m_x.begin(), m_rk.begin(), i-3);313CHAM_DecRound<11, 16>(m_x.begin(), m_rk.begin(), i-4);314CHAM_DecRound<10, 16>(m_x.begin(), m_rk.begin(), i-5);315CHAM_DecRound< 9, 16>(m_x.begin(), m_rk.begin(), i-6);316CHAM_DecRound< 8, 16>(m_x.begin(), m_rk.begin(), i-7);317CHAM_DecRound< 7, 16>(m_x.begin(), m_rk.begin(), i-8);318CHAM_DecRound< 6, 16>(m_x.begin(), m_rk.begin(), i-9);319CHAM_DecRound< 5, 16>(m_x.begin(), m_rk.begin(), i-10);320CHAM_DecRound< 4, 16>(m_x.begin(), m_rk.begin(), i-11);321CHAM_DecRound< 3, 16>(m_x.begin(), m_rk.begin(), i-12);322CHAM_DecRound< 2, 16>(m_x.begin(), m_rk.begin(), i-13);323CHAM_DecRound< 1, 16>(m_x.begin(), m_rk.begin(), i-14);324CHAM_DecRound< 0, 16>(m_x.begin(), m_rk.begin(), i-15);325}326break;327}328default:329CRYPTOPP_ASSERT(0);330}331332PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);333oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);334}335336#if CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS337size_t CHAM128::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,338byte *outBlocks, size_t length, word32 flags) const339{340# if (CRYPTOPP_SSSE3_AVAILABLE)341if (HasSSSE3()) {342const size_t rounds = (m_kw == 4 ? 80 : 96);343return CHAM128_Enc_AdvancedProcessBlocks_SSSE3(m_rk, rounds,344inBlocks, xorBlocks, outBlocks, length, flags);345}346# endif // CRYPTOPP_SSSE3_AVAILABLE347return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);348}349350size_t CHAM128::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,351byte *outBlocks, size_t length, word32 flags) const352{353# if (CRYPTOPP_SSSE3_AVAILABLE)354if (HasSSSE3()) {355const size_t rounds = (m_kw == 4 ? 80 : 96);356return CHAM128_Dec_AdvancedProcessBlocks_SSSE3(m_rk, rounds,357inBlocks, xorBlocks, outBlocks, length, flags);358}359# endif // CRYPTOPP_SSSE3_AVAILABLE360return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);361}362#endif // CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS363364NAMESPACE_END365366367