Crypto++ 8.9 Free C++ class library of cryptographic schemes

hc128.cpp
1 // hc128.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/e2-hc128.html.
6
7 #include "pch.h"
8 #include "config.h"
9
10 #include "hc128.h"
11 #include "secblock.h"
12 #include "strciphr.h"
13 #include "misc.h"
14
15 /*h1 function*/
16 #define h1(x, y) { \
17 byte a,c; \
18 a = (byte) (x); \
19 c = (byte) ((x) >> 16); \
20 y = (m_T[512+a])+(m_T[512+256+c]); \
21 }
22
23 /*h2 function*/
24 #define h2(x, y) { \
25 byte a,c; \
26 a = (byte) (x); \
27 c = (byte) ((x) >> 16); \
28 y = (m_T[a])+(m_T[256+c]); \
29 }
30
31 /*one step of HC-128, update P and generate 32 bits keystream*/
32 #define step_P(u,v,a,b,c,d,n){ \
33 word32 tem0,tem1,tem2,tem3; \
34 h1(m_X[(d)],tem3); \
35 tem0 = rotrConstant<23>(m_T[(v)]); \
36 tem1 = rotrConstant<10>(m_X[(c)]); \
37 tem2 = rotrConstant<8>(m_X[(b)]); \
38 (m_T[(u)]) += tem2+(tem0 ^ tem1); \
39 (m_X[(a)]) = (m_T[(u)]); \
40 (n) = tem3 ^ (m_T[(u)]); \
41 }
42
43 /*one step of HC-128, update Q and generate 32 bits keystream*/
44 #define step_Q(u,v,a,b,c,d,n){ \
45 word32 tem0,tem1,tem2,tem3; \
46 h2(m_Y[(d)],tem3); \
47 tem0 = rotrConstant<(32-23)>(m_T[(v)]); \
48 tem1 = rotrConstant<(32-10)>(m_Y[(c)]); \
49 tem2 = rotrConstant<(32-8)>(m_Y[(b)]); \
50 (m_T[(u)]) += tem2 + (tem0 ^ tem1); \
51 (m_Y[(a)]) = (m_T[(u)]); \
52 (n) = tem3 ^ (m_T[(u)]) ; \
53 }
54
55 /*update table P*/
56 #define update_P(u,v,a,b,c,d){ \
57 word32 tem0,tem1,tem2,tem3; \
58 tem0 = rotrConstant<23>(m_T[(v)]); \
59 tem1 = rotrConstant<10>(m_X[(c)]); \
60 tem2 = rotrConstant<8>(m_X[(b)]); \
61 h1(m_X[(d)],tem3); \
62 (m_T[(u)]) = ((m_T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \
63 (m_X[(a)]) = (m_T[(u)]); \
64 }
65
66 /*update table Q*/
67 #define update_Q(u,v,a,b,c,d){ \
68 word32 tem0,tem1,tem2,tem3; \
69 tem0 = rotrConstant<(32-23)>(m_T[(v)]); \
70 tem1 = rotrConstant<(32-10)>(m_Y[(c)]); \
71 tem2 = rotrConstant<(32-8)>(m_Y[(b)]); \
72 h2(m_Y[(d)],tem3); \
73 (m_T[(u)]) = ((m_T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \
74 (m_Y[(a)]) = (m_T[(u)]); \
75 }
76
77 #define BYTES_PER_ITERATION 64
78
79 #define WordType word32
80
81 #define HC128_OUTPUT(x){\
82 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, keystream[ 0]);\
83 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, keystream[ 1]);\
84 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, keystream[ 2]);\
85 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, keystream[ 3]);\
86 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, keystream[ 4]);\
87 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, keystream[ 5]);\
88 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, keystream[ 6]);\
89 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, keystream[ 7]);\
90 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, keystream[ 8]);\
91 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, keystream[ 9]);\
92 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, keystream[10]);\
93 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, keystream[11]);\
94 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, keystream[12]);\
95 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, keystream[13]);\
96 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, keystream[14]);\
97 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, keystream[15]);}
98
99 ANONYMOUS_NAMESPACE_BEGIN
100
101 using CryptoPP::word32;
102 using CryptoPP::rotrConstant;
103
104 inline word32 f1(word32 x)
105 {
106 return rotrConstant<7>(x) ^ rotrConstant<18>(x) ^ ((x) >> 3);
107 }
108
109 inline word32 f2(word32 x)
110 {
111 return rotrConstant<17>(x) ^ rotrConstant<19>(x) ^ ((x) >> 10);
112 }
113
114 ANONYMOUS_NAMESPACE_END
115
116 NAMESPACE_BEGIN(CryptoPP)
117
118 /*16 steps of HC-128, generate 512 bits keystream*/
119 void HC128Policy::GenerateKeystream(word32 keystream[16])
120 {
121 unsigned int cc = m_ctr & 0x1ff;
122 unsigned int dd = (cc + 16) & 0x1ff;
123
124 if (m_ctr < 512)
125 {
126 m_ctr = (m_ctr + 16) & 0x3ff;
127 step_P(cc + 0, cc + 1, 0, 6, 13, 4, keystream[0]);
128 step_P(cc + 1, cc + 2, 1, 7, 14, 5, keystream[1]);
129 step_P(cc + 2, cc + 3, 2, 8, 15, 6, keystream[2]);
130 step_P(cc + 3, cc + 4, 3, 9, 0, 7, keystream[3]);
131 step_P(cc + 4, cc + 5, 4, 10, 1, 8, keystream[4]);
132 step_P(cc + 5, cc + 6, 5, 11, 2, 9, keystream[5]);
133 step_P(cc + 6, cc + 7, 6, 12, 3, 10, keystream[6]);
134 step_P(cc + 7, cc + 8, 7, 13, 4, 11, keystream[7]);
135 step_P(cc + 8, cc + 9, 8, 14, 5, 12, keystream[8]);
136 step_P(cc + 9, cc + 10, 9, 15, 6, 13, keystream[9]);
137 step_P(cc + 10, cc + 11, 10, 0, 7, 14, keystream[10]);
138 step_P(cc + 11, cc + 12, 11, 1, 8, 15, keystream[11]);
139 step_P(cc + 12, cc + 13, 12, 2, 9, 0, keystream[12]);
140 step_P(cc + 13, cc + 14, 13, 3, 10, 1, keystream[13]);
141 step_P(cc + 14, cc + 15, 14, 4, 11, 2, keystream[14]);
142 step_P(cc + 15, dd + 0, 15, 5, 12, 3, keystream[15]);
143 }
144 else
145 {
146 m_ctr = (m_ctr + 16) & 0x3ff;
147 step_Q(512 + cc + 0, 512 + cc + 1, 0, 6, 13, 4, keystream[0]);
148 step_Q(512 + cc + 1, 512 + cc + 2, 1, 7, 14, 5, keystream[1]);
149 step_Q(512 + cc + 2, 512 + cc + 3, 2, 8, 15, 6, keystream[2]);
150 step_Q(512 + cc + 3, 512 + cc + 4, 3, 9, 0, 7, keystream[3]);
151 step_Q(512 + cc + 4, 512 + cc + 5, 4, 10, 1, 8, keystream[4]);
152 step_Q(512 + cc + 5, 512 + cc + 6, 5, 11, 2, 9, keystream[5]);
153 step_Q(512 + cc + 6, 512 + cc + 7, 6, 12, 3, 10, keystream[6]);
154 step_Q(512 + cc + 7, 512 + cc + 8, 7, 13, 4, 11, keystream[7]);
155 step_Q(512 + cc + 8, 512 + cc + 9, 8, 14, 5, 12, keystream[8]);
156 step_Q(512 + cc + 9, 512 + cc + 10, 9, 15, 6, 13, keystream[9]);
157 step_Q(512 + cc + 10, 512 + cc + 11, 10, 0, 7, 14, keystream[10]);
158 step_Q(512 + cc + 11, 512 + cc + 12, 11, 1, 8, 15, keystream[11]);
159 step_Q(512 + cc + 12, 512 + cc + 13, 12, 2, 9, 0, keystream[12]);
160 step_Q(512 + cc + 13, 512 + cc + 14, 13, 3, 10, 1, keystream[13]);
161 step_Q(512 + cc + 14, 512 + cc + 15, 14, 4, 11, 2, keystream[14]);
162 step_Q(512 + cc + 15, 512 + dd + 0, 15, 5, 12, 3, keystream[15]);
163 }
164 }
165
166 /*16 steps of HC-128, without generating keystream, */
167 /*but use the outputs to update P and Q*/
168 void HC128Policy::SetupUpdate() /*each time 16 steps*/
169 {
170 unsigned int cc = m_ctr & 0x1ff;
171 unsigned int dd = (cc + 16) & 0x1ff;
172
173 if (m_ctr < 512)
174 {
175 m_ctr = (m_ctr + 16) & 0x3ff;
176 update_P(cc + 0, cc + 1, 0, 6, 13, 4);
177 update_P(cc + 1, cc + 2, 1, 7, 14, 5);
178 update_P(cc + 2, cc + 3, 2, 8, 15, 6);
179 update_P(cc + 3, cc + 4, 3, 9, 0, 7);
180 update_P(cc + 4, cc + 5, 4, 10, 1, 8);
181 update_P(cc + 5, cc + 6, 5, 11, 2, 9);
182 update_P(cc + 6, cc + 7, 6, 12, 3, 10);
183 update_P(cc + 7, cc + 8, 7, 13, 4, 11);
184 update_P(cc + 8, cc + 9, 8, 14, 5, 12);
185 update_P(cc + 9, cc + 10, 9, 15, 6, 13);
186 update_P(cc + 10, cc + 11, 10, 0, 7, 14);
187 update_P(cc + 11, cc + 12, 11, 1, 8, 15);
188 update_P(cc + 12, cc + 13, 12, 2, 9, 0);
189 update_P(cc + 13, cc + 14, 13, 3, 10, 1);
190 update_P(cc + 14, cc + 15, 14, 4, 11, 2);
191 update_P(cc + 15, dd + 0, 15, 5, 12, 3);
192 }
193 else
194 {
195 m_ctr = (m_ctr + 16) & 0x3ff;
196 update_Q(512 + cc + 0, 512 + cc + 1, 0, 6, 13, 4);
197 update_Q(512 + cc + 1, 512 + cc + 2, 1, 7, 14, 5);
198 update_Q(512 + cc + 2, 512 + cc + 3, 2, 8, 15, 6);
199 update_Q(512 + cc + 3, 512 + cc + 4, 3, 9, 0, 7);
200 update_Q(512 + cc + 4, 512 + cc + 5, 4, 10, 1, 8);
201 update_Q(512 + cc + 5, 512 + cc + 6, 5, 11, 2, 9);
202 update_Q(512 + cc + 6, 512 + cc + 7, 6, 12, 3, 10);
203 update_Q(512 + cc + 7, 512 + cc + 8, 7, 13, 4, 11);
204 update_Q(512 + cc + 8, 512 + cc + 9, 8, 14, 5, 12);
205 update_Q(512 + cc + 9, 512 + cc + 10, 9, 15, 6, 13);
206 update_Q(512 + cc + 10, 512 + cc + 11, 10, 0, 7, 14);
207 update_Q(512 + cc + 11, 512 + cc + 12, 11, 1, 8, 15);
208 update_Q(512 + cc + 12, 512 + cc + 13, 12, 2, 9, 0);
209 update_Q(512 + cc + 13, 512 + cc + 14, 13, 3, 10, 1);
210 update_Q(512 + cc + 14, 512 + cc + 15, 14, 4, 11, 2);
211 update_Q(512 + cc + 15, 512 + dd + 0, 15, 5, 12, 3);
212 }
213 }
214
215 void HC128Policy::CipherSetKey(const NameValuePairs &params, const byte *userKey, size_t keylen)
216 {
217 CRYPTOPP_UNUSED(params);
218
219 GetUserKey(LITTLE_ENDIAN_ORDER, m_key.begin(), 4, userKey, keylen);
220 for (unsigned int i = 4; i < 8; i++)
221 m_key[i] = m_key[i - 4];
222 }
223
224 void HC128Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
225 {
226 while (iterationCount--)
227 {
228 FixedSizeSecBlock<word32, 16> keystream;
229 GenerateKeystream(keystream);
230
231 CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(HC128_OUTPUT, BYTES_PER_ITERATION);
232 }
233 }
234
235 void HC128Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
236 {
237 CRYPTOPP_UNUSED(keystreamBuffer);
238
239 GetUserKey(LITTLE_ENDIAN_ORDER, m_iv.begin(), 4, iv, length);
240 for (unsigned int i = 4; i < 8; i++)
241 m_iv[i] = m_iv[i - 4];
242
243 /* expand the key and IV into the table T */
244 /* (expand the key and IV into the table P and Q) */
245
246 for (unsigned int i = 0; i < 8; i++)
247 m_T[i] = m_key[i];
248 for (unsigned int i = 8; i < 16; i++)
249 m_T[i] = m_iv[i - 8];
250
251 for (unsigned int i = 16; i < (256 + 16); i++)
252 m_T[i] = f2(m_T[i - 2]) + m_T[i - 7] + f1(m_T[i - 15]) + m_T[i - 16] + i;
253
254 for (unsigned int i = 0; i < 16; i++)
255 m_T[i] = m_T[256 + i];
256
257 for (unsigned int i = 16; i < 1024; i++)
258 m_T[i] = f2(m_T[i - 2]) + m_T[i - 7] + f1(m_T[i - 15]) + m_T[i - 16] + 256 + i;
259
260 /* initialize counter1024, X and Y */
261 m_ctr = 0;
262 for (unsigned int i = 0; i < 16; i++)
263 m_X[i] = m_T[512 - 16 + i];
264 for (unsigned int i = 0; i < 16; i++)
265 m_Y[i] = m_T[512 + 512 - 16 + i];
266
267 /* run the cipher 1024 steps before generating the output */
268 for (unsigned int i = 0; i < 64; i++)
269 SetupUpdate();
270 }
271
272 NAMESPACE_END
FixedSizeSecBlock< word32, 16 >
NameValuePairs
Interface for retrieving values given their names.
Definition: cryptlib.h:327
SecBlock::begin
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:836
config.h
Library configuration file.
word32
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
LITTLE_ENDIAN_ORDER
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition: cryptlib.h:150
hc128.h
Classes for HC-128 stream cipher.
misc.h
Utility functions for the Crypto++ library.
rotrConstant
T rotrConstant(T x)
Performs a right rotate.
Definition: misc.h:1783
GetUserKey
void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
Copy bytes in a buffer to an array of elements in big-endian order.
Definition: misc.h:2500
CryptoPP
Crypto++ library namespace.
pch.h
Precompiled header file.
secblock.h
Classes and functions for secure memory allocations.
strciphr.h
Classes for implementing stream ciphers.
CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH
#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y)
Helper macro to implement OperateKeystream.
Definition: strciphr.h:266
KeystreamOperation
KeystreamOperation
Keystream operation flags.
Definition: strciphr.h:88
AdditiveCipherConcretePolicy< word32, 16 >::BYTES_PER_ITERATION
static const int BYTES_PER_ITERATION
Number of bytes for an iteration.
Definition: strciphr.h:211