3 * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
5 * This file is part of CyaSSL.
7 * CyaSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * CyaSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
28 #include <cyassl/ctaocrypt/hc128.h>
30 #include <cyassl/ctaocrypt/hc128.h>
32 #include <ctaocrypt/src/misc.c>
36 #ifdef BIG_ENDIAN_ORDER
37 #define LITTLE32(x) ByteReverseWord32(x)
39 #define LITTLE32(x) (x)
44 #define h1(ctx, x, y) { \
47 c = (byte) ((x) >> 16); \
48 y = (ctx->T[512+a])+(ctx->T[512+256+c]); \
52 #define h2(ctx, x, y) { \
55 c = (byte) ((x) >> 16); \
56 y = (ctx->T[a])+(ctx->T[256+c]); \
59 /*one step of HC-128, update P and generate 32 bits keystream*/
60 #define step_P(ctx,u,v,a,b,c,d,n){ \
61 word32 tem0,tem1,tem2,tem3; \
62 h1((ctx),(ctx->X[(d)]),tem3); \
63 tem0 = rotrFixed((ctx->T[(v)]),23); \
64 tem1 = rotrFixed((ctx->X[(c)]),10); \
65 tem2 = rotrFixed((ctx->X[(b)]),8); \
66 (ctx->T[(u)]) += tem2+(tem0 ^ tem1); \
67 (ctx->X[(a)]) = (ctx->T[(u)]); \
68 (n) = tem3 ^ (ctx->T[(u)]) ; \
71 /*one step of HC-128, update Q and generate 32 bits keystream*/
72 #define step_Q(ctx,u,v,a,b,c,d,n){ \
73 word32 tem0,tem1,tem2,tem3; \
74 h2((ctx),(ctx->Y[(d)]),tem3); \
75 tem0 = rotrFixed((ctx->T[(v)]),(32-23)); \
76 tem1 = rotrFixed((ctx->Y[(c)]),(32-10)); \
77 tem2 = rotrFixed((ctx->Y[(b)]),(32-8)); \
78 (ctx->T[(u)]) += tem2 + (tem0 ^ tem1); \
79 (ctx->Y[(a)]) = (ctx->T[(u)]); \
80 (n) = tem3 ^ (ctx->T[(u)]) ; \
83 /*16 steps of HC-128, generate 512 bits keystream*/
84 static void generate_keystream(HC128* ctx, word32* keystream)
87 cc = ctx->counter1024 & 0x1ff;
90 if (ctx->counter1024 < 512)
92 ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
93 step_P(ctx, cc+0, cc+1, 0, 6, 13,4, keystream[0]);
94 step_P(ctx, cc+1, cc+2, 1, 7, 14,5, keystream[1]);
95 step_P(ctx, cc+2, cc+3, 2, 8, 15,6, keystream[2]);
96 step_P(ctx, cc+3, cc+4, 3, 9, 0, 7, keystream[3]);
97 step_P(ctx, cc+4, cc+5, 4, 10,1, 8, keystream[4]);
98 step_P(ctx, cc+5, cc+6, 5, 11,2, 9, keystream[5]);
99 step_P(ctx, cc+6, cc+7, 6, 12,3, 10,keystream[6]);
100 step_P(ctx, cc+7, cc+8, 7, 13,4, 11,keystream[7]);
101 step_P(ctx, cc+8, cc+9, 8, 14,5, 12,keystream[8]);
102 step_P(ctx, cc+9, cc+10,9, 15,6, 13,keystream[9]);
103 step_P(ctx, cc+10,cc+11,10,0, 7, 14,keystream[10]);
104 step_P(ctx, cc+11,cc+12,11,1, 8, 15,keystream[11]);
105 step_P(ctx, cc+12,cc+13,12,2, 9, 0, keystream[12]);
106 step_P(ctx, cc+13,cc+14,13,3, 10,1, keystream[13]);
107 step_P(ctx, cc+14,cc+15,14,4, 11,2, keystream[14]);
108 step_P(ctx, cc+15,dd+0, 15,5, 12,3, keystream[15]);
112 ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
113 step_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]);
114 step_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]);
115 step_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]);
116 step_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]);
117 step_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]);
118 step_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]);
119 step_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]);
120 step_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]);
121 step_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]);
122 step_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]);
123 step_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]);
124 step_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]);
125 step_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]);
126 step_Q(ctx, 512+cc+13,512+cc+14,13,3, 10,1, keystream[13]);
127 step_Q(ctx, 512+cc+14,512+cc+15,14,4, 11,2, keystream[14]);
128 step_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]);
133 /* The following defines the initialization functions */
134 #define f1(x) (rotrFixed((x),7) ^ rotrFixed((x),18) ^ ((x) >> 3))
135 #define f2(x) (rotrFixed((x),17) ^ rotrFixed((x),19) ^ ((x) >> 10))
138 #define update_P(ctx,u,v,a,b,c,d){ \
139 word32 tem0,tem1,tem2,tem3; \
140 tem0 = rotrFixed((ctx->T[(v)]),23); \
141 tem1 = rotrFixed((ctx->X[(c)]),10); \
142 tem2 = rotrFixed((ctx->X[(b)]),8); \
143 h1((ctx),(ctx->X[(d)]),tem3); \
144 (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \
145 (ctx->X[(a)]) = (ctx->T[(u)]); \
149 #define update_Q(ctx,u,v,a,b,c,d){ \
150 word32 tem0,tem1,tem2,tem3; \
151 tem0 = rotrFixed((ctx->T[(v)]),(32-23)); \
152 tem1 = rotrFixed((ctx->Y[(c)]),(32-10)); \
153 tem2 = rotrFixed((ctx->Y[(b)]),(32-8)); \
154 h2((ctx),(ctx->Y[(d)]),tem3); \
155 (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \
156 (ctx->Y[(a)]) = (ctx->T[(u)]); \
159 /*16 steps of HC-128, without generating keystream, */
160 /*but use the outputs to update P and Q*/
161 static void setup_update(HC128* ctx) /*each time 16 steps*/
164 cc = ctx->counter1024 & 0x1ff;
167 if (ctx->counter1024 < 512)
169 ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
170 update_P(ctx, cc+0, cc+1, 0, 6, 13, 4);
171 update_P(ctx, cc+1, cc+2, 1, 7, 14, 5);
172 update_P(ctx, cc+2, cc+3, 2, 8, 15, 6);
173 update_P(ctx, cc+3, cc+4, 3, 9, 0, 7);
174 update_P(ctx, cc+4, cc+5, 4, 10,1, 8);
175 update_P(ctx, cc+5, cc+6, 5, 11,2, 9);
176 update_P(ctx, cc+6, cc+7, 6, 12,3, 10);
177 update_P(ctx, cc+7, cc+8, 7, 13,4, 11);
178 update_P(ctx, cc+8, cc+9, 8, 14,5, 12);
179 update_P(ctx, cc+9, cc+10,9, 15,6, 13);
180 update_P(ctx, cc+10,cc+11,10,0, 7, 14);
181 update_P(ctx, cc+11,cc+12,11,1, 8, 15);
182 update_P(ctx, cc+12,cc+13,12,2, 9, 0);
183 update_P(ctx, cc+13,cc+14,13,3, 10, 1);
184 update_P(ctx, cc+14,cc+15,14,4, 11, 2);
185 update_P(ctx, cc+15,dd+0, 15,5, 12, 3);
189 ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff;
190 update_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13, 4);
191 update_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14, 5);
192 update_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15, 6);
193 update_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7);
194 update_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8);
195 update_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9);
196 update_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10);
197 update_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11);
198 update_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12);
199 update_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13);
200 update_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14);
201 update_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15);
202 update_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0);
203 update_Q(ctx, 512+cc+13,512+cc+14,13,3, 10, 1);
204 update_Q(ctx, 512+cc+14,512+cc+15,14,4, 11, 2);
205 update_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12, 3);
210 /* for the 128-bit key: key[0]...key[15]
211 * key[0] is the least significant byte of ctx->key[0] (K_0);
212 * key[3] is the most significant byte of ctx->key[0] (K_0);
214 * key[12] is the least significant byte of ctx->key[3] (K_3)
215 * key[15] is the most significant byte of ctx->key[3] (K_3)
217 * for the 128-bit iv: iv[0]...iv[15]
218 * iv[0] is the least significant byte of ctx->iv[0] (IV_0);
219 * iv[3] is the most significant byte of ctx->iv[0] (IV_0);
221 * iv[12] is the least significant byte of ctx->iv[3] (IV_3)
222 * iv[15] is the most significant byte of ctx->iv[3] (IV_3)
227 static void Hc128_SetIV(HC128* ctx, const byte* iv)
231 for (i = 0; i < (128 >> 5); i++)
232 ctx->iv[i] = LITTLE32(((word32*)iv)[i]);
234 for (; i < 8; i++) ctx->iv[i] = ctx->iv[i-4];
236 /* expand the key and IV into the table T */
237 /* (expand the key and IV into the table P and Q) */
239 for (i = 0; i < 8; i++) ctx->T[i] = ctx->key[i];
240 for (i = 8; i < 16; i++) ctx->T[i] = ctx->iv[i-8];
242 for (i = 16; i < (256+16); i++)
243 ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) +
246 for (i = 0; i < 16; i++) ctx->T[i] = ctx->T[256+i];
248 for (i = 16; i < 1024; i++)
249 ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) +
252 /* initialize counter1024, X and Y */
253 ctx->counter1024 = 0;
254 for (i = 0; i < 16; i++) ctx->X[i] = ctx->T[512-16+i];
255 for (i = 0; i < 16; i++) ctx->Y[i] = ctx->T[512+512-16+i];
257 /* run the cipher 1024 steps before generating the output */
258 for (i = 0; i < 64; i++) setup_update(ctx);
262 void Hc128_SetKey(HC128* ctx, const byte* key, const byte* iv)
266 /* Key size in bits 128 */
267 for (i = 0; i < (128 >> 5); i++)
268 ctx->key[i] = LITTLE32(((word32*)key)[i]);
270 for ( ; i < 8 ; i++) ctx->key[i] = ctx->key[i-4];
272 Hc128_SetIV(ctx, iv);
276 /* The following defines the encryption of data stream */
277 void Hc128_Process(HC128* ctx, byte* output, const byte* input, word32 msglen)
279 word32 i, keystream[16];
281 for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64)
283 generate_keystream(ctx, keystream);
286 ((word32*)output)[0] = ((word32*)input)[0] ^ LITTLE32(keystream[0]);
287 ((word32*)output)[1] = ((word32*)input)[1] ^ LITTLE32(keystream[1]);
288 ((word32*)output)[2] = ((word32*)input)[2] ^ LITTLE32(keystream[2]);
289 ((word32*)output)[3] = ((word32*)input)[3] ^ LITTLE32(keystream[3]);
290 ((word32*)output)[4] = ((word32*)input)[4] ^ LITTLE32(keystream[4]);
291 ((word32*)output)[5] = ((word32*)input)[5] ^ LITTLE32(keystream[5]);
292 ((word32*)output)[6] = ((word32*)input)[6] ^ LITTLE32(keystream[6]);
293 ((word32*)output)[7] = ((word32*)input)[7] ^ LITTLE32(keystream[7]);
294 ((word32*)output)[8] = ((word32*)input)[8] ^ LITTLE32(keystream[8]);
295 ((word32*)output)[9] = ((word32*)input)[9] ^ LITTLE32(keystream[9]);
296 ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]);
297 ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]);
298 ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]);
299 ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]);
300 ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]);
301 ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]);
306 generate_keystream(ctx, keystream);
308 #ifdef BIG_ENDIAN_ORDER
310 word32 wordsLeft = msglen / sizeof(word32);
311 if (msglen % sizeof(word32)) wordsLeft++;
313 ByteReverseWords(keystream, keystream, wordsLeft * sizeof(word32));
317 for (i = 0; i < msglen; i++)
318 output[i] = input[i] ^ ((byte*)keystream)[i];
324 #else /* HAVE_HC128 */
328 /* 4206 warning for blank file */
329 #pragma warning(disable: 4206)
333 #endif /* HAVE_HC128 */