4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R
[illumos-gate.git] / usr / src / common / crypto / skein / skein.c
blob00421fdf6687b7e289daf28902c7c795fa8de75b
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 #define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */
10 #include <sys/types.h>
11 #include <sys/note.h>
12 #include <sys/skein.h> /* get the Skein API definitions */
13 #include "skein_impl.h" /* get internal definitions */
15 /* External function to process blkCnt (nonzero) full block(s) of data. */
16 void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx, const uint8_t *blkPtr,
17 size_t blkCnt, size_t byteCntAdd);
18 void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx, const uint8_t *blkPtr,
19 size_t blkCnt, size_t byteCntAdd);
20 void Skein1024_Process_Block(Skein1024_Ctxt_t *ctx, const uint8_t *blkPtr,
21 size_t blkCnt, size_t byteCntAdd);
23 /* 256-bit Skein */
24 /* init the context for a straight hashing operation */
25 int
26 Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen)
28 union {
29 uint8_t b[SKEIN_256_STATE_BYTES];
30 uint64_t w[SKEIN_256_STATE_WORDS];
31 } cfg; /* config block */
33 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
34 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
36 switch (hashBitLen) { /* use pre-computed values, where available */
37 #ifndef SKEIN_NO_PRECOMP
38 case 256:
39 bcopy(SKEIN_256_IV_256, ctx->X, sizeof (ctx->X));
40 break;
41 case 224:
42 bcopy(SKEIN_256_IV_224, ctx->X, sizeof (ctx->X));
43 break;
44 case 160:
45 bcopy(SKEIN_256_IV_160, ctx->X, sizeof (ctx->X));
46 break;
47 case 128:
48 bcopy(SKEIN_256_IV_128, ctx->X, sizeof (ctx->X));
49 break;
50 #endif
51 default:
52 /* here if there is no precomputed IV value available */
54 * build/process the config block, type == CONFIG (could be
55 * precomputed)
57 /* set tweaks: T0=0; T1=CFG | FINAL */
58 Skein_Start_New_Type(ctx, CFG_FINAL);
60 /* set the schema, version */
61 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
62 /* hash result length in bits */
63 cfg.w[1] = Skein_Swap64(hashBitLen);
64 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
65 /* zero pad config block */
66 bzero(&cfg.w[3], sizeof (cfg) - 3 * sizeof (cfg.w[0]));
68 /* compute the initial chaining values from config block */
69 /* zero the chaining variables */
70 bzero(ctx->X, sizeof (ctx->X));
71 Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
72 break;
75 * The chaining vars ctx->X are now initialized for the given
76 * hashBitLen.
77 * Set up to process the data message portion of the hash (default)
79 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
81 return (SKEIN_SUCCESS);
84 /* init the context for a MAC and/or tree hash operation */
86 * [identical to Skein_256_Init() when keyBytes == 0 &&
87 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
89 int
90 Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
91 const uint8_t *key, size_t keyBytes)
93 union {
94 uint8_t b[SKEIN_256_STATE_BYTES];
95 uint64_t w[SKEIN_256_STATE_WORDS];
96 } cfg; /* config block */
98 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
99 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
101 /* compute the initial chaining values ctx->X[], based on key */
102 if (keyBytes == 0) { /* is there a key? */
103 /* no key: use all zeroes as key for config block */
104 bzero(ctx->X, sizeof (ctx->X));
105 } else { /* here to pre-process a key */
107 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
108 /* do a mini-Init right here */
109 /* set output hash bit count = state size */
110 ctx->h.hashBitLen = 8 * sizeof (ctx->X);
111 /* set tweaks: T0 = 0; T1 = KEY type */
112 Skein_Start_New_Type(ctx, KEY);
113 /* zero the initial chaining variables */
114 bzero(ctx->X, sizeof (ctx->X));
115 /* hash the key */
116 (void) Skein_256_Update(ctx, key, keyBytes);
117 /* put result into cfg.b[] */
118 (void) Skein_256_Final_Pad(ctx, cfg.b);
119 /* copy over into ctx->X[] */
120 bcopy(cfg.b, ctx->X, sizeof (cfg.b));
121 #if SKEIN_NEED_SWAP
123 uint_t i;
124 /* convert key bytes to context words */
125 for (i = 0; i < SKEIN_256_STATE_WORDS; i++)
126 ctx->X[i] = Skein_Swap64(ctx->X[i]);
128 #endif
131 * build/process the config block, type == CONFIG (could be
132 * precomputed for each key)
134 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
135 Skein_Start_New_Type(ctx, CFG_FINAL);
137 bzero(&cfg.w, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
138 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
139 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
140 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
141 cfg.w[2] = Skein_Swap64(treeInfo);
143 Skein_Show_Key(256, &ctx->h, key, keyBytes);
145 /* compute the initial chaining values from config block */
146 Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
148 /* The chaining vars ctx->X are now initialized */
149 /* Set up to process the data message portion of the hash (default) */
150 ctx->h.bCnt = 0; /* buffer b[] starts out empty */
151 Skein_Start_New_Type(ctx, MSG);
153 return (SKEIN_SUCCESS);
156 /* process the input bytes */
158 Skein_256_Update(Skein_256_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
160 size_t n;
162 /* catch uninitialized context */
163 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
165 /* process full blocks, if any */
166 if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES) {
167 /* finish up any buffered message data */
168 if (ctx->h.bCnt) {
169 /* # bytes free in buffer b[] */
170 n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt;
171 if (n) {
172 /* check on our logic here */
173 Skein_assert(n < msgByteCnt);
174 bcopy(msg, &ctx->b[ctx->h.bCnt], n);
175 msgByteCnt -= n;
176 msg += n;
177 ctx->h.bCnt += n;
179 Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES);
180 Skein_256_Process_Block(ctx, ctx->b, 1,
181 SKEIN_256_BLOCK_BYTES);
182 ctx->h.bCnt = 0;
185 * now process any remaining full blocks, directly from input
186 * message data
188 if (msgByteCnt > SKEIN_256_BLOCK_BYTES) {
189 /* number of full blocks to process */
190 n = (msgByteCnt - 1) / SKEIN_256_BLOCK_BYTES;
191 Skein_256_Process_Block(ctx, msg, n,
192 SKEIN_256_BLOCK_BYTES);
193 msgByteCnt -= n * SKEIN_256_BLOCK_BYTES;
194 msg += n * SKEIN_256_BLOCK_BYTES;
196 Skein_assert(ctx->h.bCnt == 0);
199 /* copy any remaining source message data bytes into b[] */
200 if (msgByteCnt) {
201 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES);
202 bcopy(msg, &ctx->b[ctx->h.bCnt], msgByteCnt);
203 ctx->h.bCnt += msgByteCnt;
206 return (SKEIN_SUCCESS);
209 /* finalize the hash computation and output the result */
211 Skein_256_Final(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
213 size_t i, n, byteCnt;
214 uint64_t X[SKEIN_256_STATE_WORDS];
216 /* catch uninitialized context */
217 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
219 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
220 /* zero pad b[] if necessary */
221 if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)
222 bzero(&ctx->b[ctx->h.bCnt],
223 SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
225 /* process the final block */
226 Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
228 /* now output the result */
229 /* total number of output bytes */
230 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
232 /* run Threefish in "counter mode" to generate output */
233 /* zero out b[], so it can hold the counter */
234 bzero(ctx->b, sizeof (ctx->b));
235 /* keep a local copy of counter mode "key" */
236 bcopy(ctx->X, X, sizeof (X));
237 for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) {
238 /* build the counter block */
239 uint64_t tmp = Skein_Swap64((uint64_t)i);
240 bcopy(&tmp, ctx->b, sizeof (tmp));
241 Skein_Start_New_Type(ctx, OUT_FINAL);
242 /* run "counter mode" */
243 Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
244 /* number of output bytes left to go */
245 n = byteCnt - i * SKEIN_256_BLOCK_BYTES;
246 if (n >= SKEIN_256_BLOCK_BYTES)
247 n = SKEIN_256_BLOCK_BYTES;
248 Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES,
249 ctx->X, n); /* "output" the ctr mode bytes */
250 Skein_Show_Final(256, &ctx->h, n,
251 hashVal + i * SKEIN_256_BLOCK_BYTES);
252 /* restore the counter mode key for next time */
253 bcopy(X, ctx->X, sizeof (X));
255 return (SKEIN_SUCCESS);
258 /* 512-bit Skein */
260 /* init the context for a straight hashing operation */
262 Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
264 union {
265 uint8_t b[SKEIN_512_STATE_BYTES];
266 uint64_t w[SKEIN_512_STATE_WORDS];
267 } cfg; /* config block */
269 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
270 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
272 switch (hashBitLen) { /* use pre-computed values, where available */
273 #ifndef SKEIN_NO_PRECOMP
274 case 512:
275 bcopy(SKEIN_512_IV_512, ctx->X, sizeof (ctx->X));
276 break;
277 case 384:
278 bcopy(SKEIN_512_IV_384, ctx->X, sizeof (ctx->X));
279 break;
280 case 256:
281 bcopy(SKEIN_512_IV_256, ctx->X, sizeof (ctx->X));
282 break;
283 case 224:
284 bcopy(SKEIN_512_IV_224, ctx->X, sizeof (ctx->X));
285 break;
286 #endif
287 default:
289 * here if there is no precomputed IV value available
290 * build/process the config block, type == CONFIG (could be
291 * precomputed)
293 /* set tweaks: T0=0; T1=CFG | FINAL */
294 Skein_Start_New_Type(ctx, CFG_FINAL);
296 /* set the schema, version */
297 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
298 /* hash result length in bits */
299 cfg.w[1] = Skein_Swap64(hashBitLen);
300 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
301 /* zero pad config block */
302 bzero(&cfg.w[3], sizeof (cfg) - 3 * sizeof (cfg.w[0]));
304 /* compute the initial chaining values from config block */
305 /* zero the chaining variables */
306 bzero(ctx->X, sizeof (ctx->X));
307 Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
308 break;
312 * The chaining vars ctx->X are now initialized for the given
313 * hashBitLen. Set up to process the data message portion of the
314 * hash (default)
316 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
318 return (SKEIN_SUCCESS);
321 /* init the context for a MAC and/or tree hash operation */
323 * [identical to Skein_512_Init() when keyBytes == 0 &&
324 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
327 Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
328 const uint8_t *key, size_t keyBytes)
330 union {
331 uint8_t b[SKEIN_512_STATE_BYTES];
332 uint64_t w[SKEIN_512_STATE_WORDS];
333 } cfg; /* config block */
335 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
336 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
338 /* compute the initial chaining values ctx->X[], based on key */
339 if (keyBytes == 0) { /* is there a key? */
340 /* no key: use all zeroes as key for config block */
341 bzero(ctx->X, sizeof (ctx->X));
342 } else { /* here to pre-process a key */
344 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
345 /* do a mini-Init right here */
346 /* set output hash bit count = state size */
347 ctx->h.hashBitLen = 8 * sizeof (ctx->X);
348 /* set tweaks: T0 = 0; T1 = KEY type */
349 Skein_Start_New_Type(ctx, KEY);
350 /* zero the initial chaining variables */
351 bzero(ctx->X, sizeof (ctx->X));
352 (void) Skein_512_Update(ctx, key, keyBytes); /* hash the key */
353 /* put result into cfg.b[] */
354 (void) Skein_512_Final_Pad(ctx, cfg.b);
355 /* copy over into ctx->X[] */
356 bcopy(cfg.b, ctx->X, sizeof (cfg.b));
357 #if SKEIN_NEED_SWAP
359 uint_t i;
360 /* convert key bytes to context words */
361 for (i = 0; i < SKEIN_512_STATE_WORDS; i++)
362 ctx->X[i] = Skein_Swap64(ctx->X[i]);
364 #endif
367 * build/process the config block, type == CONFIG (could be
368 * precomputed for each key)
370 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
371 Skein_Start_New_Type(ctx, CFG_FINAL);
373 bzero(&cfg.w, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
374 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
375 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
376 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
377 cfg.w[2] = Skein_Swap64(treeInfo);
379 Skein_Show_Key(512, &ctx->h, key, keyBytes);
381 /* compute the initial chaining values from config block */
382 Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
384 /* The chaining vars ctx->X are now initialized */
385 /* Set up to process the data message portion of the hash (default) */
386 ctx->h.bCnt = 0; /* buffer b[] starts out empty */
387 Skein_Start_New_Type(ctx, MSG);
389 return (SKEIN_SUCCESS);
392 /* process the input bytes */
394 Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
396 size_t n;
398 /* catch uninitialized context */
399 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
401 /* process full blocks, if any */
402 if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) {
403 /* finish up any buffered message data */
404 if (ctx->h.bCnt) {
405 /* # bytes free in buffer b[] */
406 n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt;
407 if (n) {
408 /* check on our logic here */
409 Skein_assert(n < msgByteCnt);
410 bcopy(msg, &ctx->b[ctx->h.bCnt], n);
411 msgByteCnt -= n;
412 msg += n;
413 ctx->h.bCnt += n;
415 Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES);
416 Skein_512_Process_Block(ctx, ctx->b, 1,
417 SKEIN_512_BLOCK_BYTES);
418 ctx->h.bCnt = 0;
421 * now process any remaining full blocks, directly from input
422 * message data
424 if (msgByteCnt > SKEIN_512_BLOCK_BYTES) {
425 /* number of full blocks to process */
426 n = (msgByteCnt - 1) / SKEIN_512_BLOCK_BYTES;
427 Skein_512_Process_Block(ctx, msg, n,
428 SKEIN_512_BLOCK_BYTES);
429 msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
430 msg += n * SKEIN_512_BLOCK_BYTES;
432 Skein_assert(ctx->h.bCnt == 0);
435 /* copy any remaining source message data bytes into b[] */
436 if (msgByteCnt) {
437 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES);
438 bcopy(msg, &ctx->b[ctx->h.bCnt], msgByteCnt);
439 ctx->h.bCnt += msgByteCnt;
442 return (SKEIN_SUCCESS);
445 /* finalize the hash computation and output the result */
447 Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
449 size_t i, n, byteCnt;
450 uint64_t X[SKEIN_512_STATE_WORDS];
452 /* catch uninitialized context */
453 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
455 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
456 /* zero pad b[] if necessary */
457 if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
458 bzero(&ctx->b[ctx->h.bCnt],
459 SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
461 /* process the final block */
462 Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
464 /* now output the result */
465 /* total number of output bytes */
466 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
468 /* run Threefish in "counter mode" to generate output */
469 /* zero out b[], so it can hold the counter */
470 bzero(ctx->b, sizeof (ctx->b));
471 /* keep a local copy of counter mode "key" */
472 bcopy(ctx->X, X, sizeof (X));
473 for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) {
474 /* build the counter block */
475 uint64_t tmp = Skein_Swap64((uint64_t)i);
476 bcopy(&tmp, ctx->b, sizeof (tmp));
477 Skein_Start_New_Type(ctx, OUT_FINAL);
478 /* run "counter mode" */
479 Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
480 /* number of output bytes left to go */
481 n = byteCnt - i * SKEIN_512_BLOCK_BYTES;
482 if (n >= SKEIN_512_BLOCK_BYTES)
483 n = SKEIN_512_BLOCK_BYTES;
484 Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES,
485 ctx->X, n); /* "output" the ctr mode bytes */
486 Skein_Show_Final(512, &ctx->h, n,
487 hashVal + i * SKEIN_512_BLOCK_BYTES);
488 /* restore the counter mode key for next time */
489 bcopy(X, ctx->X, sizeof (X));
491 return (SKEIN_SUCCESS);
494 /* 1024-bit Skein */
496 /* init the context for a straight hashing operation */
498 Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen)
500 union {
501 uint8_t b[SKEIN1024_STATE_BYTES];
502 uint64_t w[SKEIN1024_STATE_WORDS];
503 } cfg; /* config block */
505 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
506 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
508 switch (hashBitLen) { /* use pre-computed values, where available */
509 #ifndef SKEIN_NO_PRECOMP
510 case 512:
511 bcopy(SKEIN1024_IV_512, ctx->X, sizeof (ctx->X));
512 break;
513 case 384:
514 bcopy(SKEIN1024_IV_384, ctx->X, sizeof (ctx->X));
515 break;
516 case 1024:
517 bcopy(SKEIN1024_IV_1024, ctx->X, sizeof (ctx->X));
518 break;
519 #endif
520 default:
521 /* here if there is no precomputed IV value available */
523 * build/process the config block, type == CONFIG (could be
524 * precomputed)
526 /* set tweaks: T0=0; T1=CFG | FINAL */
527 Skein_Start_New_Type(ctx, CFG_FINAL);
529 /* set the schema, version */
530 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
531 /* hash result length in bits */
532 cfg.w[1] = Skein_Swap64(hashBitLen);
533 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
534 /* zero pad config block */
535 bzero(&cfg.w[3], sizeof (cfg) - 3 * sizeof (cfg.w[0]));
537 /* compute the initial chaining values from config block */
538 /* zero the chaining variables */
539 bzero(ctx->X, sizeof (ctx->X));
540 Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
541 break;
545 * The chaining vars ctx->X are now initialized for the given
546 * hashBitLen. Set up to process the data message portion of the hash
547 * (default)
549 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
551 return (SKEIN_SUCCESS);
554 /* init the context for a MAC and/or tree hash operation */
556 * [identical to Skein1024_Init() when keyBytes == 0 &&
557 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
560 Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
561 const uint8_t *key, size_t keyBytes)
563 union {
564 uint8_t b[SKEIN1024_STATE_BYTES];
565 uint64_t w[SKEIN1024_STATE_WORDS];
566 } cfg; /* config block */
568 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
569 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
571 /* compute the initial chaining values ctx->X[], based on key */
572 if (keyBytes == 0) { /* is there a key? */
573 /* no key: use all zeroes as key for config block */
574 bzero(ctx->X, sizeof (ctx->X));
575 } else { /* here to pre-process a key */
576 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X));
577 /* do a mini-Init right here */
578 /* set output hash bit count = state size */
579 ctx->h.hashBitLen = 8 * sizeof (ctx->X);
580 /* set tweaks: T0 = 0; T1 = KEY type */
581 Skein_Start_New_Type(ctx, KEY);
582 /* zero the initial chaining variables */
583 bzero(ctx->X, sizeof (ctx->X));
584 (void) Skein1024_Update(ctx, key, keyBytes); /* hash the key */
585 /* put result into cfg.b[] */
586 (void) Skein1024_Final_Pad(ctx, cfg.b);
587 /* copy over into ctx->X[] */
588 bcopy(cfg.b, ctx->X, sizeof (cfg.b));
589 #if SKEIN_NEED_SWAP
591 uint_t i;
592 /* convert key bytes to context words */
593 for (i = 0; i < SKEIN1024_STATE_WORDS; i++)
594 ctx->X[i] = Skein_Swap64(ctx->X[i]);
596 #endif
599 * build/process the config block, type == CONFIG (could be
600 * precomputed for each key)
602 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
603 Skein_Start_New_Type(ctx, CFG_FINAL);
605 bzero(&cfg.w, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */
606 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
607 /* hash result length in bits */
608 cfg.w[1] = Skein_Swap64(hashBitLen);
609 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
610 cfg.w[2] = Skein_Swap64(treeInfo);
612 Skein_Show_Key(1024, &ctx->h, key, keyBytes);
614 /* compute the initial chaining values from config block */
615 Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
617 /* The chaining vars ctx->X are now initialized */
618 /* Set up to process the data message portion of the hash (default) */
619 ctx->h.bCnt = 0; /* buffer b[] starts out empty */
620 Skein_Start_New_Type(ctx, MSG);
622 return (SKEIN_SUCCESS);
625 /* process the input bytes */
627 Skein1024_Update(Skein1024_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
629 size_t n;
631 /* catch uninitialized context */
632 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
634 /* process full blocks, if any */
635 if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES) {
636 /* finish up any buffered message data */
637 if (ctx->h.bCnt) {
638 /* # bytes free in buffer b[] */
639 n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt;
640 if (n) {
641 /* check on our logic here */
642 Skein_assert(n < msgByteCnt);
643 bcopy(msg, &ctx->b[ctx->h.bCnt], n);
644 msgByteCnt -= n;
645 msg += n;
646 ctx->h.bCnt += n;
648 Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES);
649 Skein1024_Process_Block(ctx, ctx->b, 1,
650 SKEIN1024_BLOCK_BYTES);
651 ctx->h.bCnt = 0;
654 * now process any remaining full blocks, directly from
655 * input message data
657 if (msgByteCnt > SKEIN1024_BLOCK_BYTES) {
658 /* number of full blocks to process */
659 n = (msgByteCnt - 1) / SKEIN1024_BLOCK_BYTES;
660 Skein1024_Process_Block(ctx, msg, n,
661 SKEIN1024_BLOCK_BYTES);
662 msgByteCnt -= n * SKEIN1024_BLOCK_BYTES;
663 msg += n * SKEIN1024_BLOCK_BYTES;
665 Skein_assert(ctx->h.bCnt == 0);
668 /* copy any remaining source message data bytes into b[] */
669 if (msgByteCnt) {
670 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES);
671 bcopy(msg, &ctx->b[ctx->h.bCnt], msgByteCnt);
672 ctx->h.bCnt += msgByteCnt;
675 return (SKEIN_SUCCESS);
678 /* finalize the hash computation and output the result */
680 Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
682 size_t i, n, byteCnt;
683 uint64_t X[SKEIN1024_STATE_WORDS];
685 /* catch uninitialized context */
686 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
688 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
689 /* zero pad b[] if necessary */
690 if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)
691 bzero(&ctx->b[ctx->h.bCnt],
692 SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
694 /* process the final block */
695 Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
697 /* now output the result */
698 /* total number of output bytes */
699 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
701 /* run Threefish in "counter mode" to generate output */
702 /* zero out b[], so it can hold the counter */
703 bzero(ctx->b, sizeof (ctx->b));
704 /* keep a local copy of counter mode "key" */
705 bcopy(ctx->X, X, sizeof (X));
706 for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) {
707 /* build the counter block */
708 uint64_t tmp = Skein_Swap64((uint64_t)i);
709 bcopy(&tmp, ctx->b, sizeof (tmp));
710 Skein_Start_New_Type(ctx, OUT_FINAL);
711 /* run "counter mode" */
712 Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
713 /* number of output bytes left to go */
714 n = byteCnt - i * SKEIN1024_BLOCK_BYTES;
715 if (n >= SKEIN1024_BLOCK_BYTES)
716 n = SKEIN1024_BLOCK_BYTES;
717 Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES,
718 ctx->X, n); /* "output" the ctr mode bytes */
719 Skein_Show_Final(1024, &ctx->h, n,
720 hashVal + i * SKEIN1024_BLOCK_BYTES);
721 /* restore the counter mode key for next time */
722 bcopy(X, ctx->X, sizeof (X));
724 return (SKEIN_SUCCESS);
727 /* Functions to support MAC/tree hashing */
728 /* (this code is identical for Optimized and Reference versions) */
730 /* finalize the hash computation and output the block, no OUTPUT stage */
732 Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
734 /* catch uninitialized context */
735 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
737 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
738 /* zero pad b[] if necessary */
739 if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES)
740 bzero(&ctx->b[ctx->h.bCnt],
741 SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
742 /* process the final block */
743 Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
745 /* "output" the state bytes */
746 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_256_BLOCK_BYTES);
748 return (SKEIN_SUCCESS);
751 /* finalize the hash computation and output the block, no OUTPUT stage */
753 Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
755 /* catch uninitialized context */
756 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
758 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
759 /* zero pad b[] if necessary */
760 if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES)
761 bzero(&ctx->b[ctx->h.bCnt],
762 SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
763 /* process the final block */
764 Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
766 /* "output" the state bytes */
767 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_512_BLOCK_BYTES);
769 return (SKEIN_SUCCESS);
772 /* finalize the hash computation and output the block, no OUTPUT stage */
774 Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
776 /* catch uninitialized context */
777 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
779 /* tag as the final block */
780 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL;
781 /* zero pad b[] if necessary */
782 if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES)
783 bzero(&ctx->b[ctx->h.bCnt],
784 SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
785 /* process the final block */
786 Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
788 /* "output" the state bytes */
789 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN1024_BLOCK_BYTES);
791 return (SKEIN_SUCCESS);
794 #if SKEIN_TREE_HASH
795 /* just do the OUTPUT stage */
797 Skein_256_Output(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
799 size_t i, n, byteCnt;
800 uint64_t X[SKEIN_256_STATE_WORDS];
802 /* catch uninitialized context */
803 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
805 /* now output the result */
806 /* total number of output bytes */
807 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
809 /* run Threefish in "counter mode" to generate output */
810 /* zero out b[], so it can hold the counter */
811 bzero(ctx->b, sizeof (ctx->b));
812 /* keep a local copy of counter mode "key" */
813 bcopy(ctx->X, X, sizeof (X));
814 for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) {
815 /* build the counter block */
816 uint64_t tmp = Skein_Swap64((uint64_t)i);
817 bcopy(&tmp, ctx->b, sizeof (tmp));
818 Skein_Start_New_Type(ctx, OUT_FINAL);
819 /* run "counter mode" */
820 Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
821 /* number of output bytes left to go */
822 n = byteCnt - i * SKEIN_256_BLOCK_BYTES;
823 if (n >= SKEIN_256_BLOCK_BYTES)
824 n = SKEIN_256_BLOCK_BYTES;
825 Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES,
826 ctx->X, n); /* "output" the ctr mode bytes */
827 Skein_Show_Final(256, &ctx->h, n,
828 hashVal + i * SKEIN_256_BLOCK_BYTES);
829 /* restore the counter mode key for next time */
830 bcopy(X, ctx->X, sizeof (X));
832 return (SKEIN_SUCCESS);
835 /* just do the OUTPUT stage */
837 Skein_512_Output(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
839 size_t i, n, byteCnt;
840 uint64_t X[SKEIN_512_STATE_WORDS];
842 /* catch uninitialized context */
843 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
845 /* now output the result */
846 /* total number of output bytes */
847 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
849 /* run Threefish in "counter mode" to generate output */
850 /* zero out b[], so it can hold the counter */
851 bzero(ctx->b, sizeof (ctx->b));
852 /* keep a local copy of counter mode "key" */
853 bcopy(ctx->X, X, sizeof (X));
854 for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) {
855 /* build the counter block */
856 uint64_t tmp = Skein_Swap64((uint64_t)i);
857 bcopy(&tmp, ctx->b, sizeof (tmp));
858 Skein_Start_New_Type(ctx, OUT_FINAL);
859 /* run "counter mode" */
860 Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
861 /* number of output bytes left to go */
862 n = byteCnt - i * SKEIN_512_BLOCK_BYTES;
863 if (n >= SKEIN_512_BLOCK_BYTES)
864 n = SKEIN_512_BLOCK_BYTES;
865 Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES,
866 ctx->X, n); /* "output" the ctr mode bytes */
867 Skein_Show_Final(256, &ctx->h, n,
868 hashVal + i * SKEIN_512_BLOCK_BYTES);
869 /* restore the counter mode key for next time */
870 bcopy(X, ctx->X, sizeof (X));
872 return (SKEIN_SUCCESS);
875 /* just do the OUTPUT stage */
877 Skein1024_Output(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
879 size_t i, n, byteCnt;
880 uint64_t X[SKEIN1024_STATE_WORDS];
882 /* catch uninitialized context */
883 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
885 /* now output the result */
886 /* total number of output bytes */
887 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
889 /* run Threefish in "counter mode" to generate output */
890 /* zero out b[], so it can hold the counter */
891 bzero(ctx->b, sizeof (ctx->b));
892 /* keep a local copy of counter mode "key" */
893 bcopy(ctx->X, X, sizeof (X));
894 for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) {
895 /* build the counter block */
896 uint64_t tmp = Skein_Swap64((uint64_t)i);
897 bcopy(&tmp, ctx->b, sizeof (tmp));
898 Skein_Start_New_Type(ctx, OUT_FINAL);
899 /* run "counter mode" */
900 Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t));
901 /* number of output bytes left to go */
902 n = byteCnt - i * SKEIN1024_BLOCK_BYTES;
903 if (n >= SKEIN1024_BLOCK_BYTES)
904 n = SKEIN1024_BLOCK_BYTES;
905 Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES,
906 ctx->X, n); /* "output" the ctr mode bytes */
907 Skein_Show_Final(256, &ctx->h, n,
908 hashVal + i * SKEIN1024_BLOCK_BYTES);
909 /* restore the counter mode key for next time */
910 bcopy(X, ctx->X, sizeof (X));
912 return (SKEIN_SUCCESS);
914 #endif