skein_cli main routine simplified.
[skeinsum.git] / skein.c
1 /***********************************************************************\r
2 **\r
3 ** Implementation of the Skein hash function.\r
4 **\r
5 ** Source code author: Doug Whiting, 2008.\r
6 **\r
7 ** This algorithm and source code is released to the public domain.\r
8 ** \r
9 ************************************************************************/\r
10 \r
11 #include <string.h>      /* get the memcpy/memset functions */\r
12 #include "skein.h"       /* get the Skein API definitions   */\r
13 \r
14 /*****************************************************************/\r
15 /* External function to process blkCnt (nonzero) full block(s) of data. */\r
16 void    Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);\r
17 void    Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);\r
18 void    Skein1024_Process_Block(Skein1024_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);\r
19 \r
20 /*****************************************************************/\r
21 /*     Portable (i.e., slow) endianness conversion functions     */\r
22 u64b_t Skein_Swap64(u64b_t w64)\r
23     {    /* instantiate the function body here */\r
24     static const u64b_t ONE = 1;              /* use this to check endianness */\r
25 \r
26     /* figure out endianness "on-the-fly" */\r
27     if (1 == ((u08b_t *) & ONE)[0])\r
28         return w64;                           /* little-endian is fast */\r
29     else\r
30         return  (( w64       & 0xFF) << 56) | /*    big-endian is slow */\r
31                 (((w64 >> 8) & 0xFF) << 48) |\r
32                 (((w64 >>16) & 0xFF) << 40) |\r
33                 (((w64 >>24) & 0xFF) << 32) |\r
34                 (((w64 >>32) & 0xFF) << 24) |\r
35                 (((w64 >>40) & 0xFF) << 16) |\r
36                 (((w64 >>48) & 0xFF) <<  8) |\r
37                 (((w64 >>56) & 0xFF)      ) ;\r
38     }\r
39 \r
40 void    Skein_Put64_LSB_First(u08b_t *dst,const u64b_t *src,size_t bCnt)\r
41     { /* this version is fully portable (big-endian or little-endian), but slow */\r
42     size_t n;\r
43 \r
44     for (n=0;n<bCnt;n++)\r
45         dst[n] = (u08b_t) (src[n>>3] >> (8*(n&7)));\r
46     }\r
47 \r
48 void    Skein_Get64_LSB_First(u64b_t *dst,const u08b_t *src,size_t wCnt)\r
49     { /* this version is fully portable (big-endian or little-endian), but slow */\r
50     size_t n;\r
51 \r
52     for (n=0;n<8*wCnt;n+=8)\r
53         dst[n/8] = (((u64b_t) src[n  ])      ) +\r
54                    (((u64b_t) src[n+1]) <<  8) +\r
55                    (((u64b_t) src[n+2]) << 16) +\r
56                    (((u64b_t) src[n+3]) << 24) +\r
57                    (((u64b_t) src[n+4]) << 32) +\r
58                    (((u64b_t) src[n+5]) << 40) +\r
59                    (((u64b_t) src[n+6]) << 48) +\r
60                    (((u64b_t) src[n+7]) << 56) ;\r
61     }\r
62 \r
63 /*****************************************************************/\r
64 /*     256-bit Skein                                             */\r
65 /*****************************************************************/\r
66 \r
67 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
68 /* init the context for a straight hashing operation */\r
69 int Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen)\r
70     {\r
71     union\r
72         {\r
73         u08b_t  b[SKEIN_256_STATE_BYTES];\r
74         u64b_t  w[SKEIN_256_STATE_WORDS];\r
75         } cfg;                                  /* config block */\r
76         \r
77     Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);\r
78 \r
79     /* build/process config block for hashing */\r
80     ctx->h.hashBitLen = hashBitLen;             /* output hash byte count */\r
81     Skein_Start_New_Type(ctx,CFG_FINAL);        /* set tweaks: T0=0; T1=CFG | FINAL */\r
82 \r
83     memset(&cfg.w,0,sizeof(cfg.w));             /* pre-pad cfg.w[] with zeroes */\r
84     cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);  /* set the schema, version */\r
85     cfg.w[1] = Skein_Swap64(hashBitLen);        /* hash result length in bits */\r
86     cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);\r
87 \r
88     /* compute the initial chaining values from config block */\r
89     memset(ctx->X,0,sizeof(ctx->X));            /* zero the chaining variables */\r
90     Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);\r
91 \r
92     /* The chaining vars ctx->X are now initialized for the given hashBitLen. */\r
93     /* Set up to process the data message portion of the hash (default) */\r
94     Skein_Start_New_Type(ctx,MSG);              /* T0=0, T1= MSG type, h.bCnt=0 */\r
95 \r
96     return SKEIN_SUCCESS;\r
97     }\r
98 \r
99 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
100 /* init the context for a MAC and/or tree hash operation */\r
101 /* [identical to Skein_256_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */\r
102 int Skein_256_InitExt(Skein_256_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes)\r
103     {\r
104     uint_t i;\r
105     union\r
106         {\r
107         u08b_t  b[SKEIN_256_STATE_BYTES];\r
108         u64b_t  w[SKEIN_256_STATE_WORDS];\r
109         } cfg;                                  /* config block */\r
110         \r
111     Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);\r
112     Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);\r
113 \r
114     /* compute the initial chaining values ctx->X[], based on key */\r
115     if (keyBytes == 0)                          /* is there a key? */\r
116         {                                   \r
117         memset(ctx->X,0,sizeof(ctx->X));        /* no key: use all zeroes as key for config block */\r
118         }\r
119     else                                        /* here to pre-process a key */\r
120         {\r
121         Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X));\r
122         /* do a mini-Init right here */\r
123         ctx->h.hashBitLen=8*sizeof(ctx->X);     /* set output hash bit count = state size */\r
124         Skein_Start_New_Type(ctx,KEY);          /* set tweaks: T0 = 0; T1 = KEY type */\r
125         memset(ctx->X,0,sizeof(ctx->X));        /* zero the initial chaining variables */\r
126         Skein_256_Update(ctx,key,keyBytes);     /* hash the key */\r
127         Skein_256_Final_Pad(ctx,cfg.b);         /* put result into cfg.b[] */\r
128         memcpy(ctx->X,cfg.b,sizeof(cfg.b));     /* copy over into ctx->X[] */\r
129         for (i=0;i<SKEIN_256_STATE_WORDS;i++)   /* convert key bytes to context words */\r
130             ctx->X[i] = Skein_Swap64(ctx->X[i]);\r
131         }\r
132 \r
133     /* build/process the config block, type == CONFIG (could be precomputed for each key) */\r
134     ctx->h.hashBitLen = hashBitLen;             /* output hash bit count */\r
135     Skein_Start_New_Type(ctx,CFG_FINAL);\r
136 \r
137     memset(&cfg.w,0,sizeof(cfg.w));             /* pre-pad cfg.w[] with zeroes */\r
138     cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);\r
139     cfg.w[1] = Skein_Swap64(hashBitLen);        /* hash result length in bits */\r
140     cfg.w[2] = Skein_Swap64(treeInfo);          /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */\r
141 \r
142     Skein_Show_Key(256,&ctx->h,key,keyBytes);\r
143 \r
144     /* compute the initial chaining values from config block */\r
145     Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);\r
146 \r
147     /* The chaining vars ctx->X are now initialized */\r
148     /* Set up to process the data message portion of the hash */\r
149     Skein_Start_New_Type(ctx,MSG);              /* T0=0, T1= MSG type, h.bCnt=0 */\r
150 \r
151     return SKEIN_SUCCESS;\r
152     }\r
153 \r
154 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
155 /* process the input bytes */\r
156 int Skein_256_Update(Skein_256_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)\r
157     {\r
158     size_t n;\r
159 \r
160     Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL);     /* catch uninitialized context */\r
161 \r
162     /* process full blocks, if any */\r
163     if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES)\r
164         {\r
165         if (ctx->h.bCnt)                              /* finish up any buffered message data */\r
166             {\r
167             n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt;  /* # bytes free in buffer b[] */\r
168             if (n)\r
169                 {\r
170                 Skein_assert(n < msgByteCnt);         /* check on our logic here */\r
171                 memcpy(&ctx->b[ctx->h.bCnt],msg,n);\r
172                 msgByteCnt  -= n;\r
173                 msg         += n;\r
174                 ctx->h.bCnt += n;\r
175                 }\r
176             Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES);\r
177             Skein_256_Process_Block(ctx,ctx->b,1,SKEIN_256_BLOCK_BYTES);\r
178             ctx->h.bCnt = 0;\r
179             }\r
180         /* now process any remaining full blocks, directly from input message data */\r
181         if (msgByteCnt > SKEIN_256_BLOCK_BYTES)\r
182             {\r
183             n = (msgByteCnt-1) / SKEIN_256_BLOCK_BYTES;   /* number of full blocks to process */\r
184             Skein_256_Process_Block(ctx,msg,n,SKEIN_256_BLOCK_BYTES);\r
185             msgByteCnt -= n * SKEIN_256_BLOCK_BYTES;\r
186             msg        += n * SKEIN_256_BLOCK_BYTES;\r
187             }\r
188         Skein_assert(ctx->h.bCnt == 0);\r
189         }\r
190 \r
191     /* copy any remaining source message data bytes into b[] */\r
192     if (msgByteCnt)\r
193         {\r
194         Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES);\r
195         memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);\r
196         ctx->h.bCnt += msgByteCnt;\r
197         }\r
198 \r
199     return SKEIN_SUCCESS;\r
200     }\r
201    \r
202 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
203 /* finalize the hash computation and output the result */\r
204 int Skein_256_Final(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)\r
205     {\r
206     size_t i,n,byteCnt;\r
207     u64b_t X[SKEIN_256_STATE_WORDS];\r
208     Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL);    /* catch uninitialized context */\r
209 \r
210     ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;        /* tag as the final block */\r
211     if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)   /* zero pad b[] if necessary */\r
212         memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);\r
213     Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt);    /* process the final block */\r
214     \r
215     /* now output the result */\r
216     byteCnt = (ctx->h.hashBitLen + 7) >> 3;    /* total number of output bytes */\r
217 \r
218     /* run Threefish in "counter mode" to generate output */\r
219     memset(ctx->b,0,sizeof(ctx->b));  /* zero out b[], so it can hold the counter */\r
220     memcpy(X,ctx->X,sizeof(X));       /* keep a local copy of counter mode "key" */\r
221     for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++)\r
222         {\r
223         ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */\r
224         Skein_Start_New_Type(ctx,OUT_FINAL);\r
225         Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */\r
226         n = byteCnt - i*SKEIN_256_BLOCK_BYTES;   /* number of output bytes left to go */\r
227         if (n >= SKEIN_256_BLOCK_BYTES)\r
228             n  = SKEIN_256_BLOCK_BYTES;\r
229         Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n);   /* "output" the ctr mode bytes */\r
230         Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES);\r
231         memcpy(ctx->X,X,sizeof(X));   /* restore the counter mode key for next time */\r
232         }\r
233     return SKEIN_SUCCESS;\r
234     }\r
235 \r
236 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)\r
237 size_t Skein_256_API_CodeSize(void)\r
238     {\r
239     return ((u08b_t *) Skein_256_API_CodeSize) -\r
240            ((u08b_t *) Skein_256_Init);\r
241     }\r
242 #endif\r
243 \r
244 /*****************************************************************/\r
245 /*     512-bit Skein                                             */\r
246 /*****************************************************************/\r
247 \r
248 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
249 /* init the context for a straight hashing operation */\r
250 int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)\r
251     {\r
252     union\r
253         {\r
254         u08b_t  b[SKEIN_512_STATE_BYTES];\r
255         u64b_t  w[SKEIN_512_STATE_WORDS];\r
256         } cfg;                                  /* config block */\r
257         \r
258     Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);\r
259 \r
260     /* build/process config block for hashing */\r
261     ctx->h.hashBitLen = hashBitLen;             /* output hash byte count */\r
262     Skein_Start_New_Type(ctx,CFG_FINAL);        /* set tweaks: T0=0; T1=CFG | FINAL */\r
263 \r
264     memset(&cfg.w,0,sizeof(cfg.w));             /* pre-pad cfg.w[] with zeroes */\r
265     cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);  /* set the schema, version */\r
266     cfg.w[1] = Skein_Swap64(hashBitLen);        /* hash result length in bits */\r
267     cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);\r
268 \r
269     /* compute the initial chaining values from config block */\r
270     memset(ctx->X,0,sizeof(ctx->X));            /* zero the chaining variables */\r
271     Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);\r
272 \r
273     /* The chaining vars ctx->X are now initialized for the given hashBitLen. */\r
274     /* Set up to process the data message portion of the hash (default) */\r
275     Skein_Start_New_Type(ctx,MSG);              /* T0=0, T1= MSG type, h.bCnt=0 */\r
276 \r
277     return SKEIN_SUCCESS;\r
278     }\r
279 \r
280 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
281 /* init the context for a MAC and/or tree hash operation */\r
282 /* [identical to Skein_512_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */\r
283 int Skein_512_InitExt(Skein_512_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes)\r
284     {\r
285     uint_t i;\r
286     union\r
287         {\r
288         u08b_t  b[SKEIN_512_STATE_BYTES];\r
289         u64b_t  w[SKEIN_512_STATE_WORDS];\r
290         } cfg;                                  /* config block */\r
291         \r
292     Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);\r
293     Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);\r
294 \r
295     /* compute the initial chaining values ctx->X[], based on key */\r
296     if (keyBytes == 0)                          /* is there a key? */\r
297         {                                   \r
298         memset(ctx->X,0,sizeof(ctx->X));        /* no key: use all zeroes as key for config block */\r
299         }\r
300     else                                        /* here to pre-process a key */\r
301         {\r
302         Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X));\r
303         /* do a mini-Init right here */\r
304         ctx->h.hashBitLen=8*sizeof(ctx->X);     /* set output hash bit count = state size */\r
305         Skein_Start_New_Type(ctx,KEY);          /* set tweaks: T0 = 0; T1 = KEY type */\r
306         memset(ctx->X,0,sizeof(ctx->X));        /* zero the initial chaining variables */\r
307         Skein_512_Update(ctx,key,keyBytes);     /* hash the key */\r
308         Skein_512_Final_Pad(ctx,cfg.b);         /* put result into cfg.b[] */\r
309         memcpy(ctx->X,cfg.b,sizeof(cfg.b));     /* copy over into ctx->X[] */\r
310         for (i=0;i<SKEIN_512_STATE_WORDS;i++)   /* convert key bytes to context words */\r
311             ctx->X[i] = Skein_Swap64(ctx->X[i]);\r
312         }\r
313 \r
314     /* build/process the config block, type == CONFIG (could be precomputed for each key) */\r
315     ctx->h.hashBitLen = hashBitLen;             /* output hash bit count */\r
316     Skein_Start_New_Type(ctx,CFG_FINAL);\r
317 \r
318     memset(&cfg.w,0,sizeof(cfg.w));             /* pre-pad cfg.w[] with zeroes */\r
319     cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);\r
320     cfg.w[1] = Skein_Swap64(hashBitLen);        /* hash result length in bits */\r
321     cfg.w[2] = Skein_Swap64(treeInfo);          /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */\r
322 \r
323     Skein_Show_Key(512,&ctx->h,key,keyBytes);\r
324 \r
325     /* compute the initial chaining values from config block */\r
326     Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);\r
327 \r
328     /* The chaining vars ctx->X are now initialized */\r
329     /* Set up to process the data message portion of the hash */\r
330     Skein_Start_New_Type(ctx,MSG);              /* T0=0, T1= MSG type, h.bCnt=0 */\r
331 \r
332     return SKEIN_SUCCESS;\r
333     }\r
334 \r
335 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
336 /* process the input bytes */\r
337 int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)\r
338     {\r
339     size_t n;\r
340 \r
341     Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL);     /* catch uninitialized context */\r
342 \r
343     /* process full blocks, if any */\r
344     if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES)\r
345         {\r
346         if (ctx->h.bCnt)                              /* finish up any buffered message data */\r
347             {\r
348             n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt;  /* # bytes free in buffer b[] */\r
349             if (n)\r
350                 {\r
351                 Skein_assert(n < msgByteCnt);         /* check on our logic here */\r
352                 memcpy(&ctx->b[ctx->h.bCnt],msg,n);\r
353                 msgByteCnt  -= n;\r
354                 msg         += n;\r
355                 ctx->h.bCnt += n;\r
356                 }\r
357             Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES);\r
358             Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES);\r
359             ctx->h.bCnt = 0;\r
360             }\r
361         /* now process any remaining full blocks, directly from input message data */\r
362         if (msgByteCnt > SKEIN_512_BLOCK_BYTES)\r
363             {\r
364             n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES;   /* number of full blocks to process */\r
365             Skein_512_Process_Block(ctx,msg,n,SKEIN_512_BLOCK_BYTES);\r
366             msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;\r
367             msg        += n * SKEIN_512_BLOCK_BYTES;\r
368             }\r
369         Skein_assert(ctx->h.bCnt == 0);\r
370         }\r
371 \r
372     /* copy any remaining source message data bytes into b[] */\r
373     if (msgByteCnt)\r
374         {\r
375         Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES);\r
376         memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);\r
377         ctx->h.bCnt += msgByteCnt;\r
378         }\r
379 \r
380     return SKEIN_SUCCESS;\r
381     }\r
382    \r
383 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
384 /* finalize the hash computation and output the result */\r
385 int Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)\r
386     {\r
387     size_t i,n,byteCnt;\r
388     u64b_t X[SKEIN_512_STATE_WORDS];\r
389     Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL);    /* catch uninitialized context */\r
390 \r
391     ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;                 /* tag as the final block */\r
392     if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)   /* zero pad b[] if necessary */\r
393         memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);\r
394 \r
395     Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt);  /* process the final block */\r
396     \r
397     /* now output the result */\r
398     byteCnt = (ctx->h.hashBitLen + 7) >> 3;             /* total number of output bytes */\r
399 \r
400     /* run Threefish in "counter mode" to generate more output */\r
401     memset(ctx->b,0,sizeof(ctx->b));  /* zero out b[], so it can hold the counter */\r
402     memcpy(X,ctx->X,sizeof(X));       /* keep a local copy of counter mode "key" */\r
403     for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++)\r
404         {\r
405         ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */\r
406         Skein_Start_New_Type(ctx,OUT_FINAL);\r
407         Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */\r
408         n = byteCnt - i*SKEIN_512_BLOCK_BYTES;   /* number of output bytes left to go */\r
409         if (n >= SKEIN_512_BLOCK_BYTES)\r
410             n  = SKEIN_512_BLOCK_BYTES;\r
411         Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n);   /* "output" the ctr mode bytes */\r
412         Skein_Show_Final(512,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES);\r
413         memcpy(ctx->X,X,sizeof(X));   /* restore the counter mode key for next time */\r
414         }\r
415 \r
416     return SKEIN_SUCCESS;\r
417     }\r
418 \r
419 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)\r
420 size_t Skein_512_API_CodeSize(void)\r
421     {\r
422     return ((u08b_t *) Skein_512_API_CodeSize) -\r
423            ((u08b_t *) Skein_512_Init);\r
424     }\r
425 #endif\r
426 \r
427 /*****************************************************************/\r
428 /*    1024-bit Skein                                             */\r
429 /*****************************************************************/\r
430 \r
431 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
432 /* init the context for a straight hashing operation */\r
433 int Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen)\r
434     {\r
435     union\r
436         {\r
437         u08b_t  b[SKEIN1024_STATE_BYTES];\r
438         u64b_t  w[SKEIN1024_STATE_WORDS];\r
439         } cfg;                                  /* config block */\r
440         \r
441     Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);\r
442 \r
443     /* build/process config block for hashing */\r
444     ctx->h.hashBitLen = hashBitLen;             /* output hash byte count */\r
445     Skein_Start_New_Type(ctx,CFG_FINAL);        /* set tweaks: T0=0; T1=CFG | FINAL */\r
446 \r
447     memset(&cfg.w,0,sizeof(cfg.w));             /* pre-pad cfg.w[] with zeroes */\r
448     cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);  /* set the schema, version */\r
449     cfg.w[1] = Skein_Swap64(hashBitLen);        /* hash result length in bits */\r
450     cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);\r
451 \r
452     /* compute the initial chaining values from config block */\r
453     memset(ctx->X,0,sizeof(ctx->X));            /* zero the chaining variables */\r
454     Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);\r
455 \r
456     /* The chaining vars ctx->X are now initialized for the given hashBitLen. */\r
457     /* Set up to process the data message portion of the hash (default) */\r
458     Skein_Start_New_Type(ctx,MSG);              /* T0=0, T1= MSG type, h.bCnt=0 */\r
459 \r
460     return SKEIN_SUCCESS;\r
461     }\r
462 \r
463 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
464 /* init the context for a MAC and/or tree hash operation */\r
465 /* [identical to Skein1024_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */\r
466 int Skein1024_InitExt(Skein1024_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes)\r
467     {\r
468     uint_t i;\r
469     union\r
470         {\r
471         u08b_t  b[SKEIN1024_STATE_BYTES];\r
472         u64b_t  w[SKEIN1024_STATE_WORDS];\r
473         } cfg;                                  /* config block */\r
474         \r
475     Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);\r
476     Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);\r
477 \r
478     /* compute the initial chaining values ctx->X[], based on key */\r
479     if (keyBytes == 0)                          /* is there a key? */\r
480         {                                   \r
481         memset(ctx->X,0,sizeof(ctx->X));        /* no key: use all zeroes as key for config block */\r
482         }\r
483     else                                        /* here to pre-process a key */\r
484         {\r
485         Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X));\r
486         /* do a mini-Init right here */\r
487         ctx->h.hashBitLen=8*sizeof(ctx->X);     /* set output hash bit count = state size */\r
488         Skein_Start_New_Type(ctx,KEY);          /* set tweaks: T0 = 0; T1 = KEY type */\r
489         memset(ctx->X,0,sizeof(ctx->X));        /* zero the initial chaining variables */\r
490         Skein1024_Update(ctx,key,keyBytes);     /* hash the key */\r
491         Skein1024_Final_Pad(ctx,cfg.b);         /* put result into cfg.b[] */\r
492         memcpy(ctx->X,cfg.b,sizeof(cfg.b));     /* copy over into ctx->X[] */\r
493         for (i=0;i<SKEIN1024_STATE_WORDS;i++)   /* convert key bytes to context words */\r
494             ctx->X[i] = Skein_Swap64(ctx->X[i]);\r
495         }\r
496 \r
497     /* build/process the config block, type == CONFIG (could be precomputed for each key) */\r
498     ctx->h.hashBitLen = hashBitLen;             /* output hash bit count */\r
499     Skein_Start_New_Type(ctx,CFG_FINAL);\r
500 \r
501     memset(&cfg.w,0,sizeof(cfg.w));             /* pre-pad cfg.w[] with zeroes */\r
502     cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);\r
503     cfg.w[1] = Skein_Swap64(hashBitLen);        /* hash result length in bits */\r
504     cfg.w[2] = Skein_Swap64(treeInfo);          /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */\r
505 \r
506     Skein_Show_Key(1024,&ctx->h,key,keyBytes);\r
507 \r
508     /* compute the initial chaining values from config block */\r
509     Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);\r
510 \r
511     /* The chaining vars ctx->X are now initialized */\r
512     /* Set up to process the data message portion of the hash */\r
513     Skein_Start_New_Type(ctx,MSG);              /* T0=0, T1= MSG type, h.bCnt=0 */\r
514 \r
515     return SKEIN_SUCCESS;\r
516     }\r
517 \r
518 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
519 /* process the input bytes */\r
520 int Skein1024_Update(Skein1024_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)\r
521     {\r
522     size_t n;\r
523 \r
524     Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL);     /* catch uninitialized context */\r
525 \r
526     /* process full blocks, if any */\r
527     if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES)\r
528         {\r
529         if (ctx->h.bCnt)                              /* finish up any buffered message data */\r
530             {\r
531             n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt;  /* # bytes free in buffer b[] */\r
532             if (n)\r
533                 {\r
534                 Skein_assert(n < msgByteCnt);         /* check on our logic here */\r
535                 memcpy(&ctx->b[ctx->h.bCnt],msg,n);\r
536                 msgByteCnt  -= n;\r
537                 msg         += n;\r
538                 ctx->h.bCnt += n;\r
539                 }\r
540             Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES);\r
541             Skein1024_Process_Block(ctx,ctx->b,1,SKEIN1024_BLOCK_BYTES);\r
542             ctx->h.bCnt = 0;\r
543             }\r
544         /* now process any remaining full blocks, directly from input message data */\r
545         if (msgByteCnt > SKEIN1024_BLOCK_BYTES)\r
546             {\r
547             n = (msgByteCnt-1) / SKEIN1024_BLOCK_BYTES;   /* number of full blocks to process */\r
548             Skein1024_Process_Block(ctx,msg,n,SKEIN1024_BLOCK_BYTES);\r
549             msgByteCnt -= n * SKEIN1024_BLOCK_BYTES;\r
550             msg        += n * SKEIN1024_BLOCK_BYTES;\r
551             }\r
552         Skein_assert(ctx->h.bCnt == 0);\r
553         }\r
554 \r
555     /* copy any remaining source message data bytes into b[] */\r
556     if (msgByteCnt)\r
557         {\r
558         Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES);\r
559         memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);\r
560         ctx->h.bCnt += msgByteCnt;\r
561         }\r
562 \r
563     return SKEIN_SUCCESS;\r
564     }\r
565    \r
566 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
567 /* finalize the hash computation and output the result */\r
568 int Skein1024_Final(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)\r
569     {\r
570     size_t i,n,byteCnt;\r
571     u64b_t X[SKEIN1024_STATE_WORDS];\r
572     Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL);    /* catch uninitialized context */\r
573 \r
574     ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;                 /* tag as the final block */\r
575     if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)   /* zero pad b[] if necessary */\r
576         memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);\r
577 \r
578     Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt);  /* process the final block */\r
579     \r
580     /* now output the result */\r
581     byteCnt = (ctx->h.hashBitLen + 7) >> 3;    /* total number of output bytes */\r
582 \r
583     /* run Threefish in "counter mode" to generate output */\r
584     memset(ctx->b,0,sizeof(ctx->b));  /* zero out b[], so it can hold the counter */\r
585     memcpy(X,ctx->X,sizeof(X));       /* keep a local copy of counter mode "key" */\r
586     for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++)\r
587         {\r
588         ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */\r
589         Skein_Start_New_Type(ctx,OUT_FINAL);\r
590         Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */\r
591         n = byteCnt - i*SKEIN1024_BLOCK_BYTES;   /* number of output bytes left to go */\r
592         if (n >= SKEIN1024_BLOCK_BYTES)\r
593             n  = SKEIN1024_BLOCK_BYTES;\r
594         Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n);   /* "output" the ctr mode bytes */\r
595         Skein_Show_Final(1024,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES);\r
596         memcpy(ctx->X,X,sizeof(X));   /* restore the counter mode key for next time */\r
597         }\r
598     return SKEIN_SUCCESS;\r
599     }\r
600 \r
601 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)\r
602 size_t Skein1024_API_CodeSize(void)\r
603     {\r
604     return ((u08b_t *) Skein1024_API_CodeSize) -\r
605            ((u08b_t *) Skein1024_Init);\r
606     }\r
607 #endif\r
608 \r
609 /**************** Functions to support MAC/tree hashing ***************/\r
610 /*   (this code is identical for Optimized and Reference versions)    */\r
611 \r
612 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
613 /* finalize the hash computation and output the block, no OUTPUT stage */\r
614 int Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)\r
615     {\r
616     Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL);    /* catch uninitialized context */\r
617 \r
618     ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;        /* tag as the final block */\r
619     if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)   /* zero pad b[] if necessary */\r
620         memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);\r
621     Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt);    /* process the final block */\r
622     \r
623     Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_256_BLOCK_BYTES);   /* "output" the state bytes */\r
624     \r
625     return SKEIN_SUCCESS;\r
626     }\r
627 \r
628 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
629 /* finalize the hash computation and output the block, no OUTPUT stage */\r
630 int Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)\r
631     {\r
632     Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL);    /* catch uninitialized context */\r
633 \r
634     ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;        /* tag as the final block */\r
635     if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)   /* zero pad b[] if necessary */\r
636         memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);\r
637     Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt);    /* process the final block */\r
638     \r
639     Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_512_BLOCK_BYTES);   /* "output" the state bytes */\r
640     \r
641     return SKEIN_SUCCESS;\r
642     }\r
643 \r
644 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
645 /* finalize the hash computation and output the block, no OUTPUT stage */\r
646 int Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)\r
647     {\r
648     Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL);    /* catch uninitialized context */\r
649 \r
650     ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;        /* tag as the final block */\r
651     if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)   /* zero pad b[] if necessary */\r
652         memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);\r
653     Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt);    /* process the final block */\r
654     \r
655     Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN1024_BLOCK_BYTES);   /* "output" the state bytes */\r
656     \r
657     return SKEIN_SUCCESS;\r
658     }\r
659 \r
660 #if SKEIN_TREE_HASH\r
661 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
662 /* just do the OUTPUT stage                                       */\r
663 int Skein_256_Output(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)\r
664     {\r
665     size_t i,n,byteCnt;\r
666     u64b_t X[SKEIN_256_STATE_WORDS];\r
667     Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL);    /* catch uninitialized context */\r
668 \r
669     /* now output the result */\r
670     byteCnt = (ctx->h.hashBitLen + 7) >> 3;    /* total number of output bytes */\r
671 \r
672     /* run Threefish in "counter mode" to generate output */\r
673     memset(ctx->b,0,sizeof(ctx->b));  /* zero out b[], so it can hold the counter */\r
674     memcpy(X,ctx->X,sizeof(X));       /* keep a local copy of counter mode "key" */\r
675     for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++)\r
676         {\r
677         ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */\r
678         Skein_Start_New_Type(ctx,OUT_FINAL);\r
679         Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */\r
680         n = byteCnt - i*SKEIN_256_BLOCK_BYTES;   /* number of output bytes left to go */\r
681         if (n >= SKEIN_256_BLOCK_BYTES)\r
682             n  = SKEIN_256_BLOCK_BYTES;\r
683         Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n);   /* "output" the ctr mode bytes */\r
684         Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES);\r
685         memcpy(ctx->X,X,sizeof(X));   /* restore the counter mode key for next time */\r
686         }\r
687     return SKEIN_SUCCESS;\r
688     }\r
689 \r
690 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
691 /* just do the OUTPUT stage                                       */\r
692 int Skein_512_Output(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)\r
693     {\r
694     size_t i,n,byteCnt;\r
695     u64b_t X[SKEIN_512_STATE_WORDS];\r
696     Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL);    /* catch uninitialized context */\r
697 \r
698     /* now output the result */\r
699     byteCnt = (ctx->h.hashBitLen + 7) >> 3;    /* total number of output bytes */\r
700 \r
701     /* run Threefish in "counter mode" to generate output */\r
702     memset(ctx->b,0,sizeof(ctx->b));  /* zero out b[], so it can hold the counter */\r
703     memcpy(X,ctx->X,sizeof(X));       /* keep a local copy of counter mode "key" */\r
704     for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++)\r
705         {\r
706         ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */\r
707         Skein_Start_New_Type(ctx,OUT_FINAL);\r
708         Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */\r
709         n = byteCnt - i*SKEIN_512_BLOCK_BYTES;   /* number of output bytes left to go */\r
710         if (n >= SKEIN_512_BLOCK_BYTES)\r
711             n  = SKEIN_512_BLOCK_BYTES;\r
712         Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n);   /* "output" the ctr mode bytes */\r
713         Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES);\r
714         memcpy(ctx->X,X,sizeof(X));   /* restore the counter mode key for next time */\r
715         }\r
716     return SKEIN_SUCCESS;\r
717     }\r
718 \r
719 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/\r
720 /* just do the OUTPUT stage                                       */\r
721 int Skein1024_Output(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)\r
722     {\r
723     size_t i,n,byteCnt;\r
724     u64b_t X[SKEIN1024_STATE_WORDS];\r
725     Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL);    /* catch uninitialized context */\r
726 \r
727     /* now output the result */\r
728     byteCnt = (ctx->h.hashBitLen + 7) >> 3;    /* total number of output bytes */\r
729 \r
730     /* run Threefish in "counter mode" to generate output */\r
731     memset(ctx->b,0,sizeof(ctx->b));  /* zero out b[], so it can hold the counter */\r
732     memcpy(X,ctx->X,sizeof(X));       /* keep a local copy of counter mode "key" */\r
733     for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++)\r
734         {\r
735         ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */\r
736         Skein_Start_New_Type(ctx,OUT_FINAL);\r
737         Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */\r
738         n = byteCnt - i*SKEIN1024_BLOCK_BYTES;   /* number of output bytes left to go */\r
739         if (n >= SKEIN1024_BLOCK_BYTES)\r
740             n  = SKEIN1024_BLOCK_BYTES;\r
741         Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n);   /* "output" the ctr mode bytes */\r
742         Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES);\r
743         memcpy(ctx->X,X,sizeof(X));   /* restore the counter mode key for next time */\r
744         }\r
745     return SKEIN_SUCCESS;\r
746     }\r
747 #endif\r