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 155 156 157 158 159 160 161 162 163
|
// 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 "strciphr.h"
#include "misc.h"
#define BYTES_PER_ITERATION 16
#define WordType word32
#define HC256_OUTPUT(x){\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, keystream[0]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, keystream[1]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, keystream[2]);\
CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, keystream[3]);}
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::word32;
using CryptoPP::rotrConstant;
inline word32 f1(word32 x)
{
return rotrConstant<7>(x) ^ rotrConstant<18>(x) ^ (x >> 3);
}
inline word32 f2(word32 x)
{
return rotrConstant<17>(x) ^ rotrConstant<19>(x) ^ (x >> 10);
}
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
inline word32 HC256Policy::H1(word32 u)
{
word32 tem;
byte a, b, c, d;
a = (byte)(u);
b = (byte)(u >> 8);
c = (byte)(u >> 16);
d = (byte)(u >> 24);
tem = m_Q[a] + m_Q[256 + b] + m_Q[512 + c] + m_Q[768 + d];
return (tem);
}
inline word32 HC256Policy::H2(word32 u)
{
word32 tem;
byte a, b, c, d;
a = (byte)(u);
b = (byte)(u >> 8);
c = (byte)(u >> 16);
d = (byte)(u >> 24);
tem = m_P[a] + m_P[256 + b] + m_P[512 + c] + m_P[768 + d];
return (tem);
}
inline word32 HC256Policy::Generate() /*one step of the cipher*/
{
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::GenerateKeystream(word32 keystream[4])
{
keystream[0] = Generate();
keystream[1] = Generate();
keystream[2] = Generate();
keystream[3] = Generate();
}
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)
{
while (iterationCount--)
{
FixedSizeSecBlock<word32, 4> keystream;
GenerateKeystream(keystream);
CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(HC256_OUTPUT, BYTES_PER_ITERATION);
}
}
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
|