ZTS: Add Fedora 41, remove Fedora 39
[zfs.git] / module / icp / algs / skein / skein.c
blob41ed2dd44e9ef1fd06e3231f6fdff02512a7a103
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. */
8 #include <sys/sysmacros.h>
9 #include <sys/types.h>
10 #include <sys/skein.h> /* get the Skein API definitions */
11 #include "skein_impl.h" /* get internal definitions */
13 /* 256-bit Skein */
14 /* init the context for a straight hashing operation */
15 int
16 Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen)
18 union {
19 uint8_t b[SKEIN_256_STATE_BYTES];
20 uint64_t w[SKEIN_256_STATE_WORDS];
21 } cfg; /* config block */
23 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
24 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
26 switch (hashBitLen) { /* use pre-computed values, where available */
27 #ifndef SKEIN_NO_PRECOMP
28 case 256:
29 memcpy(ctx->X, SKEIN_256_IV_256, sizeof (ctx->X));
30 break;
31 case 224:
32 memcpy(ctx->X, SKEIN_256_IV_224, sizeof (ctx->X));
33 break;
34 case 160:
35 memcpy(ctx->X, SKEIN_256_IV_160, sizeof (ctx->X));
36 break;
37 case 128:
38 memcpy(ctx->X, SKEIN_256_IV_128, sizeof (ctx->X));
39 break;
40 #endif
41 default:
42 /* here if there is no precomputed IV value available */
44 * build/process the config block, type == CONFIG (could be
45 * precomputed)
47 /* set tweaks: T0=0; T1=CFG | FINAL */
48 Skein_Start_New_Type(ctx, CFG_FINAL);
50 /* set the schema, version */
51 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
52 /* hash result length in bits */
53 cfg.w[1] = Skein_Swap64(hashBitLen);
54 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
55 /* zero pad config block */
56 memset(&cfg.w[3], 0, sizeof (cfg) - 3 * sizeof (cfg.w[0]));
58 /* compute the initial chaining values from config block */
59 /* zero the chaining variables */
60 memset(ctx->X, 0, sizeof (ctx->X));
61 Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
62 break;
65 * The chaining vars ctx->X are now initialized for the given
66 * hashBitLen.
67 * Set up to process the data message portion of the hash (default)
69 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
71 return (SKEIN_SUCCESS);
74 /* init the context for a MAC and/or tree hash operation */
76 * [identical to Skein_256_Init() when keyBytes == 0 &&
77 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
79 int
80 Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
81 const uint8_t *key, size_t keyBytes)
83 union {
84 uint8_t b[SKEIN_256_STATE_BYTES];
85 uint64_t w[SKEIN_256_STATE_WORDS];
86 } cfg; /* config block */
88 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
89 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
91 /* compute the initial chaining values ctx->X[], based on key */
92 if (keyBytes == 0) { /* is there a key? */
93 /* no key: use all zeroes as key for config block */
94 memset(ctx->X, 0, sizeof (ctx->X));
95 } else { /* here to pre-process a key */
97 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
98 /* do a mini-Init right here */
99 /* set output hash bit count = state size */
100 ctx->h.hashBitLen = 8 * sizeof (ctx->X);
101 /* set tweaks: T0 = 0; T1 = KEY type */
102 Skein_Start_New_Type(ctx, KEY);
103 /* zero the initial chaining variables */
104 memset(ctx->X, 0, sizeof (ctx->X));
105 /* hash the key */
106 (void) Skein_256_Update(ctx, key, keyBytes);
107 /* put result into cfg.b[] */
108 (void) Skein_256_Final_Pad(ctx, cfg.b);
109 /* copy over into ctx->X[] */
110 memcpy(ctx->X, cfg.b, sizeof (cfg.b));
111 #if SKEIN_NEED_SWAP
113 uint_t i;
114 /* convert key bytes to context words */
115 for (i = 0; i < SKEIN_256_STATE_WORDS; i++)
116 ctx->X[i] = Skein_Swap64(ctx->X[i]);
118 #endif
121 * build/process the config block, type == CONFIG (could be
122 * precomputed for each key)
124 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
125 Skein_Start_New_Type(ctx, CFG_FINAL);
127 memset(&cfg.w, 0, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
128 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
129 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
130 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
131 cfg.w[2] = Skein_Swap64(treeInfo);
133 Skein_Show_Key(256, &ctx->h, key, keyBytes);
135 /* compute the initial chaining values from config block */
136 Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
138 /* The chaining vars ctx->X are now initialized */
139 /* Set up to process the data message portion of the hash (default) */
140 ctx->h.bCnt = 0; /* buffer b[] starts out empty */
141 Skein_Start_New_Type(ctx, MSG);
143 return (SKEIN_SUCCESS);
146 /* process the input bytes */
148 Skein_256_Update(Skein_256_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
150 size_t n;
152 /* catch uninitialized context */
153 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
155 /* process full blocks, if any */
156 if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES) {
157 /* finish up any buffered message data */
158 if (ctx->h.bCnt) {
159 /* # bytes free in buffer b[] */
160 n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt;
161 if (n) {
162 /* check on our logic here */
163 Skein_assert(n < msgByteCnt);
164 memcpy(&ctx->b[ctx->h.bCnt], msg, n);
165 msgByteCnt -= n;
166 msg += n;
167 ctx->h.bCnt += n;
169 Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES);
170 Skein_256_Process_Block(ctx, ctx->b, 1,
171 SKEIN_256_BLOCK_BYTES);
172 ctx->h.bCnt = 0;
175 * now process any remaining full blocks, directly from input
176 * message data
178 if (msgByteCnt > SKEIN_256_BLOCK_BYTES) {
179 /* number of full blocks to process */
180 n = (msgByteCnt - 1) / SKEIN_256_BLOCK_BYTES;
181 Skein_256_Process_Block(ctx, msg, n,
182 SKEIN_256_BLOCK_BYTES);
183 msgByteCnt -= n * SKEIN_256_BLOCK_BYTES;
184 msg += n * SKEIN_256_BLOCK_BYTES;
186 Skein_assert(ctx->h.bCnt == 0);
189 /* copy any remaining source message data bytes into b[] */
190 if (msgByteCnt) {
191 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES);
192 memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
193 ctx->h.bCnt += msgByteCnt;
196 return (SKEIN_SUCCESS);
199 /* finalize the hash computation and output the result */
201 Skein_256_Final(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
203 size_t i, n, byteCnt;
204 uint64_t X[SKEIN_256_STATE_WORDS];
206 /* catch uninitialized context */
207 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
209 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
210 /* zero pad b[] if necessary */
211 if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)
212 memset(&ctx->b[ctx->h.bCnt], 0,
213 SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
215 /* process the final block */
216 Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
218 /* now output the result */
219 /* total number of output bytes */
220 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
222 /* run Threefish in "counter mode" to generate output */
223 /* zero out b[], so it can hold the counter */
224 memset(ctx->b, 0, sizeof (ctx->b));
225 /* keep a local copy of counter mode "key" */
226 memcpy(X, ctx->X, sizeof (X));
227 for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) {
228 /* build the counter block */
229 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
230 Skein_Start_New_Type(ctx, OUT_FINAL);
231 /* run "counter mode" */
232 Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
233 /* number of output bytes left to go */
234 n = byteCnt - i * SKEIN_256_BLOCK_BYTES;
235 if (n >= SKEIN_256_BLOCK_BYTES)
236 n = SKEIN_256_BLOCK_BYTES;
237 Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES,
238 ctx->X, n); /* "output" the ctr mode bytes */
239 Skein_Show_Final(256, &ctx->h, n,
240 hashVal + i * SKEIN_256_BLOCK_BYTES);
241 /* restore the counter mode key for next time */
242 memcpy(ctx->X, X, sizeof (X));
244 return (SKEIN_SUCCESS);
247 /* 512-bit Skein */
249 /* init the context for a straight hashing operation */
251 Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
253 union {
254 uint8_t b[SKEIN_512_STATE_BYTES];
255 uint64_t w[SKEIN_512_STATE_WORDS];
256 } cfg; /* config block */
258 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
259 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
261 switch (hashBitLen) { /* use pre-computed values, where available */
262 #ifndef SKEIN_NO_PRECOMP
263 case 512:
264 memcpy(ctx->X, SKEIN_512_IV_512, sizeof (ctx->X));
265 break;
266 case 384:
267 memcpy(ctx->X, SKEIN_512_IV_384, sizeof (ctx->X));
268 break;
269 case 256:
270 memcpy(ctx->X, SKEIN_512_IV_256, sizeof (ctx->X));
271 break;
272 case 224:
273 memcpy(ctx->X, SKEIN_512_IV_224, sizeof (ctx->X));
274 break;
275 #endif
276 default:
278 * here if there is no precomputed IV value available
279 * build/process the config block, type == CONFIG (could be
280 * precomputed)
282 /* set tweaks: T0=0; T1=CFG | FINAL */
283 Skein_Start_New_Type(ctx, CFG_FINAL);
285 /* set the schema, version */
286 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
287 /* hash result length in bits */
288 cfg.w[1] = Skein_Swap64(hashBitLen);
289 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
290 /* zero pad config block */
291 memset(&cfg.w[3], 0, sizeof (cfg) - 3 * sizeof (cfg.w[0]));
293 /* compute the initial chaining values from config block */
294 /* zero the chaining variables */
295 memset(ctx->X, 0, sizeof (ctx->X));
296 Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
297 break;
301 * The chaining vars ctx->X are now initialized for the given
302 * hashBitLen. Set up to process the data message portion of the
303 * hash (default)
305 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
307 return (SKEIN_SUCCESS);
310 /* init the context for a MAC and/or tree hash operation */
312 * [identical to Skein_512_Init() when keyBytes == 0 &&
313 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
316 Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
317 const uint8_t *key, size_t keyBytes)
319 union {
320 uint8_t b[SKEIN_512_STATE_BYTES];
321 uint64_t w[SKEIN_512_STATE_WORDS];
322 } cfg; /* config block */
324 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
325 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
327 /* compute the initial chaining values ctx->X[], based on key */
328 if (keyBytes == 0) { /* is there a key? */
329 /* no key: use all zeroes as key for config block */
330 memset(ctx->X, 0, sizeof (ctx->X));
331 } else { /* here to pre-process a key */
333 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
334 /* do a mini-Init right here */
335 /* set output hash bit count = state size */
336 ctx->h.hashBitLen = 8 * sizeof (ctx->X);
337 /* set tweaks: T0 = 0; T1 = KEY type */
338 Skein_Start_New_Type(ctx, KEY);
339 /* zero the initial chaining variables */
340 memset(ctx->X, 0, sizeof (ctx->X));
341 (void) Skein_512_Update(ctx, key, keyBytes); /* hash the key */
342 /* put result into cfg.b[] */
343 (void) Skein_512_Final_Pad(ctx, cfg.b);
344 /* copy over into ctx->X[] */
345 memcpy(ctx->X, cfg.b, sizeof (cfg.b));
346 #if SKEIN_NEED_SWAP
348 uint_t i;
349 /* convert key bytes to context words */
350 for (i = 0; i < SKEIN_512_STATE_WORDS; i++)
351 ctx->X[i] = Skein_Swap64(ctx->X[i]);
353 #endif
356 * build/process the config block, type == CONFIG (could be
357 * precomputed for each key)
359 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
360 Skein_Start_New_Type(ctx, CFG_FINAL);
362 memset(&cfg.w, 0, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
363 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
364 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
365 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
366 cfg.w[2] = Skein_Swap64(treeInfo);
368 Skein_Show_Key(512, &ctx->h, key, keyBytes);
370 /* compute the initial chaining values from config block */
371 Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
373 /* The chaining vars ctx->X are now initialized */
374 /* Set up to process the data message portion of the hash (default) */
375 ctx->h.bCnt = 0; /* buffer b[] starts out empty */
376 Skein_Start_New_Type(ctx, MSG);
378 return (SKEIN_SUCCESS);
381 /* process the input bytes */
383 Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
385 size_t n;
387 /* catch uninitialized context */
388 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
390 /* process full blocks, if any */
391 if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) {
392 /* finish up any buffered message data */
393 if (ctx->h.bCnt) {
394 /* # bytes free in buffer b[] */
395 n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt;
396 if (n) {
397 /* check on our logic here */
398 Skein_assert(n < msgByteCnt);
399 memcpy(&ctx->b[ctx->h.bCnt], msg, n);
400 msgByteCnt -= n;
401 msg += n;
402 ctx->h.bCnt += n;
404 Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES);
405 Skein_512_Process_Block(ctx, ctx->b, 1,
406 SKEIN_512_BLOCK_BYTES);
407 ctx->h.bCnt = 0;
410 * now process any remaining full blocks, directly from input
411 * message data
413 if (msgByteCnt > SKEIN_512_BLOCK_BYTES) {
414 /* number of full blocks to process */
415 n = (msgByteCnt - 1) / SKEIN_512_BLOCK_BYTES;
416 Skein_512_Process_Block(ctx, msg, n,
417 SKEIN_512_BLOCK_BYTES);
418 msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
419 msg += n * SKEIN_512_BLOCK_BYTES;
421 Skein_assert(ctx->h.bCnt == 0);
424 /* copy any remaining source message data bytes into b[] */
425 if (msgByteCnt) {
426 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES);
427 memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
428 ctx->h.bCnt += msgByteCnt;
431 return (SKEIN_SUCCESS);
434 /* finalize the hash computation and output the result */
436 Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
438 size_t i, n, byteCnt;
439 uint64_t X[SKEIN_512_STATE_WORDS];
441 /* catch uninitialized context */
442 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
444 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
445 /* zero pad b[] if necessary */
446 if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
447 memset(&ctx->b[ctx->h.bCnt], 0,
448 SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
450 /* process the final block */
451 Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
453 /* now output the result */
454 /* total number of output bytes */
455 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
457 /* run Threefish in "counter mode" to generate output */
458 /* zero out b[], so it can hold the counter */
459 memset(ctx->b, 0, sizeof (ctx->b));
460 /* keep a local copy of counter mode "key" */
461 memcpy(X, ctx->X, sizeof (X));
462 for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) {
463 /* build the counter block */
464 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
465 Skein_Start_New_Type(ctx, OUT_FINAL);
466 /* run "counter mode" */
467 Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
468 /* number of output bytes left to go */
469 n = byteCnt - i * SKEIN_512_BLOCK_BYTES;
470 if (n >= SKEIN_512_BLOCK_BYTES)
471 n = SKEIN_512_BLOCK_BYTES;
472 Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES,
473 ctx->X, n); /* "output" the ctr mode bytes */
474 Skein_Show_Final(512, &ctx->h, n,
475 hashVal + i * SKEIN_512_BLOCK_BYTES);
476 /* restore the counter mode key for next time */
477 memcpy(ctx->X, X, sizeof (X));
479 return (SKEIN_SUCCESS);
482 /* 1024-bit Skein */
484 /* init the context for a straight hashing operation */
486 Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen)
488 union {
489 uint8_t b[SKEIN1024_STATE_BYTES];
490 uint64_t w[SKEIN1024_STATE_WORDS];
491 } cfg; /* config block */
493 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
494 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
496 switch (hashBitLen) { /* use pre-computed values, where available */
497 #ifndef SKEIN_NO_PRECOMP
498 case 512:
499 memcpy(ctx->X, SKEIN1024_IV_512, sizeof (ctx->X));
500 break;
501 case 384:
502 memcpy(ctx->X, SKEIN1024_IV_384, sizeof (ctx->X));
503 break;
504 case 1024:
505 memcpy(ctx->X, SKEIN1024_IV_1024, sizeof (ctx->X));
506 break;
507 #endif
508 default:
509 /* here if there is no precomputed IV value available */
511 * build/process the config block, type == CONFIG (could be
512 * precomputed)
514 /* set tweaks: T0=0; T1=CFG | FINAL */
515 Skein_Start_New_Type(ctx, CFG_FINAL);
517 /* set the schema, version */
518 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
519 /* hash result length in bits */
520 cfg.w[1] = Skein_Swap64(hashBitLen);
521 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
522 /* zero pad config block */
523 memset(&cfg.w[3], 0, sizeof (cfg) - 3 * sizeof (cfg.w[0]));
525 /* compute the initial chaining values from config block */
526 /* zero the chaining variables */
527 memset(ctx->X, 0, sizeof (ctx->X));
528 Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
529 break;
533 * The chaining vars ctx->X are now initialized for the given
534 * hashBitLen. Set up to process the data message portion of the hash
535 * (default)
537 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
539 return (SKEIN_SUCCESS);
542 /* init the context for a MAC and/or tree hash operation */
544 * [identical to Skein1024_Init() when keyBytes == 0 &&
545 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
548 Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
549 const uint8_t *key, size_t keyBytes)
551 union {
552 uint8_t b[SKEIN1024_STATE_BYTES];
553 uint64_t w[SKEIN1024_STATE_WORDS];
554 } cfg; /* config block */
556 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
557 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
559 /* compute the initial chaining values ctx->X[], based on key */
560 if (keyBytes == 0) { /* is there a key? */
561 /* no key: use all zeroes as key for config block */
562 memset(ctx->X, 0, sizeof (ctx->X));
563 } else { /* here to pre-process a key */
564 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
565 /* do a mini-Init right here */
566 /* set output hash bit count = state size */
567 ctx->h.hashBitLen = 8 * sizeof (ctx->X);
568 /* set tweaks: T0 = 0; T1 = KEY type */
569 Skein_Start_New_Type(ctx, KEY);
570 /* zero the initial chaining variables */
571 memset(ctx->X, 0, sizeof (ctx->X));
572 (void) Skein1024_Update(ctx, key, keyBytes); /* hash the key */
573 /* put result into cfg.b[] */
574 (void) Skein1024_Final_Pad(ctx, cfg.b);
575 /* copy over into ctx->X[] */
576 memcpy(ctx->X, cfg.b, sizeof (cfg.b));
577 #if SKEIN_NEED_SWAP
579 uint_t i;
580 /* convert key bytes to context words */
581 for (i = 0; i < SKEIN1024_STATE_WORDS; i++)
582 ctx->X[i] = Skein_Swap64(ctx->X[i]);
584 #endif
587 * build/process the config block, type == CONFIG (could be
588 * precomputed for each key)
590 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
591 Skein_Start_New_Type(ctx, CFG_FINAL);
593 memset(&cfg.w, 0, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
594 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
595 /* hash result length in bits */
596 cfg.w[1] = Skein_Swap64(hashBitLen);
597 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
598 cfg.w[2] = Skein_Swap64(treeInfo);
600 Skein_Show_Key(1024, &ctx->h, key, keyBytes);
602 /* compute the initial chaining values from config block */
603 Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
605 /* The chaining vars ctx->X are now initialized */
606 /* Set up to process the data message portion of the hash (default) */
607 ctx->h.bCnt = 0; /* buffer b[] starts out empty */
608 Skein_Start_New_Type(ctx, MSG);
610 return (SKEIN_SUCCESS);
613 /* process the input bytes */
615 Skein1024_Update(Skein1024_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
617 size_t n;
619 /* catch uninitialized context */
620 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
622 /* process full blocks, if any */
623 if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES) {
624 /* finish up any buffered message data */
625 if (ctx->h.bCnt) {
626 /* # bytes free in buffer b[] */
627 n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt;
628 if (n) {
629 /* check on our logic here */
630 Skein_assert(n < msgByteCnt);
631 memcpy(&ctx->b[ctx->h.bCnt], msg, n);
632 msgByteCnt -= n;
633 msg += n;
634 ctx->h.bCnt += n;
636 Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES);
637 Skein1024_Process_Block(ctx, ctx->b, 1,
638 SKEIN1024_BLOCK_BYTES);
639 ctx->h.bCnt = 0;
642 * now process any remaining full blocks, directly from
643 * input message data
645 if (msgByteCnt > SKEIN1024_BLOCK_BYTES) {
646 /* number of full blocks to process */
647 n = (msgByteCnt - 1) / SKEIN1024_BLOCK_BYTES;
648 Skein1024_Process_Block(ctx, msg, n,
649 SKEIN1024_BLOCK_BYTES);
650 msgByteCnt -= n * SKEIN1024_BLOCK_BYTES;
651 msg += n * SKEIN1024_BLOCK_BYTES;
653 Skein_assert(ctx->h.bCnt == 0);
656 /* copy any remaining source message data bytes into b[] */
657 if (msgByteCnt) {
658 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES);
659 memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
660 ctx->h.bCnt += msgByteCnt;
663 return (SKEIN_SUCCESS);
666 /* finalize the hash computation and output the result */
668 Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
670 size_t i, n, byteCnt;
671 uint64_t X[SKEIN1024_STATE_WORDS];
673 /* catch uninitialized context */
674 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
676 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
677 /* zero pad b[] if necessary */
678 if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)
679 memset(&ctx->b[ctx->h.bCnt], 0,
680 SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
682 /* process the final block */
683 Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
685 /* now output the result */
686 /* total number of output bytes */
687 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
689 /* run Threefish in "counter mode" to generate output */
690 /* zero out b[], so it can hold the counter */
691 memset(ctx->b, 0, sizeof (ctx->b));
692 /* keep a local copy of counter mode "key" */
693 memcpy(X, ctx->X, sizeof (X));
694 for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) {
695 /* build the counter block */
696 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
697 Skein_Start_New_Type(ctx, OUT_FINAL);
698 /* run "counter mode" */
699 Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
700 /* number of output bytes left to go */
701 n = byteCnt - i * SKEIN1024_BLOCK_BYTES;
702 if (n >= SKEIN1024_BLOCK_BYTES)
703 n = SKEIN1024_BLOCK_BYTES;
704 Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES,
705 ctx->X, n); /* "output" the ctr mode bytes */
706 Skein_Show_Final(1024, &ctx->h, n,
707 hashVal + i * SKEIN1024_BLOCK_BYTES);
708 /* restore the counter mode key for next time */
709 memcpy(ctx->X, X, sizeof (X));
711 return (SKEIN_SUCCESS);
714 /* Functions to support MAC/tree hashing */
715 /* (this code is identical for Optimized and Reference versions) */
717 /* finalize the hash computation and output the block, no OUTPUT stage */
719 Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
721 /* catch uninitialized context */
722 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
724 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
725 /* zero pad b[] if necessary */
726 if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)
727 memset(&ctx->b[ctx->h.bCnt], 0,
728 SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
729 /* process the final block */
730 Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
732 /* "output" the state bytes */
733 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_256_BLOCK_BYTES);
735 return (SKEIN_SUCCESS);
738 /* finalize the hash computation and output the block, no OUTPUT stage */
740 Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
742 /* catch uninitialized context */
743 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
745 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
746 /* zero pad b[] if necessary */
747 if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
748 memset(&ctx->b[ctx->h.bCnt], 0,
749 SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
750 /* process the final block */
751 Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
753 /* "output" the state bytes */
754 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_512_BLOCK_BYTES);
756 return (SKEIN_SUCCESS);
759 /* finalize the hash computation and output the block, no OUTPUT stage */
761 Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
763 /* catch uninitialized context */
764 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
766 /* tag as the final block */
767 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;
768 /* zero pad b[] if necessary */
769 if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)
770 memset(&ctx->b[ctx->h.bCnt], 0,
771 SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
772 /* process the final block */
773 Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
775 /* "output" the state bytes */
776 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN1024_BLOCK_BYTES);
778 return (SKEIN_SUCCESS);
781 #if SKEIN_TREE_HASH
782 /* just do the OUTPUT stage */
784 Skein_256_Output(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
786 size_t i, n, byteCnt;
787 uint64_t X[SKEIN_256_STATE_WORDS];
789 /* catch uninitialized context */
790 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
792 /* now output the result */
793 /* total number of output bytes */
794 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
796 /* run Threefish in "counter mode" to generate output */
797 /* zero out b[], so it can hold the counter */
798 memset(ctx->b, 0, sizeof (ctx->b));
799 /* keep a local copy of counter mode "key" */
800 memcpy(X, ctx->X, sizeof (X));
801 for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) {
802 /* build the counter block */
803 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
804 Skein_Start_New_Type(ctx, OUT_FINAL);
805 /* run "counter mode" */
806 Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
807 /* number of output bytes left to go */
808 n = byteCnt - i * SKEIN_256_BLOCK_BYTES;
809 if (n >= SKEIN_256_BLOCK_BYTES)
810 n = SKEIN_256_BLOCK_BYTES;
811 Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES,
812 ctx->X, n); /* "output" the ctr mode bytes */
813 Skein_Show_Final(256, &ctx->h, n,
814 hashVal + i * SKEIN_256_BLOCK_BYTES);
815 /* restore the counter mode key for next time */
816 memcpy(ctx->X, X, sizeof (X));
818 return (SKEIN_SUCCESS);
821 /* just do the OUTPUT stage */
823 Skein_512_Output(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
825 size_t i, n, byteCnt;
826 uint64_t X[SKEIN_512_STATE_WORDS];
828 /* catch uninitialized context */
829 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
831 /* now output the result */
832 /* total number of output bytes */
833 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
835 /* run Threefish in "counter mode" to generate output */
836 /* zero out b[], so it can hold the counter */
837 memset(ctx->b, 0, sizeof (ctx->b));
838 /* keep a local copy of counter mode "key" */
839 memcpy(X, ctx->X, sizeof (X));
840 for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) {
841 /* build the counter block */
842 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
843 Skein_Start_New_Type(ctx, OUT_FINAL);
844 /* run "counter mode" */
845 Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
846 /* number of output bytes left to go */
847 n = byteCnt - i * SKEIN_512_BLOCK_BYTES;
848 if (n >= SKEIN_512_BLOCK_BYTES)
849 n = SKEIN_512_BLOCK_BYTES;
850 Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES,
851 ctx->X, n); /* "output" the ctr mode bytes */
852 Skein_Show_Final(256, &ctx->h, n,
853 hashVal + i * SKEIN_512_BLOCK_BYTES);
854 /* restore the counter mode key for next time */
855 memcpy(ctx->X, X, sizeof (X));
857 return (SKEIN_SUCCESS);
860 /* just do the OUTPUT stage */
862 Skein1024_Output(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
864 size_t i, n, byteCnt;
865 uint64_t X[SKEIN1024_STATE_WORDS];
867 /* catch uninitialized context */
868 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
870 /* now output the result */
871 /* total number of output bytes */
872 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
874 /* run Threefish in "counter mode" to generate output */
875 /* zero out b[], so it can hold the counter */
876 memset(ctx->b, 0, sizeof (ctx->b));
877 /* keep a local copy of counter mode "key" */
878 memcpy(X, ctx->X, sizeof (X));
879 for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) {
880 /* build the counter block */
881 *(uint64_t *)ctx->b = Skein_Swap64((uint64_t)i);
882 Skein_Start_New_Type(ctx, OUT_FINAL);
883 /* run "counter mode" */
884 Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
885 /* number of output bytes left to go */
886 n = byteCnt - i * SKEIN1024_BLOCK_BYTES;
887 if (n >= SKEIN1024_BLOCK_BYTES)
888 n = SKEIN1024_BLOCK_BYTES;
889 Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES,
890 ctx->X, n); /* "output" the ctr mode bytes */
891 Skein_Show_Final(256, &ctx->h, n,
892 hashVal + i * SKEIN1024_BLOCK_BYTES);
893 /* restore the counter mode key for next time */
894 memcpy(ctx->X, X, sizeof (X));
896 return (SKEIN_SUCCESS);
898 #endif
900 #ifdef _KERNEL
901 EXPORT_SYMBOL(Skein_512_Init);
902 EXPORT_SYMBOL(Skein_512_InitExt);
903 EXPORT_SYMBOL(Skein_512_Update);
904 EXPORT_SYMBOL(Skein_512_Final);
905 #endif