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