summaryrefslogtreecommitdiff
path: root/hc256.cpp
diff options
context:
space:
mode:
authorJeffrey Walton <noloader@gmail.com>2018-07-05 06:43:04 -0400
committerJeffrey Walton <noloader@gmail.com>2018-07-05 06:43:04 -0400
commit989bf6dc5e333791d5e64916be0cd49d026a71c2 (patch)
treeef831cc7f5837317fd7047d3b31d8af3d462671b /hc256.cpp
parent069d85d3f872974a7ed383ad4c8ddadb80f26fa9 (diff)
downloadcryptopp-git-989bf6dc5e333791d5e64916be0cd49d026a71c2.tar.gz
Add HC-256 stream cipher (GH #680)
Diffstat (limited to 'hc256.cpp')
-rw-r--r--hc256.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/hc256.cpp b/hc256.cpp
new file mode 100644
index 00000000..ff75b2b2
--- /dev/null
+++ b/hc256.cpp
@@ -0,0 +1,148 @@
+// 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)
+{
+ 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)
+
+word32 HC256Policy::H1(word32 u)
+{
+ word32 tem;
+ unsigned char a, b, c, d;
+ a = (unsigned char)((u));
+ b = (unsigned char)((u) >> 8);
+ c = (unsigned char)((u) >> 16);
+ d = (unsigned char)((u) >> 24);
+ tem = m_Q[a] + m_Q[256 + b] + m_Q[512 + c] + m_Q[768 + d];
+ return (tem);
+}
+
+word32 HC256Policy::H2(word32 u)
+{
+ word32 tem;
+ unsigned char a, b, c, d;
+ a = (unsigned char)((u));
+ b = (unsigned char)((u) >> 8);
+ c = (unsigned char)((u) >> 16);
+ d = (unsigned char)((u) >> 24);
+ tem = m_P[a] + m_P[256 + b] + m_P[512 + c] + m_P[768 + d];
+ return (tem);
+}
+
+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::CipherSetKey(const NameValuePairs &params, 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)
+{
+ size_t msglen = (GetBytesPerIteration() * iterationCount) >> 2;
+ for (unsigned int i = 0; i < msglen; i++, input += 4, output += 4)
+ {
+ PutWord(false, LITTLE_ENDIAN_ORDER, output, Generate());
+
+ // If AdditiveCipherTemplate does not have an acculated keystream
+ // then it will ask OperateKeystream to XOR the plaintext with
+ // the keystream and write it to the ciphertext buffer.
+ if ((operation & INPUT_NULL) != INPUT_NULL)
+ xorbuf(output, input, 4);
+ }
+}
+
+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