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