Crypto++  8.8
Free C++ class library of cryptographic schemes
hc256.cpp
1 // hc256.cpp - written and placed in the public domain by Jeffrey Walton
2 // based on public domain code by Hongjun Wu.
3 //
4 // The reference materials and source files are available at
5 // The eSTREAM Project, http://www.ecrypt.eu.org/stream/hc256.html.
6 
7 #include "pch.h"
8 #include "config.h"
9 
10 #include "hc256.h"
11 #include "secblock.h"
12 #include "misc.h"
13 
14 ANONYMOUS_NAMESPACE_BEGIN
15 
16 using CryptoPP::word32;
18 
19 inline word32 f1(word32 x)
20 {
21  return rotrConstant<7>(x) ^ rotrConstant<18>(x) ^ (x >> 3);
22 }
23 
24 inline word32 f2(word32 x)
25 {
26  return rotrConstant<17>(x) ^ rotrConstant<19>(x) ^ (x >> 10);
27 }
28 
29 ANONYMOUS_NAMESPACE_END
30 
31 NAMESPACE_BEGIN(CryptoPP)
32 
33 inline word32 HC256Policy::H1(word32 u)
34 {
35  word32 tem;
36  byte a, b, c, d;
37  a = (byte)(u);
38  b = (byte)(u >> 8);
39  c = (byte)(u >> 16);
40  d = (byte)(u >> 24);
41  tem = m_Q[a] + m_Q[256 + b] + m_Q[512 + c] + m_Q[768 + d];
42  return (tem);
43 }
44 
45 inline word32 HC256Policy::H2(word32 u)
46 {
47  word32 tem;
48  byte a, b, c, d;
49  a = (byte)(u);
50  b = (byte)(u >> 8);
51  c = (byte)(u >> 16);
52  d = (byte)(u >> 24);
53  tem = m_P[a] + m_P[256 + b] + m_P[512 + c] + m_P[768 + d];
54  return (tem);
55 }
56 
57 inline word32 HC256Policy::Generate() /*one step of the cipher*/
58 {
59  word32 i, i3, i10, i12, i1023;
60  word32 output;
61 
62  i = m_ctr & 0x3ff;
63  i3 = (i - 3) & 0x3ff;
64  i10 = (i - 10) & 0x3ff;
65  i12 = (i - 12) & 0x3ff;
66  i1023 = (i - 1023) & 0x3ff;
67 
68  if (m_ctr < 1024) {
69  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];
70  output = H1(m_P[i12]) ^ m_P[i];
71  }
72  else {
73  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];
74  output = H2(m_Q[i12]) ^ m_Q[i];
75  }
76  m_ctr = (m_ctr + 1) & 0x7ff;
77  return (output);
78 }
79 
80 void HC256Policy::CipherSetKey(const NameValuePairs &params, const byte *userKey, size_t keylen)
81 {
82  CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(keylen);
83  CRYPTOPP_ASSERT(keylen == 32);
84 
85  for (unsigned int i = 0; i < 8; i++)
86  m_key[i] = 0;
87 
88  for (unsigned int i = 0; i < 32; i++)
89  {
90  m_key[i >> 2] = m_key[i >> 2] | userKey[i];
91  m_key[i >> 2] = rotlConstant<8>(m_key[i >> 2]);
92  }
93 }
94 
95 void HC256Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
96 {
97  while (iterationCount--)
98  {
99  PutWord(false, LITTLE_ENDIAN_ORDER, output + 0, Generate());
100  PutWord(false, LITTLE_ENDIAN_ORDER, output + 4, Generate());
101  PutWord(false, LITTLE_ENDIAN_ORDER, output + 8, Generate());
102  PutWord(false, LITTLE_ENDIAN_ORDER, output + 12, Generate());
103 
104  // If AdditiveCipherTemplate does not have an accumulated keystream
105  // then it will ask OperateKeystream to generate one. Optionally it
106  // will ask for an XOR of the input with the keystream while
107  // writing the result to the output buffer. In all cases the
108  // keystream is written to the output buffer. The optional part is
109  // adding the input buffer and keystream.
110  if ((operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL))
111  {
112  xorbuf(output, input, BYTES_PER_ITERATION);
113  input += BYTES_PER_ITERATION;
114  }
115 
116  output += BYTES_PER_ITERATION;
117  }
118 }
119 
120 void HC256Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
121 {
122  CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(length);
123  CRYPTOPP_ASSERT(length == 32);
124 
125  /* initialize the iv */
126  word32 W[2560];
127  for (unsigned int i = 0; i < 8; i++)
128  m_iv[i] = 0;
129 
130  for (unsigned int i = 0; i < 32; i++)
131  {
132  m_iv[i >> 2] = m_iv[i >> 2] | iv[i];
133  m_iv[i >> 2] = rotlConstant<8>(m_iv[i >> 2]);
134  }
135 
136  /* setup the table P and Q */
137 
138  for (unsigned int i = 0; i < 8; i++)
139  W[i] = m_key[i];
140  for (unsigned int i = 8; i < 16; i++)
141  W[i] = m_iv[i - 8];
142 
143  for (unsigned int i = 16; i < 2560; i++)
144  W[i] = f2(W[i - 2]) + W[i - 7] + f1(W[i - 15]) + W[i - 16] + i;
145 
146  for (unsigned int i = 0; i < 1024; i++)
147  m_P[i] = W[i + 512];
148  for (unsigned int i = 0; i < 1024; i++)
149  m_Q[i] = W[i + 1536];
150 
151  m_ctr = 0;
152 
153  /* run the cipher 4096 steps before generating the output */
154  for (unsigned int i = 0; i < 4096; i++)
155  Generate();
156 }
157 
158 NAMESPACE_END
Interface for retrieving values given their names.
Definition: cryptlib.h:327
Library configuration file.
unsigned char byte
8-bit unsigned datatype
Definition: config_int.h:66
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition: cryptlib.h:150
Classes for HC-256 stream cipher.
Utility functions for the Crypto++ library.
T rotrConstant(T x)
Performs a right rotate.
Definition: misc.h:1783
#define EnumToInt(v)
Integer value.
Definition: misc.h:504
void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock=NULL)
Access a block of memory.
Definition: misc.h:2948
CRYPTOPP_DLL void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Crypto++ library namespace.
Precompiled header file.
Classes and functions for secure memory allocations.
KeystreamOperation
Keystream operation flags.
Definition: strciphr.h:88
@ INPUT_NULL
Input buffer is NULL.
Definition: strciphr.h:82
static const int BYTES_PER_ITERATION
Number of bytes for an iteration.
Definition: strciphr.h:211
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68