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: releng/11.0/sys/crypto/skein/skein.c 300921 2016-05-29 01:15:36Z allanjude $");
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. */
31void    Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
32void    Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
33void    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  */
41int 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] */
85int 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 */
143int 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 */
191int 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)
225size_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  */
238int 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] */
283int 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 */
341int 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 */
389int 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)
423size_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  */
436int 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] */
480int 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 */
538int 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 */
586int 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)
620size_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 */
632int 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 */
648int 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 */
664int 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                                       */
681int 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                                       */
710int 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                                       */
739int 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 */
768void
769SKEIN256_Init(SKEIN256_CTX * ctx)
770{
771
772	Skein_256_Init(ctx, 256);
773}
774
775void
776SKEIN512_Init(SKEIN512_CTX * ctx)
777{
778
779	Skein_512_Init(ctx, 512);
780}
781
782void
783SKEIN1024_Init(SKEIN1024_CTX * ctx)
784{
785
786	Skein1024_Init(ctx, 1024);
787}
788
789void
790SKEIN256_Update(SKEIN256_CTX * ctx, const void *in, size_t len)
791{
792
793	Skein_256_Update(ctx, in, len);
794}
795
796void
797SKEIN512_Update(SKEIN512_CTX * ctx, const void *in, size_t len)
798{
799
800	Skein_512_Update(ctx, in, len);
801}
802
803void
804SKEIN1024_Update(SKEIN1024_CTX * ctx, const void *in, size_t len)
805{
806
807	Skein1024_Update(ctx, in, len);
808}
809
810void
811SKEIN256_Final(unsigned char digest[static SKEIN_256_BLOCK_BYTES], SKEIN256_CTX *ctx)
812{
813
814	Skein_256_Final(ctx, digest);
815}
816
817void
818SKEIN512_Final(unsigned char digest[static SKEIN_512_BLOCK_BYTES], SKEIN512_CTX *ctx)
819{
820
821	Skein_512_Final(ctx, digest);
822}
823
824void
825SKEIN1024_Final(unsigned char digest[static SKEIN1024_BLOCK_BYTES], SKEIN1024_CTX *ctx)
826{
827
828	Skein1024_Final(ctx, digest);
829}
830
831#ifdef WEAK_REFS
832/* When building libmd, provide weak references. Note: this is not
833   activated in the context of compiling these sources for internal
834   use in libcrypt.
835 */
836#undef SKEIN256_Init
837__weak_reference(_libmd_SKEIN256_Init, SKEIN256_Init);
838#undef SKEIN256_Update
839__weak_reference(_libmd_SKEIN256_Update, SKEIN256_Update);
840#undef SKEIN256_Final
841__weak_reference(_libmd_SKEIN256_Final, SKEIN256_Final);
842
843#undef SKEIN512_Init
844__weak_reference(_libmd_SKEIN512_Init, SKEIN512_Init);
845#undef SKEIN512_Update
846__weak_reference(_libmd_SKEIN512_Update, SKEIN512_Update);
847#undef SKEIN512_Final
848__weak_reference(_libmd_SKEIN512_Final, SKEIN512_Final);
849
850#undef SKEIN1024_Init
851__weak_reference(_libmd_SKEIN1024_Init, SKEIN1024_Init);
852#undef SKEIN1024_Update
853__weak_reference(_libmd_SKEIN1024_Update, SKEIN1024_Update);
854#undef SKEIN1024_Final
855__weak_reference(_libmd_SKEIN1024_Final, SKEIN1024_Final);
856#endif
857
858#endif
859