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