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. */
29void    Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
30void    Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
31void    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  */
39int 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] */
83int 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 */
141int 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 */
189int 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)
223size_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  */
236int 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] */
281int 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 */
339int 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 */
387int 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)
421size_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  */
434int 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] */
478int 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 */
536int 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 */
584int 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)
618size_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 */
630int 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 */
646int 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 */
662int 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                                       */
679int 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                                       */
708int 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                                       */
737int 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 */
766void
767SKEIN256_Init(SKEIN256_CTX * ctx)
768{
769
770	Skein_256_Init(ctx, 256);
771}
772
773void
774SKEIN512_Init(SKEIN512_CTX * ctx)
775{
776
777	Skein_512_Init(ctx, 512);
778}
779
780void
781SKEIN1024_Init(SKEIN1024_CTX * ctx)
782{
783
784	Skein1024_Init(ctx, 1024);
785}
786
787void
788SKEIN256_Update(SKEIN256_CTX * ctx, const void *in, size_t len)
789{
790
791	Skein_256_Update(ctx, in, len);
792}
793
794void
795SKEIN512_Update(SKEIN512_CTX * ctx, const void *in, size_t len)
796{
797
798	Skein_512_Update(ctx, in, len);
799}
800
801void
802SKEIN1024_Update(SKEIN1024_CTX * ctx, const void *in, size_t len)
803{
804
805	Skein1024_Update(ctx, in, len);
806}
807
808void
809SKEIN256_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
816void
817SKEIN512_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
824void
825SKEIN1024_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