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