2018-07-05 10:43:04 +00:00
|
|
|
// hc256.cpp - written and placed in the public domain by Jeffrey Walton
|
|
|
|
// based on public domain code by Hongjun Wu.
|
|
|
|
//
|
|
|
|
// The reference materials and source files are available at
|
|
|
|
// The eSTREAM Project, http://www.ecrypt.eu.org/stream/hc256.html.
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "hc256.h"
|
|
|
|
#include "secblock.h"
|
|
|
|
#include "misc.h"
|
|
|
|
|
|
|
|
ANONYMOUS_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
using CryptoPP::word32;
|
|
|
|
using CryptoPP::rotrConstant;
|
|
|
|
|
|
|
|
inline word32 f1(word32 x)
|
|
|
|
{
|
2018-07-05 11:11:44 +00:00
|
|
|
return rotrConstant<7>(x) ^ rotrConstant<18>(x) ^ (x >> 3);
|
2018-07-05 10:43:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline word32 f2(word32 x)
|
|
|
|
{
|
2018-07-05 11:11:44 +00:00
|
|
|
return rotrConstant<17>(x) ^ rotrConstant<19>(x) ^ (x >> 10);
|
2018-07-05 10:43:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ANONYMOUS_NAMESPACE_END
|
|
|
|
|
|
|
|
NAMESPACE_BEGIN(CryptoPP)
|
|
|
|
|
2018-07-05 11:11:44 +00:00
|
|
|
inline word32 HC256Policy::H1(word32 u)
|
2018-07-05 10:43:04 +00:00
|
|
|
{
|
|
|
|
word32 tem;
|
2018-07-05 11:11:44 +00:00
|
|
|
byte a, b, c, d;
|
2018-07-05 12:22:59 +00:00
|
|
|
a = (byte)(u);
|
|
|
|
b = (byte)(u >> 8);
|
|
|
|
c = (byte)(u >> 16);
|
|
|
|
d = (byte)(u >> 24);
|
2018-07-05 10:43:04 +00:00
|
|
|
tem = m_Q[a] + m_Q[256 + b] + m_Q[512 + c] + m_Q[768 + d];
|
|
|
|
return (tem);
|
|
|
|
}
|
|
|
|
|
2018-07-05 11:11:44 +00:00
|
|
|
inline word32 HC256Policy::H2(word32 u)
|
2018-07-05 10:43:04 +00:00
|
|
|
{
|
|
|
|
word32 tem;
|
2018-07-05 11:11:44 +00:00
|
|
|
byte a, b, c, d;
|
2018-07-05 12:22:59 +00:00
|
|
|
a = (byte)(u);
|
|
|
|
b = (byte)(u >> 8);
|
|
|
|
c = (byte)(u >> 16);
|
|
|
|
d = (byte)(u >> 24);
|
2018-07-05 10:43:04 +00:00
|
|
|
tem = m_P[a] + m_P[256 + b] + m_P[512 + c] + m_P[768 + d];
|
|
|
|
return (tem);
|
|
|
|
}
|
|
|
|
|
2018-07-05 11:11:44 +00:00
|
|
|
inline word32 HC256Policy::Generate() /*one step of the cipher*/
|
2018-07-05 10:43:04 +00:00
|
|
|
{
|
|
|
|
word32 i, i3, i10, i12, i1023;
|
|
|
|
word32 output;
|
|
|
|
|
|
|
|
i = m_ctr & 0x3ff;
|
|
|
|
i3 = (i - 3) & 0x3ff;
|
|
|
|
i10 = (i - 10) & 0x3ff;
|
|
|
|
i12 = (i - 12) & 0x3ff;
|
|
|
|
i1023 = (i - 1023) & 0x3ff;
|
|
|
|
|
|
|
|
if (m_ctr < 1024) {
|
|
|
|
m_P[i] = m_P[i] + m_P[i10] + (rotrConstant<10>(m_P[i3]) ^ rotrConstant<23>(m_P[i1023])) + m_Q[(m_P[i3] ^ m_P[i1023]) & 0x3ff];
|
|
|
|
output = H1(m_P[i12]) ^ m_P[i];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_Q[i] = m_Q[i] + m_Q[i10] + (rotrConstant<10>(m_Q[i3]) ^ rotrConstant<23>(m_Q[i1023])) + m_P[(m_Q[i3] ^ m_Q[i1023]) & 0x3ff];
|
|
|
|
output = H2(m_Q[i12]) ^ m_Q[i];
|
|
|
|
}
|
|
|
|
m_ctr = (m_ctr + 1) & 0x7ff;
|
|
|
|
return (output);
|
|
|
|
}
|
|
|
|
|
|
|
|
void HC256Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *userKey, size_t keylen)
|
|
|
|
{
|
|
|
|
CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(keylen);
|
|
|
|
CRYPTOPP_ASSERT(keylen == 32);
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < 8; i++)
|
|
|
|
m_key[i] = 0;
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < 32; i++)
|
|
|
|
{
|
|
|
|
m_key[i >> 2] = m_key[i >> 2] | userKey[i];
|
|
|
|
m_key[i >> 2] = rotlConstant<8>(m_key[i >> 2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HC256Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
|
|
|
|
{
|
2018-10-25 12:24:13 +00:00
|
|
|
while (iterationCount--)
|
|
|
|
{
|
|
|
|
PutWord(false, LITTLE_ENDIAN_ORDER, output + 0, Generate());
|
|
|
|
PutWord(false, LITTLE_ENDIAN_ORDER, output + 4, Generate());
|
|
|
|
PutWord(false, LITTLE_ENDIAN_ORDER, output + 8, Generate());
|
|
|
|
PutWord(false, LITTLE_ENDIAN_ORDER, output + 12, Generate());
|
|
|
|
|
|
|
|
// If AdditiveCipherTemplate does not have an accumulated keystream
|
|
|
|
// then it will ask OperateKeystream to generate one. Optionally it
|
|
|
|
// will ask for an XOR of the input with the keystream while
|
|
|
|
// writing the result to the output buffer. In all cases the
|
|
|
|
// keystream is written to the output buffer. The optional part is
|
|
|
|
// adding the input buffer and keystream.
|
|
|
|
if ((operation & INPUT_NULL) != INPUT_NULL)
|
|
|
|
{
|
|
|
|
xorbuf(output, input, BYTES_PER_ITERATION);
|
|
|
|
input += BYTES_PER_ITERATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
output += BYTES_PER_ITERATION;
|
|
|
|
}
|
2018-07-05 10:43:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void HC256Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
|
|
|
|
{
|
|
|
|
CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(length);
|
|
|
|
CRYPTOPP_ASSERT(length == 32);
|
|
|
|
|
|
|
|
/* initialize the iv */
|
|
|
|
word32 W[2560];
|
|
|
|
for (unsigned int i = 0; i < 8; i++)
|
|
|
|
m_iv[i] = 0;
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < 32; i++)
|
|
|
|
{
|
|
|
|
m_iv[i >> 2] = m_iv[i >> 2] | iv[i];
|
|
|
|
m_iv[i >> 2] = rotlConstant<8>(m_iv[i >> 2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* setup the table P and Q */
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < 8; i++)
|
|
|
|
W[i] = m_key[i];
|
|
|
|
for (unsigned int i = 8; i < 16; i++)
|
|
|
|
W[i] = m_iv[i - 8];
|
|
|
|
|
|
|
|
for (unsigned int i = 16; i < 2560; i++)
|
|
|
|
W[i] = f2(W[i - 2]) + W[i - 7] + f1(W[i - 15]) + W[i - 16] + i;
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < 1024; i++)
|
|
|
|
m_P[i] = W[i + 512];
|
|
|
|
for (unsigned int i = 0; i < 1024; i++)
|
|
|
|
m_Q[i] = W[i + 1536];
|
|
|
|
|
|
|
|
m_ctr = 0;
|
|
|
|
|
|
|
|
/* run the cipher 4096 steps before generating the output */
|
|
|
|
for (unsigned int i = 0; i < 4096; i++)
|
|
|
|
Generate();
|
|
|
|
}
|
|
|
|
|
|
|
|
NAMESPACE_END
|