20 #include "runtime.hpp"
30 #ifdef BIG_ENDIAN_ORDER
31 #define LITTLE32(x) ByteReverse((word32)x)
33 #define LITTLE32(x) (x)
41 c = (byte) ((x) >> 16); \
42 y = (T_[512+a])+(T_[512+256+c]); \
49 c = (byte) ((x) >> 16); \
50 y = (T_[a])+(T_[256+c]); \
54 #define step_P(u,v,a,b,c,d,n){ \
55 word32 tem0,tem1,tem2,tem3; \
57 tem0 = rotrFixed((T_[(v)]),23); \
58 tem1 = rotrFixed((X_[(c)]),10); \
59 tem2 = rotrFixed((X_[(b)]),8); \
60 (T_[(u)]) += tem2+(tem0 ^ tem1); \
61 (X_[(a)]) = (T_[(u)]); \
62 (n) = tem3 ^ (T_[(u)]) ; \
66 #define step_Q(u,v,a,b,c,d,n){ \
67 word32 tem0,tem1,tem2,tem3; \
69 tem0 = rotrFixed((T_[(v)]),(32-23)); \
70 tem1 = rotrFixed((Y_[(c)]),(32-10)); \
71 tem2 = rotrFixed((Y_[(b)]),(32-8)); \
72 (T_[(u)]) += tem2 + (tem0 ^ tem1); \
73 (Y_[(a)]) = (T_[(u)]); \
74 (n) = tem3 ^ (T_[(u)]) ; \
79 void HC128::GenerateKeystream(word32* keystream)
82 cc = counter1024_ & 0x1ff;
85 if (counter1024_ < 512)
87 counter1024_ = (counter1024_ + 16) & 0x3ff;
88 step_P(cc+0, cc+1, 0, 6, 13,4, keystream[0]);
89 step_P(cc+1, cc+2, 1, 7, 14,5, keystream[1]);
90 step_P(cc+2, cc+3, 2, 8, 15,6, keystream[2]);
91 step_P(cc+3, cc+4, 3, 9, 0, 7, keystream[3]);
92 step_P(cc+4, cc+5, 4, 10,1, 8, keystream[4]);
93 step_P(cc+5, cc+6, 5, 11,2, 9, keystream[5]);
94 step_P(cc+6, cc+7, 6, 12,3, 10,keystream[6]);
95 step_P(cc+7, cc+8, 7, 13,4, 11,keystream[7]);
96 step_P(cc+8, cc+9, 8, 14,5, 12,keystream[8]);
97 step_P(cc+9, cc+10,9, 15,6, 13,keystream[9]);
98 step_P(cc+10,cc+11,10,0, 7, 14,keystream[10]);
99 step_P(cc+11,cc+12,11,1, 8, 15,keystream[11]);
100 step_P(cc+12,cc+13,12,2, 9, 0, keystream[12]);
101 step_P(cc+13,cc+14,13,3, 10,1, keystream[13]);
102 step_P(cc+14,cc+15,14,4, 11,2, keystream[14]);
103 step_P(cc+15,dd+0, 15,5, 12,3, keystream[15]);
107 counter1024_ = (counter1024_ + 16) & 0x3ff;
108 step_Q(512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]);
109 step_Q(512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]);
110 step_Q(512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]);
111 step_Q(512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]);
112 step_Q(512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]);
113 step_Q(512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]);
114 step_Q(512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]);
115 step_Q(512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]);
116 step_Q(512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]);
117 step_Q(512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]);
118 step_Q(512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]);
119 step_Q(512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]);
120 step_Q(512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]);
121 step_Q(512+cc+13,512+cc+14,13,3, 10,1, keystream[13]);
122 step_Q(512+cc+14,512+cc+15,14,4, 11,2, keystream[14]);
123 step_Q(512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]);
129 #define f1(x) (rotrFixed((x),7) ^ rotrFixed((x),18) ^ ((x) >> 3))
130 #define f2(x) (rotrFixed((x),17) ^ rotrFixed((x),19) ^ ((x) >> 10))
133 #define update_P(u,v,a,b,c,d){ \
134 word32 tem0,tem1,tem2,tem3; \
135 tem0 = rotrFixed((T_[(v)]),23); \
136 tem1 = rotrFixed((X_[(c)]),10); \
137 tem2 = rotrFixed((X_[(b)]),8); \
138 h1((X_[(d)]),tem3); \
139 (T_[(u)]) = ((T_[(u)]) + tem2+(tem0^tem1)) ^ tem3; \
140 (X_[(a)]) = (T_[(u)]); \
144 #define update_Q(u,v,a,b,c,d){ \
145 word32 tem0,tem1,tem2,tem3; \
146 tem0 = rotrFixed((T_[(v)]),(32-23)); \
147 tem1 = rotrFixed((Y_[(c)]),(32-10)); \
148 tem2 = rotrFixed((Y_[(b)]),(32-8)); \
149 h2((Y_[(d)]),tem3); \
150 (T_[(u)]) = ((T_[(u)]) + tem2+(tem0^tem1)) ^ tem3; \
151 (Y_[(a)]) = (T_[(u)]); \
156 void HC128::SetupUpdate()
159 cc = counter1024_ & 0x1ff;
162 if (counter1024_ < 512)
164 counter1024_ = (counter1024_ + 16) & 0x3ff;
165 update_P(cc+0, cc+1, 0, 6, 13, 4);
166 update_P(cc+1, cc+2, 1, 7, 14, 5);
167 update_P(cc+2, cc+3, 2, 8, 15, 6);
168 update_P(cc+3, cc+4, 3, 9, 0, 7);
169 update_P(cc+4, cc+5, 4, 10,1, 8);
170 update_P(cc+5, cc+6, 5, 11,2, 9);
171 update_P(cc+6, cc+7, 6, 12,3, 10);
172 update_P(cc+7, cc+8, 7, 13,4, 11);
173 update_P(cc+8, cc+9, 8, 14,5, 12);
174 update_P(cc+9, cc+10,9, 15,6, 13);
175 update_P(cc+10,cc+11,10,0, 7, 14);
176 update_P(cc+11,cc+12,11,1, 8, 15);
177 update_P(cc+12,cc+13,12,2, 9, 0);
178 update_P(cc+13,cc+14,13,3, 10, 1);
179 update_P(cc+14,cc+15,14,4, 11, 2);
180 update_P(cc+15,dd+0, 15,5, 12, 3);
184 counter1024_ = (counter1024_ + 16) & 0x3ff;
185 update_Q(512+cc+0, 512+cc+1, 0, 6, 13, 4);
186 update_Q(512+cc+1, 512+cc+2, 1, 7, 14, 5);
187 update_Q(512+cc+2, 512+cc+3, 2, 8, 15, 6);
188 update_Q(512+cc+3, 512+cc+4, 3, 9, 0, 7);
189 update_Q(512+cc+4, 512+cc+5, 4, 10,1, 8);
190 update_Q(512+cc+5, 512+cc+6, 5, 11,2, 9);
191 update_Q(512+cc+6, 512+cc+7, 6, 12,3, 10);
192 update_Q(512+cc+7, 512+cc+8, 7, 13,4, 11);
193 update_Q(512+cc+8, 512+cc+9, 8, 14,5, 12);
194 update_Q(512+cc+9, 512+cc+10,9, 15,6, 13);
195 update_Q(512+cc+10,512+cc+11,10,0, 7, 14);
196 update_Q(512+cc+11,512+cc+12,11,1, 8, 15);
197 update_Q(512+cc+12,512+cc+13,12,2, 9, 0);
198 update_Q(512+cc+13,512+cc+14,13,3, 10, 1);
199 update_Q(512+cc+14,512+cc+15,14,4, 11, 2);
200 update_Q(512+cc+15,512+dd+0, 15,5, 12, 3);
222 void HC128::SetIV(
const byte* iv)
226 for (i = 0; i < (128 >> 5); i++)
227 iv_[i] = LITTLE32(((word32*)iv)[
i]);
229 for (; i < 8; i++) iv_[i] = iv_[i-4];
234 for (i = 0; i < 8; i++) T_[i] = key_[i];
235 for (i = 8; i < 16; i++) T_[i] = iv_[i-8];
237 for (i = 16; i < (256+16); i++)
238 T_[i] = f2(T_[i-2]) + T_[i-7] + f1(T_[i-15]) + T_[i-16]+
i;
240 for (i = 0; i < 16; i++) T_[i] = T_[256+i];
242 for (i = 16; i < 1024; i++)
243 T_[i] = f2(T_[i-2]) + T_[i-7] + f1(T_[i-15]) + T_[i-16]+256+
i;
247 for (i = 0; i < 16; i++) X_[i] = T_[512-16+i];
248 for (i = 0; i < 16; i++) Y_[i] = T_[512+512-16+i];
251 for (i = 0; i < 64; i++) SetupUpdate();
255 void HC128::SetKey(
const byte* key,
const byte* iv)
260 for (i = 0; i < (128 >> 5); i++)
261 key_[i] = LITTLE32(((word32*)key)[
i]);
263 for ( ; i < 8 ; i++) key_[i] = key_[i-4];
270 void HC128::Process(byte* output,
const byte* input, word32 msglen)
272 word32
i, keystream[16];
274 for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64)
276 GenerateKeystream(keystream);
279 ((word32*)output)[0] = ((word32*)input)[0] ^ LITTLE32(keystream[0]);
280 ((word32*)output)[1] = ((word32*)input)[1] ^ LITTLE32(keystream[1]);
281 ((word32*)output)[2] = ((word32*)input)[2] ^ LITTLE32(keystream[2]);
282 ((word32*)output)[3] = ((word32*)input)[3] ^ LITTLE32(keystream[3]);
283 ((word32*)output)[4] = ((word32*)input)[4] ^ LITTLE32(keystream[4]);
284 ((word32*)output)[5] = ((word32*)input)[5] ^ LITTLE32(keystream[5]);
285 ((word32*)output)[6] = ((word32*)input)[6] ^ LITTLE32(keystream[6]);
286 ((word32*)output)[7] = ((word32*)input)[7] ^ LITTLE32(keystream[7]);
287 ((word32*)output)[8] = ((word32*)input)[8] ^ LITTLE32(keystream[8]);
288 ((word32*)output)[9] = ((word32*)input)[9] ^ LITTLE32(keystream[9]);
289 ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]);
290 ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]);
291 ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]);
292 ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]);
293 ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]);
294 ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]);
299 GenerateKeystream(keystream);
301 #ifdef BIG_ENDIAN_ORDER
303 word32 wordsLeft = msglen /
sizeof(word32);
304 if (msglen %
sizeof(word32)) wordsLeft++;
306 ByteReverse(keystream, keystream, wordsLeft *
sizeof(word32));
310 for (i = 0; i < msglen; i++)
311 output[i] = input[i] ^ ((byte*)keystream)[
i];