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