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