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