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