]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/skein/skein_block.c
ebd4af1aaae5c169b087a721c3259ddfdd7e64aa
[karo-tx-linux.git] / drivers / staging / skein / skein_block.c
1 /***********************************************************************
2 **
3 ** Implementation of the Skein block functions.
4 **
5 ** Source code author: Doug Whiting, 2008.
6 **
7 ** This algorithm and source code is released to the public domain.
8 **
9 ** Compile-time switches:
10 **
11 **  SKEIN_USE_ASM  -- set bits (256/512/1024) to select which
12 **                    versions use ASM code for block processing
13 **                    [default: use C for all block sizes]
14 **
15 ************************************************************************/
16
17 #include <linux/string.h>
18 #include <skein.h>
19
20 #ifndef SKEIN_USE_ASM
21 #define SKEIN_USE_ASM   (0) /* default is all C code (no ASM) */
22 #endif
23
24 #ifndef SKEIN_LOOP
25 #define SKEIN_LOOP 001 /* default: unroll 256 and 512, but not 1024 */
26 #endif
27
28 #define BLK_BITS        (WCNT*64) /* some useful definitions for code here */
29 #define KW_TWK_BASE     (0)
30 #define KW_KEY_BASE     (3)
31 #define ks              (kw + KW_KEY_BASE)
32 #define ts              (kw + KW_TWK_BASE)
33
34 #ifdef SKEIN_DEBUG
35 #define DebugSaveTweak(ctx) { ctx->h.T[0] = ts[0]; ctx->h.T[1] = ts[1]; }
36 #else
37 #define DebugSaveTweak(ctx)
38 #endif
39
40 /*****************************  SKEIN_256 ******************************/
41 #if !(SKEIN_USE_ASM & 256)
42 void skein_256_process_block(struct skein_256_ctx *ctx, const u8 *blk_ptr,
43                              size_t blk_cnt, size_t byte_cnt_add)
44         { /* do it in C */
45         enum {
46                 WCNT = SKEIN_256_STATE_WORDS
47         };
48 #undef  RCNT
49 #define RCNT  (SKEIN_256_ROUNDS_TOTAL/8)
50
51 #ifdef SKEIN_LOOP /* configure how much to unroll the loop */
52 #define SKEIN_UNROLL_256 (((SKEIN_LOOP)/100)%10)
53 #else
54 #define SKEIN_UNROLL_256 (0)
55 #endif
56
57 #if SKEIN_UNROLL_256
58 #if (RCNT % SKEIN_UNROLL_256)
59 #error "Invalid SKEIN_UNROLL_256" /* sanity check on unroll count */
60 #endif
61         size_t  r;
62         u64  kw[WCNT+4+RCNT*2]; /* key schedule: chaining vars + tweak + "rot"*/
63 #else
64         u64  kw[WCNT+4]; /* key schedule words : chaining vars + tweak */
65 #endif
66         u64  X0, X1, X2, X3; /* local copy of context vars, for speed */
67         u64  w[WCNT]; /* local copy of input block */
68 #ifdef SKEIN_DEBUG
69         const u64 *X_ptr[4]; /* use for debugging (help cc put Xn in regs) */
70
71         X_ptr[0] = &X0;  X_ptr[1] = &X1;  X_ptr[2] = &X2;  X_ptr[3] = &X3;
72 #endif
73         Skein_assert(blk_cnt != 0); /* never call with blk_cnt == 0! */
74         ts[0] = ctx->h.T[0];
75         ts[1] = ctx->h.T[1];
76         do  {
77                 /*
78                  * this implementation only supports 2**64 input bytes
79                  * (no carry out here)
80                  */
81                 ts[0] += byte_cnt_add; /* update processed length */
82
83                 /* precompute the key schedule for this block */
84                 ks[0] = ctx->X[0];
85                 ks[1] = ctx->X[1];
86                 ks[2] = ctx->X[2];
87                 ks[3] = ctx->X[3];
88                 ks[4] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ SKEIN_KS_PARITY;
89
90                 ts[2] = ts[0] ^ ts[1];
91
92                 /* get input block in little-endian format */
93                 Skein_Get64_LSB_First(w, blk_ptr, WCNT);
94                 DebugSaveTweak(ctx);
95                 Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blk_ptr, w, ks, ts);
96
97                 X0 = w[0] + ks[0]; /* do the first full key injection */
98                 X1 = w[1] + ks[1] + ts[0];
99                 X2 = w[2] + ks[2] + ts[1];
100                 X3 = w[3] + ks[3];
101
102                 /* show starting state values */
103                 Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL,
104                                  X_ptr);
105
106                 blk_ptr += SKEIN_256_BLOCK_BYTES;
107
108                 /* run the rounds */
109
110 #define Round256(p0, p1, p2, p3, ROT, r_num)                              \
111 do { \
112         X##p0 += X##p1; X##p1 = RotL_64(X##p1, ROT##_0); X##p1 ^= X##p0; \
113         X##p2 += X##p3; X##p3 = RotL_64(X##p3, ROT##_1); X##p3 ^= X##p2; \
114 } while (0)
115
116 #if SKEIN_UNROLL_256 == 0
117 #define R256(p0, p1, p2, p3, ROT, r_num) /* fully unrolled */ \
118 do { \
119         Round256(p0, p1, p2, p3, ROT, r_num); \
120         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, r_num, X_ptr); \
121 } while (0)
122
123 #define I256(R) \
124 do { \
125         /* inject the key schedule value */ \
126         X0   += ks[((R)+1) % 5]; \
127         X1   += ks[((R)+2) % 5] + ts[((R)+1) % 3]; \
128         X2   += ks[((R)+3) % 5] + ts[((R)+2) % 3]; \
129         X3   += ks[((R)+4) % 5] +     (R)+1;       \
130         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, X_ptr); \
131 } while (0)
132 #else /* looping version */
133 #define R256(p0, p1, p2, p3, ROT, r_num) \
134 do { \
135         Round256(p0, p1, p2, p3, ROT, r_num); \
136         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, 4 * (r - 1) + r_num, X_ptr); \
137 } while (0)
138
139 #define I256(R) \
140 do { \
141         /* inject the key schedule value */ \
142         X0   += ks[r+(R)+0]; \
143         X1   += ks[r+(R)+1] + ts[r+(R)+0]; \
144         X2   += ks[r+(R)+2] + ts[r+(R)+1]; \
145         X3   += ks[r+(R)+3] +    r+(R);    \
146         /* rotate key schedule */ \
147         ks[r + (R) + 4]   = ks[r + (R) - 1]; \
148         ts[r + (R) + 2]   = ts[r + (R) - 1]; \
149         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, X_ptr); \
150 } while (0)
151
152         for (r = 1; r < 2 * RCNT; r += 2 * SKEIN_UNROLL_256)
153 #endif
154                 {
155 #define R256_8_rounds(R)                  \
156 do { \
157                 R256(0, 1, 2, 3, R_256_0, 8 * (R) + 1);  \
158                 R256(0, 3, 2, 1, R_256_1, 8 * (R) + 2);  \
159                 R256(0, 1, 2, 3, R_256_2, 8 * (R) + 3);  \
160                 R256(0, 3, 2, 1, R_256_3, 8 * (R) + 4);  \
161                 I256(2 * (R));                      \
162                 R256(0, 1, 2, 3, R_256_4, 8 * (R) + 5);  \
163                 R256(0, 3, 2, 1, R_256_5, 8 * (R) + 6);  \
164                 R256(0, 1, 2, 3, R_256_6, 8 * (R) + 7);  \
165                 R256(0, 3, 2, 1, R_256_7, 8 * (R) + 8);  \
166                 I256(2 * (R) + 1); \
167 } while (0)
168
169                 R256_8_rounds(0);
170
171 #define R256_Unroll_R(NN) \
172         ((SKEIN_UNROLL_256 == 0 && \
173           SKEIN_256_ROUNDS_TOTAL/8 > (NN)) || \
174          (SKEIN_UNROLL_256 > (NN)))
175
176         #if   R256_Unroll_R(1)
177                 R256_8_rounds(1);
178         #endif
179         #if   R256_Unroll_R(2)
180                 R256_8_rounds(2);
181         #endif
182         #if   R256_Unroll_R(3)
183                 R256_8_rounds(3);
184         #endif
185         #if   R256_Unroll_R(4)
186                 R256_8_rounds(4);
187         #endif
188         #if   R256_Unroll_R(5)
189                 R256_8_rounds(5);
190         #endif
191         #if   R256_Unroll_R(6)
192                 R256_8_rounds(6);
193         #endif
194         #if   R256_Unroll_R(7)
195                 R256_8_rounds(7);
196         #endif
197         #if   R256_Unroll_R(8)
198                 R256_8_rounds(8);
199         #endif
200         #if   R256_Unroll_R(9)
201                 R256_8_rounds(9);
202         #endif
203         #if   R256_Unroll_R(10)
204                 R256_8_rounds(10);
205         #endif
206         #if   R256_Unroll_R(11)
207                 R256_8_rounds(11);
208         #endif
209         #if   R256_Unroll_R(12)
210                 R256_8_rounds(12);
211         #endif
212         #if   R256_Unroll_R(13)
213                 R256_8_rounds(13);
214         #endif
215         #if   R256_Unroll_R(14)
216                 R256_8_rounds(14);
217         #endif
218         #if  (SKEIN_UNROLL_256 > 14)
219 #error  "need more unrolling in skein_256_process_block"
220         #endif
221                 }
222                 /* do the final "feedforward" xor, update context chaining */
223                 ctx->X[0] = X0 ^ w[0];
224                 ctx->X[1] = X1 ^ w[1];
225                 ctx->X[2] = X2 ^ w[2];
226                 ctx->X[3] = X3 ^ w[3];
227
228                 Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X);
229
230                 ts[1] &= ~SKEIN_T1_FLAG_FIRST;
231         } while (--blk_cnt);
232         ctx->h.T[0] = ts[0];
233         ctx->h.T[1] = ts[1];
234 }
235
236 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
237 size_t skein_256_process_block_code_size(void)
238 {
239         return ((u8 *) skein_256_process_block_code_size) -
240                 ((u8 *) skein_256_process_block);
241 }
242 unsigned int skein_256_unroll_cnt(void)
243 {
244         return SKEIN_UNROLL_256;
245 }
246 #endif
247 #endif
248
249 /*****************************  SKEIN_512 ******************************/
250 #if !(SKEIN_USE_ASM & 512)
251 void skein_512_process_block(struct skein_512_ctx *ctx, const u8 *blk_ptr,
252                              size_t blk_cnt, size_t byte_cnt_add)
253 { /* do it in C */
254         enum {
255                 WCNT = SKEIN_512_STATE_WORDS
256         };
257 #undef  RCNT
258 #define RCNT  (SKEIN_512_ROUNDS_TOTAL/8)
259
260 #ifdef SKEIN_LOOP /* configure how much to unroll the loop */
261 #define SKEIN_UNROLL_512 (((SKEIN_LOOP)/10)%10)
262 #else
263 #define SKEIN_UNROLL_512 (0)
264 #endif
265
266 #if SKEIN_UNROLL_512
267 #if (RCNT % SKEIN_UNROLL_512)
268 #error "Invalid SKEIN_UNROLL_512" /* sanity check on unroll count */
269 #endif
270         size_t  r;
271         u64  kw[WCNT+4+RCNT*2]; /* key sched: chaining vars + tweak + "rot"*/
272 #else
273         u64  kw[WCNT+4]; /* key schedule words : chaining vars + tweak */
274 #endif
275         u64  X0, X1, X2, X3, X4, X5, X6, X7; /* local copies, for speed */
276         u64  w[WCNT]; /* local copy of input block */
277 #ifdef SKEIN_DEBUG
278         const u64 *X_ptr[8]; /* use for debugging (help cc put Xn in regs) */
279
280         X_ptr[0] = &X0;  X_ptr[1] = &X1;  X_ptr[2] = &X2;  X_ptr[3] = &X3;
281         X_ptr[4] = &X4;  X_ptr[5] = &X5;  X_ptr[6] = &X6;  X_ptr[7] = &X7;
282 #endif
283
284         Skein_assert(blk_cnt != 0); /* never call with blk_cnt == 0! */
285         ts[0] = ctx->h.T[0];
286         ts[1] = ctx->h.T[1];
287         do  {
288                 /*
289                  * this implementation only supports 2**64 input bytes
290                  * (no carry out here)
291                  */
292                 ts[0] += byte_cnt_add; /* update processed length */
293
294                 /* precompute the key schedule for this block */
295                 ks[0] = ctx->X[0];
296                 ks[1] = ctx->X[1];
297                 ks[2] = ctx->X[2];
298                 ks[3] = ctx->X[3];
299                 ks[4] = ctx->X[4];
300                 ks[5] = ctx->X[5];
301                 ks[6] = ctx->X[6];
302                 ks[7] = ctx->X[7];
303                 ks[8] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^
304                         ks[4] ^ ks[5] ^ ks[6] ^ ks[7] ^ SKEIN_KS_PARITY;
305
306                 ts[2] = ts[0] ^ ts[1];
307
308                 /* get input block in little-endian format */
309                 Skein_Get64_LSB_First(w, blk_ptr, WCNT);
310                 DebugSaveTweak(ctx);
311                 Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blk_ptr, w, ks, ts);
312
313                 X0   = w[0] + ks[0]; /* do the first full key injection */
314                 X1   = w[1] + ks[1];
315                 X2   = w[2] + ks[2];
316                 X3   = w[3] + ks[3];
317                 X4   = w[4] + ks[4];
318                 X5   = w[5] + ks[5] + ts[0];
319                 X6   = w[6] + ks[6] + ts[1];
320                 X7   = w[7] + ks[7];
321
322                 blk_ptr += SKEIN_512_BLOCK_BYTES;
323
324                 Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL,
325                                  X_ptr);
326                 /* run the rounds */
327 #define Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) \
328 do { \
329         X##p0 += X##p1; X##p1 = RotL_64(X##p1, ROT##_0); X##p1 ^= X##p0; \
330         X##p2 += X##p3; X##p3 = RotL_64(X##p3, ROT##_1); X##p3 ^= X##p2; \
331         X##p4 += X##p5; X##p5 = RotL_64(X##p5, ROT##_2); X##p5 ^= X##p4; \
332         X##p6 += X##p7; X##p7 = RotL_64(X##p7, ROT##_3); X##p7 ^= X##p6; \
333 } while (0)
334
335 #if SKEIN_UNROLL_512 == 0
336 #define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) /* unrolled */ \
337 do { \
338         Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) \
339         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, r_num, X_ptr); \
340 } while (0)
341
342 #define I512(R) \
343 do { \
344         /* inject the key schedule value */ \
345         X0   += ks[((R) + 1) % 9]; \
346         X1   += ks[((R) + 2) % 9]; \
347         X2   += ks[((R) + 3) % 9]; \
348         X3   += ks[((R) + 4) % 9]; \
349         X4   += ks[((R) + 5) % 9]; \
350         X5   += ks[((R) + 6) % 9] + ts[((R) + 1) % 3]; \
351         X6   += ks[((R) + 7) % 9] + ts[((R) + 2) % 3]; \
352         X7   += ks[((R) + 8) % 9] +     (R) + 1;       \
353         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, X_ptr); \
354 } while (0)
355 #else /* looping version */
356 #define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) \
357 do { \
358         Round512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num); \
359         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, 4 * (r - 1) + r_num, X_ptr); \
360 } while (0)
361
362 #define I512(R) \
363 do { \
364         /* inject the key schedule value */ \
365         X0   += ks[r + (R) + 0]; \
366         X1   += ks[r + (R) + 1]; \
367         X2   += ks[r + (R) + 2]; \
368         X3   += ks[r + (R) + 3]; \
369         X4   += ks[r + (R) + 4]; \
370         X5   += ks[r + (R) + 5] + ts[r + (R) + 0]; \
371         X6   += ks[r + (R) + 6] + ts[r + (R) + 1]; \
372         X7   += ks[r + (R) + 7] +         r + (R); \
373         /* rotate key schedule */ \
374         ks[r +         (R) + 8] = ks[r + (R) - 1]; \
375         ts[r +         (R) + 2] = ts[r + (R) - 1]; \
376         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, X_ptr); \
377 } while (0)
378
379                 for (r = 1; r < 2 * RCNT; r += 2 * SKEIN_UNROLL_512)
380 #endif /* end of looped code definitions */
381                 {
382 #define R512_8_rounds(R)  /* do 8 full rounds */  \
383 do { \
384                 R512(0, 1, 2, 3, 4, 5, 6, 7, R_512_0, 8 * (R) + 1);   \
385                 R512(2, 1, 4, 7, 6, 5, 0, 3, R_512_1, 8 * (R) + 2);   \
386                 R512(4, 1, 6, 3, 0, 5, 2, 7, R_512_2, 8 * (R) + 3);   \
387                 R512(6, 1, 0, 7, 2, 5, 4, 3, R_512_3, 8 * (R) + 4);   \
388                 I512(2 * (R));                              \
389                 R512(0, 1, 2, 3, 4, 5, 6, 7, R_512_4, 8 * (R) + 5);   \
390                 R512(2, 1, 4, 7, 6, 5, 0, 3, R_512_5, 8 * (R) + 6);   \
391                 R512(4, 1, 6, 3, 0, 5, 2, 7, R_512_6, 8 * (R) + 7);   \
392                 R512(6, 1, 0, 7, 2, 5, 4, 3, R_512_7, 8 * (R) + 8);   \
393                 I512(2 * (R) + 1);        /* and key injection */ \
394 } while (0)
395
396                         R512_8_rounds(0);
397
398 #define R512_Unroll_R(NN) \
399                 ((SKEIN_UNROLL_512 == 0 && \
400                   SKEIN_512_ROUNDS_TOTAL/8 > (NN)) || \
401                  (SKEIN_UNROLL_512 > (NN)))
402
403         #if   R512_Unroll_R(1)
404                         R512_8_rounds(1);
405         #endif
406         #if   R512_Unroll_R(2)
407                         R512_8_rounds(2);
408         #endif
409         #if   R512_Unroll_R(3)
410                         R512_8_rounds(3);
411         #endif
412         #if   R512_Unroll_R(4)
413                         R512_8_rounds(4);
414         #endif
415         #if   R512_Unroll_R(5)
416                         R512_8_rounds(5);
417         #endif
418         #if   R512_Unroll_R(6)
419                         R512_8_rounds(6);
420         #endif
421         #if   R512_Unroll_R(7)
422                         R512_8_rounds(7);
423         #endif
424         #if   R512_Unroll_R(8)
425                         R512_8_rounds(8);
426         #endif
427         #if   R512_Unroll_R(9)
428                         R512_8_rounds(9);
429         #endif
430         #if   R512_Unroll_R(10)
431                         R512_8_rounds(10);
432         #endif
433         #if   R512_Unroll_R(11)
434                         R512_8_rounds(11);
435         #endif
436         #if   R512_Unroll_R(12)
437                         R512_8_rounds(12);
438         #endif
439         #if   R512_Unroll_R(13)
440                         R512_8_rounds(13);
441         #endif
442         #if   R512_Unroll_R(14)
443                         R512_8_rounds(14);
444         #endif
445         #if  (SKEIN_UNROLL_512 > 14)
446 #error  "need more unrolling in skein_512_process_block"
447         #endif
448                 }
449
450                 /* do the final "feedforward" xor, update context chaining */
451                 ctx->X[0] = X0 ^ w[0];
452                 ctx->X[1] = X1 ^ w[1];
453                 ctx->X[2] = X2 ^ w[2];
454                 ctx->X[3] = X3 ^ w[3];
455                 ctx->X[4] = X4 ^ w[4];
456                 ctx->X[5] = X5 ^ w[5];
457                 ctx->X[6] = X6 ^ w[6];
458                 ctx->X[7] = X7 ^ w[7];
459                 Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X);
460
461                 ts[1] &= ~SKEIN_T1_FLAG_FIRST;
462         } while (--blk_cnt);
463         ctx->h.T[0] = ts[0];
464         ctx->h.T[1] = ts[1];
465 }
466
467 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
468 size_t skein_512_process_block_code_size(void)
469 {
470         return ((u8 *) skein_512_process_block_code_size) -
471                 ((u8 *) skein_512_process_block);
472 }
473 unsigned int skein_512_unroll_cnt(void)
474 {
475         return SKEIN_UNROLL_512;
476 }
477 #endif
478 #endif
479
480 /*****************************  SKEIN_1024 ******************************/
481 #if !(SKEIN_USE_ASM & 1024)
482 void skein_1024_process_block(struct skein_1024_ctx *ctx, const u8 *blk_ptr,
483                               size_t blk_cnt, size_t byte_cnt_add)
484 { /* do it in C, always looping (unrolled is bigger AND slower!) */
485         enum {
486                 WCNT = SKEIN1024_STATE_WORDS
487         };
488 #undef  RCNT
489 #define RCNT  (SKEIN1024_ROUNDS_TOTAL/8)
490
491 #ifdef SKEIN_LOOP /* configure how much to unroll the loop */
492 #define SKEIN_UNROLL_1024 ((SKEIN_LOOP)%10)
493 #else
494 #define SKEIN_UNROLL_1024 (0)
495 #endif
496
497 #if (SKEIN_UNROLL_1024 != 0)
498 #if (RCNT % SKEIN_UNROLL_1024)
499 #error "Invalid SKEIN_UNROLL_1024" /* sanity check on unroll count */
500 #endif
501         size_t  r;
502         u64  kw[WCNT+4+RCNT*2]; /* key sched: chaining vars + tweak + "rot" */
503 #else
504         u64  kw[WCNT+4]; /* key schedule words : chaining vars + tweak */
505 #endif
506
507         /* local copy of vars, for speed */
508         u64  X00, X01, X02, X03, X04, X05, X06, X07,
509              X08, X09, X10, X11, X12, X13, X14, X15;
510         u64  w[WCNT]; /* local copy of input block */
511 #ifdef SKEIN_DEBUG
512         const u64 *X_ptr[16]; /* use for debugging (help cc put Xn in regs) */
513
514         X_ptr[0]  = &X00;  X_ptr[1]  = &X01;  X_ptr[2]  = &X02;
515         X_ptr[3]  = &X03;  X_ptr[4]  = &X04;  X_ptr[5]  = &X05;
516         X_ptr[6]  = &X06;  X_ptr[7]  = &X07;  X_ptr[8]  = &X08;
517         X_ptr[9]  = &X09;  X_ptr[10] = &X10;  X_ptr[11] = &X11;
518         X_ptr[12] = &X12;  X_ptr[13] = &X13;  X_ptr[14] = &X14;
519         X_ptr[15] = &X15;
520 #endif
521
522         Skein_assert(blk_cnt != 0); /* never call with blk_cnt == 0! */
523         ts[0] = ctx->h.T[0];
524         ts[1] = ctx->h.T[1];
525         do  {
526                 /*
527                  * this implementation only supports 2**64 input bytes
528                  * (no carry out here)
529                  */
530                 ts[0] += byte_cnt_add; /* update processed length */
531
532                 /* precompute the key schedule for this block */
533                 ks[0]  = ctx->X[0];
534                 ks[1]  = ctx->X[1];
535                 ks[2]  = ctx->X[2];
536                 ks[3]  = ctx->X[3];
537                 ks[4]  = ctx->X[4];
538                 ks[5]  = ctx->X[5];
539                 ks[6]  = ctx->X[6];
540                 ks[7]  = ctx->X[7];
541                 ks[8]  = ctx->X[8];
542                 ks[9]  = ctx->X[9];
543                 ks[10] = ctx->X[10];
544                 ks[11] = ctx->X[11];
545                 ks[12] = ctx->X[12];
546                 ks[13] = ctx->X[13];
547                 ks[14] = ctx->X[14];
548                 ks[15] = ctx->X[15];
549                 ks[16] =  ks[0] ^  ks[1] ^  ks[2] ^  ks[3] ^
550                           ks[4] ^  ks[5] ^  ks[6] ^  ks[7] ^
551                           ks[8] ^  ks[9] ^ ks[10] ^ ks[11] ^
552                           ks[12] ^ ks[13] ^ ks[14] ^ ks[15] ^ SKEIN_KS_PARITY;
553
554                 ts[2]  = ts[0] ^ ts[1];
555
556                 /* get input block in little-endian format */
557                 Skein_Get64_LSB_First(w, blk_ptr, WCNT);
558                 DebugSaveTweak(ctx);
559                 Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blk_ptr, w, ks, ts);
560
561                 X00    =  w[0] +  ks[0]; /* do the first full key injection */
562                 X01    =  w[1] +  ks[1];
563                 X02    =  w[2] +  ks[2];
564                 X03    =  w[3] +  ks[3];
565                 X04    =  w[4] +  ks[4];
566                 X05    =  w[5] +  ks[5];
567                 X06    =  w[6] +  ks[6];
568                 X07    =  w[7] +  ks[7];
569                 X08    =  w[8] +  ks[8];
570                 X09    =  w[9] +  ks[9];
571                 X10    = w[10] + ks[10];
572                 X11    = w[11] + ks[11];
573                 X12    = w[12] + ks[12];
574                 X13    = w[13] + ks[13] + ts[0];
575                 X14    = w[14] + ks[14] + ts[1];
576                 X15    = w[15] + ks[15];
577
578                 Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL,
579                                  X_ptr);
580
581 #define Round1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, \
582                         pF, ROT, r_num) \
583 do { \
584         X##p0 += X##p1; X##p1 = RotL_64(X##p1, ROT##_0); X##p1 ^= X##p0;   \
585         X##p2 += X##p3; X##p3 = RotL_64(X##p3, ROT##_1); X##p3 ^= X##p2;   \
586         X##p4 += X##p5; X##p5 = RotL_64(X##p5, ROT##_2); X##p5 ^= X##p4;   \
587         X##p6 += X##p7; X##p7 = RotL_64(X##p7, ROT##_3); X##p7 ^= X##p6;   \
588         X##p8 += X##p9; X##p9 = RotL_64(X##p9, ROT##_4); X##p9 ^= X##p8;   \
589         X##pA += X##pB; X##pB = RotL_64(X##pB, ROT##_5); X##pB ^= X##pA;   \
590         X##pC += X##pD; X##pD = RotL_64(X##pD, ROT##_6); X##pD ^= X##pC;   \
591         X##pE += X##pF; X##pF = RotL_64(X##pF, ROT##_7); X##pF ^= X##pE;   \
592 } while (0)
593
594 #if SKEIN_UNROLL_1024 == 0
595 #define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, pF, \
596                 ROT, rn) \
597 do { \
598         Round1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, \
599                         pF, ROT, rn) \
600         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, rn, X_ptr); \
601 } while (0)
602
603 #define I1024(R) \
604 do { \
605         /* inject the key schedule value */ \
606         X00   += ks[((R) +  1) % 17]; \
607         X01   += ks[((R) +  2) % 17]; \
608         X02   += ks[((R) +  3) % 17]; \
609         X03   += ks[((R) +  4) % 17]; \
610         X04   += ks[((R) +  5) % 17]; \
611         X05   += ks[((R) +  6) % 17]; \
612         X06   += ks[((R) +  7) % 17]; \
613         X07   += ks[((R) +  8) % 17]; \
614         X08   += ks[((R) +  9) % 17]; \
615         X09   += ks[((R) + 10) % 17]; \
616         X10   += ks[((R) + 11) % 17]; \
617         X11   += ks[((R) + 12) % 17]; \
618         X12   += ks[((R) + 13) % 17]; \
619         X13   += ks[((R) + 14) % 17] + ts[((R) + 1) % 3]; \
620         X14   += ks[((R) + 15) % 17] + ts[((R) + 2) % 3]; \
621         X15   += ks[((R) + 16) % 17] +     (R) + 1;       \
622         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INJECT, X_ptr); \
623 } while (0)
624 #else /* looping version */
625 #define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, pF, \
626                 ROT, rn) \
627 do { \
628         Round1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, \
629                         pF, ROT, rn) \
630         Skein_Show_R_Ptr(BLK_BITS, &ctx->h, 4 * (r - 1) + rn, X_ptr); \
631 } while (0)
632
633 #define I1024(R) \
634 do { \
635         /* inject the key schedule value */ \
636         X00   += ks[r + (R) +  0]; \
637         X01   += ks[r + (R) +  1]; \
638         X02   += ks[r + (R) +  2]; \
639         X03   += ks[r + (R) +  3]; \
640         X04   += ks[r + (R) +  4]; \
641         X05   += ks[r + (R) +  5]; \
642         X06   += ks[r + (R) +  6]; \
643         X07   += ks[r + (R) +  7]; \
644         X08   += ks[r + (R) +  8]; \
645         X09   += ks[r + (R) +  9]; \
646         X10   += ks[r + (R) + 10]; \
647         X11   += ks[r + (R) + 11]; \
648         X12   += ks[r + (R) + 12]; \
649         X13   += ks[r + (R) + 13] + ts[r + (R) + 0]; \
650         X14   += ks[r + (R) + 14] + ts[r + (R) + 1]; \
651         X15   += ks[r + (R) + 15] +         r + (R); \
652         /* rotate key schedule */ \
653         ks[r  +         (R) + 16] = ks[r + (R) - 1]; \
654         ts[r  +         (R) +  2] = ts[r + (R) - 1]; \
655         Skein_Show_R_Ptr(BLK_BITSi, &ctx->h, SKEIN_RND_KEY_INJECT, X_ptr); \
656 } while (0)
657
658                 for (r = 1; r <= 2 * RCNT; r += 2 * SKEIN_UNROLL_1024)
659 #endif
660                 {
661 #define R1024_8_rounds(R) \
662 do { \
663         R1024(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, \
664                 R1024_0, 8*(R) + 1); \
665         R1024(00, 09, 02, 13, 06, 11, 04, 15, 10, 07, 12, 03, 14, 05, 08, 01, \
666                 R1024_1, 8*(R) + 2); \
667         R1024(00, 07, 02, 05, 04, 03, 06, 01, 12, 15, 14, 13, 08, 11, 10, 09, \
668                 R1024_2, 8*(R) + 3); \
669         R1024(00, 15, 02, 11, 06, 13, 04, 09, 14, 01, 08, 05, 10, 03, 12, 07, \
670                 R1024_3, 8*(R) + 4); \
671         I1024(2*(R)); \
672         R1024(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, \
673                 R1024_4, 8*(R) + 5); \
674         R1024(00, 09, 02, 13, 06, 11, 04, 15, 10, 07, 12, 03, 14, 05, 08, 01, \
675                 R1024_5, 8*(R) + 6); \
676         R1024(00, 07, 02, 05, 04, 03, 06, 01, 12, 15, 14, 13, 08, 11, 10, 09, \
677                 R1024_6, 8*(R) + 7); \
678         R1024(00, 15, 02, 11, 06, 13, 04, 09, 14, 01, 08, 05, 10, 03, 12, 07, \
679                 R1024_7, 8*(R) + 8); \
680         I1024(2*(R)+1); \
681 } while (0)
682
683                         R1024_8_rounds(0);
684
685 #define R1024_Unroll_R(NN) \
686                 ((SKEIN_UNROLL_1024 == 0 && \
687                   SKEIN1024_ROUNDS_TOTAL/8 > (NN)) || \
688                  (SKEIN_UNROLL_1024 > (NN)))
689
690         #if   R1024_Unroll_R(1)
691                         R1024_8_rounds(1);
692         #endif
693         #if   R1024_Unroll_R(2)
694                         R1024_8_rounds(2);
695         #endif
696         #if   R1024_Unroll_R(3)
697                         R1024_8_rounds(3);
698         #endif
699         #if   R1024_Unroll_R(4)
700                         R1024_8_rounds(4);
701         #endif
702         #if   R1024_Unroll_R(5)
703                         R1024_8_rounds(5);
704         #endif
705         #if   R1024_Unroll_R(6)
706                         R1024_8_rounds(6);
707         #endif
708         #if   R1024_Unroll_R(7)
709                         R1024_8_rounds(7);
710         #endif
711         #if   R1024_Unroll_R(8)
712                         R1024_8_rounds(8);
713         #endif
714         #if   R1024_Unroll_R(9)
715                         R1024_8_rounds(9);
716         #endif
717         #if   R1024_Unroll_R(10)
718                         R1024_8_rounds(10);
719         #endif
720         #if   R1024_Unroll_R(11)
721                         R1024_8_rounds(11);
722         #endif
723         #if   R1024_Unroll_R(12)
724                         R1024_8_rounds(12);
725         #endif
726         #if   R1024_Unroll_R(13)
727                         R1024_8_rounds(13);
728         #endif
729         #if   R1024_Unroll_R(14)
730                         R1024_8_rounds(14);
731         #endif
732 #if  (SKEIN_UNROLL_1024 > 14)
733 #error  "need more unrolling in Skein_1024_Process_Block"
734   #endif
735                 }
736                 /* do the final "feedforward" xor, update context chaining */
737
738                 ctx->X[0] = X00 ^ w[0];
739                 ctx->X[1] = X01 ^ w[1];
740                 ctx->X[2] = X02 ^ w[2];
741                 ctx->X[3] = X03 ^ w[3];
742                 ctx->X[4] = X04 ^ w[4];
743                 ctx->X[5] = X05 ^ w[5];
744                 ctx->X[6] = X06 ^ w[6];
745                 ctx->X[7] = X07 ^ w[7];
746                 ctx->X[8] = X08 ^ w[8];
747                 ctx->X[9] = X09 ^ w[9];
748                 ctx->X[10] = X10 ^ w[10];
749                 ctx->X[11] = X11 ^ w[11];
750                 ctx->X[12] = X12 ^ w[12];
751                 ctx->X[13] = X13 ^ w[13];
752                 ctx->X[14] = X14 ^ w[14];
753                 ctx->X[15] = X15 ^ w[15];
754
755                 Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X);
756
757                 ts[1] &= ~SKEIN_T1_FLAG_FIRST;
758                 blk_ptr += SKEIN1024_BLOCK_BYTES;
759         } while (--blk_cnt);
760         ctx->h.T[0] = ts[0];
761         ctx->h.T[1] = ts[1];
762 }
763
764 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
765 size_t skein_1024_process_block_code_size(void)
766 {
767         return ((u8 *) skein_1024_process_block_code_size) -
768                 ((u8 *) skein_1024_process_block);
769 }
770 unsigned int skein_1024_unroll_cnt(void)
771 {
772         return SKEIN_UNROLL_1024;
773 }
774 #endif
775 #endif