1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
// simeck.cpp - written and placed in the public domain by Gangqiang Yang and Jeffrey Walton.
// Based on "The Simeck Family of Lightweight Block Ciphers" by Gangqiang Yang,
// Bo Zhu, Valentin Suder, Mark D. Aagaard, and Guang Gong
#include "pch.h"
#include "config.h"
#include "simeck.h"
#include "misc.h"
#include "cpu.h"
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::rotlConstant;
using CryptoPP::rotrConstant;
/// \brief SIMECK encryption round
/// \tparam T word type
/// \param key the key for the round or iteration
/// \param left the first value
/// \param right the second value
/// \details SIMECK_Encryption serves as the key schedule, encryption and
/// decryption functions.
template <class T>
inline void SIMECK_Encryption(const T key, T& left, T& right)
{
const T temp = left;
left = (left & rotlConstant<5>(left)) ^ rotlConstant<1>(left) ^ right ^ key;
right = temp;
}
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
std::string SIMECK32::Base::AlgorithmProvider() const
{
return "C++";
}
void SIMECK32::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)
{
CRYPTOPP_UNUSED(params);
CRYPTOPP_UNUSED(keyLength);
GetBlock<word16, BigEndian> kblock(userKey);
kblock(m_t[3])(m_t[2])(m_t[1])(m_t[0]);
word16 constant = 0xFFFC;
word32 sequence = 0x9A42BB1F;
for (unsigned int i = 0; i < ROUNDS; ++i)
{
m_rk[i] = m_t[0];
constant &= 0xFFFC;
constant |= sequence & 1;
sequence >>= 1;
SIMECK_Encryption(static_cast<word16>(constant), m_t[1], m_t[0]);
// rotate the LFSR of m_t
m_t[4] = m_t[1];
m_t[1] = m_t[2];
m_t[2] = m_t[3];
m_t[3] = m_t[4];
}
}
void SIMECK32::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_t[1])(m_t[0]);
for (int idx = 0; idx < ROUNDS; ++idx)
SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
oblock(m_t[1])(m_t[0]);
}
void SIMECK32::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_t[0])(m_t[1]);
for (int idx = ROUNDS - 1; idx >= 0; --idx)
SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
oblock(m_t[0])(m_t[1]);
}
std::string SIMECK64::Base::AlgorithmProvider() const
{
return "C++";
}
void SIMECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs ¶ms)
{
CRYPTOPP_UNUSED(params);
CRYPTOPP_UNUSED(keyLength);
GetBlock<word32, BigEndian> kblock(userKey);
kblock(m_t[3])(m_t[2])(m_t[1])(m_t[0]);
word64 constant = W64LIT(0xFFFFFFFC);
word64 sequence = W64LIT(0x938BCA3083F);
for (unsigned int i = 0; i < ROUNDS; ++i)
{
m_rk[i] = m_t[0];
constant &= W64LIT(0xFFFFFFFC);
constant |= sequence & 1;
sequence >>= 1;
SIMECK_Encryption(static_cast<word32>(constant), m_t[1], m_t[0]);
// rotate the LFSR of m_t
m_t[4] = m_t[1];
m_t[1] = m_t[2];
m_t[2] = m_t[3];
m_t[3] = m_t[4];
}
}
void SIMECK64::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_t[1])(m_t[0]);
for (int idx = 0; idx < ROUNDS; ++idx)
SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
oblock(m_t[1])(m_t[0]);
}
void SIMECK64::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_t[0])(m_t[1]);
for (int idx = ROUNDS - 1; idx >= 0; --idx)
SIMECK_Encryption(m_rk[idx], m_t[1], m_t[0]);
PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
oblock(m_t[0])(m_t[1]);
}
NAMESPACE_END
|