xref: /illumos-gate/usr/src/common/crypto/skein/skein.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
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. */
16 void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx, const uint8_t *blkPtr,
17     size_t blkCnt, size_t byteCntAdd);
18 void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
19     size_t blkCnt, size_t byteCntAdd);
20 void 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  */
25 int
26 Skein_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  */
89 int
90 Skein_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 */
157 int
158 Skein_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 */
210 int
211 Skein_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  */
261 int
262 Skein_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  */
326 int
327 Skein_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 */
393 int
394 Skein_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 */
446 int
447 Skein_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  */
497 int
498 Skein1024_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  */
559 int
560 Skein1024_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 */
626 int
627 Skein1024_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 */
679 int
680 Skein1024_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 */
731 int
732 Skein_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 */
752 int
753 Skein_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 */
773 int
774 Skein1024_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 */
796 int
797 Skein_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 */
836 int
837 Skein_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 */
876 int
877 Skein1024_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