xref: /freebsd/sys/contrib/openzfs/module/icp/algs/skein/skein.c (revision 2e3f49888ec8851bafb22011533217487764fdb0)
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  */
15 int
16 Skein_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  */
79 int
80 Skein_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 */
147 int
148 Skein_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 */
200 int
201 Skein_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  */
250 int
251 Skein_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  */
315 int
316 Skein_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 */
382 int
383 Skein_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 */
435 int
436 Skein_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  */
485 int
486 Skein1024_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  */
547 int
548 Skein1024_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 */
614 int
615 Skein1024_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 */
667 int
668 Skein1024_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 */
718 int
719 Skein_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 */
739 int
740 Skein_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 */
760 int
761 Skein1024_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 */
783 int
784 Skein_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 */
822 int
823 Skein_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 */
861 int
862 Skein1024_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
901 EXPORT_SYMBOL(Skein_512_Init);
902 EXPORT_SYMBOL(Skein_512_InitExt);
903 EXPORT_SYMBOL(Skein_512_Update);
904 EXPORT_SYMBOL(Skein_512_Final);
905 #endif
906