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