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
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);
22
23 /* 256-bit Skein */
24 /* init the context for a straight hashing operation */
25 int
Skein_256_Init(Skein_256_Ctxt_t * ctx,size_t hashBitLen)26 Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen)
27 {
28 union {
29 uint8_t b[SKEIN_256_STATE_BYTES];
30 uint64_t w[SKEIN_256_STATE_WORDS];
31 } cfg; /* config block */
32
33 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
34 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
35
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 */
53 /*
54 * build/process the config block, type == CONFIG (could be
55 * precomputed)
56 */
57 /* set tweaks: T0=0; T1=CFG | FINAL */
58 Skein_Start_New_Type(ctx, CFG_FINAL);
59
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]));
67
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;
73 }
74 /*
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)
78 */
79 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
80
81 return (SKEIN_SUCCESS);
82 }
83
84 /* init the context for a MAC and/or tree hash operation */
85 /*
86 * [identical to Skein_256_Init() when keyBytes == 0 &&
87 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
88 */
89 int
Skein_256_InitExt(Skein_256_Ctxt_t * ctx,size_t hashBitLen,uint64_t treeInfo,const uint8_t * key,size_t keyBytes)90 Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
91 const uint8_t *key, size_t keyBytes)
92 {
93 union {
94 uint8_t b[SKEIN_256_STATE_BYTES];
95 uint64_t w[SKEIN_256_STATE_WORDS];
96 } cfg; /* config block */
97
98 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
99 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
100
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 */
106
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
122 {
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]);
127 }
128 #endif
129 }
130 /*
131 * build/process the config block, type == CONFIG (could be
132 * precomputed for each key)
133 */
134 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
135 Skein_Start_New_Type(ctx, CFG_FINAL);
136
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);
142
143 Skein_Show_Key(256, &ctx->h, key, keyBytes);
144
145 /* compute the initial chaining values from config block */
146 Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
147
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);
152
153 return (SKEIN_SUCCESS);
154 }
155
156 /* process the input bytes */
157 int
Skein_256_Update(Skein_256_Ctxt_t * ctx,const uint8_t * msg,size_t msgByteCnt)158 Skein_256_Update(Skein_256_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
159 {
160 size_t n;
161
162 /* catch uninitialized context */
163 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
164
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;
178 }
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;
183 }
184 /*
185 * now process any remaining full blocks, directly from input
186 * message data
187 */
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;
195 }
196 Skein_assert(ctx->h.bCnt == 0);
197 }
198
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;
204 }
205
206 return (SKEIN_SUCCESS);
207 }
208
209 /* finalize the hash computation and output the result */
210 int
Skein_256_Final(Skein_256_Ctxt_t * ctx,uint8_t * hashVal)211 Skein_256_Final(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
212 {
213 size_t i, n, byteCnt;
214 uint64_t X[SKEIN_256_STATE_WORDS];
215
216 /* catch uninitialized context */
217 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
218
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);
224
225 /* process the final block */
226 Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
227
228 /* now output the result */
229 /* total number of output bytes */
230 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
231
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));
254 }
255 return (SKEIN_SUCCESS);
256 }
257
258 /* 512-bit Skein */
259
260 /* init the context for a straight hashing operation */
261 int
Skein_512_Init(Skein_512_Ctxt_t * ctx,size_t hashBitLen)262 Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
263 {
264 union {
265 uint8_t b[SKEIN_512_STATE_BYTES];
266 uint64_t w[SKEIN_512_STATE_WORDS];
267 } cfg; /* config block */
268
269 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
270 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
271
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:
288 /*
289 * here if there is no precomputed IV value available
290 * build/process the config block, type == CONFIG (could be
291 * precomputed)
292 */
293 /* set tweaks: T0=0; T1=CFG | FINAL */
294 Skein_Start_New_Type(ctx, CFG_FINAL);
295
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]));
303
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;
309 }
310
311 /*
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)
315 */
316 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
317
318 return (SKEIN_SUCCESS);
319 }
320
321 /* init the context for a MAC and/or tree hash operation */
322 /*
323 * [identical to Skein_512_Init() when keyBytes == 0 &&
324 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
325 */
326 int
Skein_512_InitExt(Skein_512_Ctxt_t * ctx,size_t hashBitLen,uint64_t treeInfo,const uint8_t * key,size_t keyBytes)327 Skein_512_InitExt(Skein_512_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
328 const uint8_t *key, size_t keyBytes)
329 {
330 union {
331 uint8_t b[SKEIN_512_STATE_BYTES];
332 uint64_t w[SKEIN_512_STATE_WORDS];
333 } cfg; /* config block */
334
335 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
336 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
337
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 */
343
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
358 {
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]);
363 }
364 #endif
365 }
366 /*
367 * build/process the config block, type == CONFIG (could be
368 * precomputed for each key)
369 */
370 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
371 Skein_Start_New_Type(ctx, CFG_FINAL);
372
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);
378
379 Skein_Show_Key(512, &ctx->h, key, keyBytes);
380
381 /* compute the initial chaining values from config block */
382 Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
383
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);
388
389 return (SKEIN_SUCCESS);
390 }
391
392 /* process the input bytes */
393 int
Skein_512_Update(Skein_512_Ctxt_t * ctx,const uint8_t * msg,size_t msgByteCnt)394 Skein_512_Update(Skein_512_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
395 {
396 size_t n;
397
398 /* catch uninitialized context */
399 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
400
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;
414 }
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;
419 }
420 /*
421 * now process any remaining full blocks, directly from input
422 * message data
423 */
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;
431 }
432 Skein_assert(ctx->h.bCnt == 0);
433 }
434
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;
440 }
441
442 return (SKEIN_SUCCESS);
443 }
444
445 /* finalize the hash computation and output the result */
446 int
Skein_512_Final(Skein_512_Ctxt_t * ctx,uint8_t * hashVal)447 Skein_512_Final(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
448 {
449 size_t i, n, byteCnt;
450 uint64_t X[SKEIN_512_STATE_WORDS];
451
452 /* catch uninitialized context */
453 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
454
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);
460
461 /* process the final block */
462 Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
463
464 /* now output the result */
465 /* total number of output bytes */
466 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
467
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));
490 }
491 return (SKEIN_SUCCESS);
492 }
493
494 /* 1024-bit Skein */
495
496 /* init the context for a straight hashing operation */
497 int
Skein1024_Init(Skein1024_Ctxt_t * ctx,size_t hashBitLen)498 Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen)
499 {
500 union {
501 uint8_t b[SKEIN1024_STATE_BYTES];
502 uint64_t w[SKEIN1024_STATE_WORDS];
503 } cfg; /* config block */
504
505 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
506 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
507
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 */
522 /*
523 * build/process the config block, type == CONFIG (could be
524 * precomputed)
525 */
526 /* set tweaks: T0=0; T1=CFG | FINAL */
527 Skein_Start_New_Type(ctx, CFG_FINAL);
528
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]));
536
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;
542 }
543
544 /*
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)
548 */
549 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
550
551 return (SKEIN_SUCCESS);
552 }
553
554 /* init the context for a MAC and/or tree hash operation */
555 /*
556 * [identical to Skein1024_Init() when keyBytes == 0 &&
557 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
558 */
559 int
Skein1024_InitExt(Skein1024_Ctxt_t * ctx,size_t hashBitLen,uint64_t treeInfo,const uint8_t * key,size_t keyBytes)560 Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo,
561 const uint8_t *key, size_t keyBytes)
562 {
563 union {
564 uint8_t b[SKEIN1024_STATE_BYTES];
565 uint64_t w[SKEIN1024_STATE_WORDS];
566 } cfg; /* config block */
567
568 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
569 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL);
570
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
590 {
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]);
595 }
596 #endif
597 }
598 /*
599 * build/process the config block, type == CONFIG (could be
600 * precomputed for each key)
601 */
602 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
603 Skein_Start_New_Type(ctx, CFG_FINAL);
604
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);
611
612 Skein_Show_Key(1024, &ctx->h, key, keyBytes);
613
614 /* compute the initial chaining values from config block */
615 Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
616
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);
621
622 return (SKEIN_SUCCESS);
623 }
624
625 /* process the input bytes */
626 int
Skein1024_Update(Skein1024_Ctxt_t * ctx,const uint8_t * msg,size_t msgByteCnt)627 Skein1024_Update(Skein1024_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt)
628 {
629 size_t n;
630
631 /* catch uninitialized context */
632 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
633
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;
647 }
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;
652 }
653 /*
654 * now process any remaining full blocks, directly from
655 * input message data
656 */
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;
664 }
665 Skein_assert(ctx->h.bCnt == 0);
666 }
667
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;
673 }
674
675 return (SKEIN_SUCCESS);
676 }
677
678 /* finalize the hash computation and output the result */
679 int
Skein1024_Final(Skein1024_Ctxt_t * ctx,uint8_t * hashVal)680 Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
681 {
682 size_t i, n, byteCnt;
683 uint64_t X[SKEIN1024_STATE_WORDS];
684
685 /* catch uninitialized context */
686 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
687
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);
693
694 /* process the final block */
695 Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt);
696
697 /* now output the result */
698 /* total number of output bytes */
699 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
700
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));
723 }
724 return (SKEIN_SUCCESS);
725 }
726
727 /* Functions to support MAC/tree hashing */
728 /* (this code is identical for Optimized and Reference versions) */
729
730 /* finalize the hash computation and output the block, no OUTPUT stage */
731 int
Skein_256_Final_Pad(Skein_256_Ctxt_t * ctx,uint8_t * hashVal)732 Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
733 {
734 /* catch uninitialized context */
735 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
736
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);
744
745 /* "output" the state bytes */
746 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_256_BLOCK_BYTES);
747
748 return (SKEIN_SUCCESS);
749 }
750
751 /* finalize the hash computation and output the block, no OUTPUT stage */
752 int
Skein_512_Final_Pad(Skein_512_Ctxt_t * ctx,uint8_t * hashVal)753 Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
754 {
755 /* catch uninitialized context */
756 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
757
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);
765
766 /* "output" the state bytes */
767 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_512_BLOCK_BYTES);
768
769 return (SKEIN_SUCCESS);
770 }
771
772 /* finalize the hash computation and output the block, no OUTPUT stage */
773 int
Skein1024_Final_Pad(Skein1024_Ctxt_t * ctx,uint8_t * hashVal)774 Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
775 {
776 /* catch uninitialized context */
777 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
778
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);
787
788 /* "output" the state bytes */
789 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN1024_BLOCK_BYTES);
790
791 return (SKEIN_SUCCESS);
792 }
793
794 #if SKEIN_TREE_HASH
795 /* just do the OUTPUT stage */
796 int
Skein_256_Output(Skein_256_Ctxt_t * ctx,uint8_t * hashVal)797 Skein_256_Output(Skein_256_Ctxt_t *ctx, uint8_t *hashVal)
798 {
799 size_t i, n, byteCnt;
800 uint64_t X[SKEIN_256_STATE_WORDS];
801
802 /* catch uninitialized context */
803 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
804
805 /* now output the result */
806 /* total number of output bytes */
807 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
808
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));
831 }
832 return (SKEIN_SUCCESS);
833 }
834
835 /* just do the OUTPUT stage */
836 int
Skein_512_Output(Skein_512_Ctxt_t * ctx,uint8_t * hashVal)837 Skein_512_Output(Skein_512_Ctxt_t *ctx, uint8_t *hashVal)
838 {
839 size_t i, n, byteCnt;
840 uint64_t X[SKEIN_512_STATE_WORDS];
841
842 /* catch uninitialized context */
843 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
844
845 /* now output the result */
846 /* total number of output bytes */
847 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
848
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));
871 }
872 return (SKEIN_SUCCESS);
873 }
874
875 /* just do the OUTPUT stage */
876 int
Skein1024_Output(Skein1024_Ctxt_t * ctx,uint8_t * hashVal)877 Skein1024_Output(Skein1024_Ctxt_t *ctx, uint8_t *hashVal)
878 {
879 size_t i, n, byteCnt;
880 uint64_t X[SKEIN1024_STATE_WORDS];
881
882 /* catch uninitialized context */
883 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL);
884
885 /* now output the result */
886 /* total number of output bytes */
887 byteCnt = (ctx->h.hashBitLen + 7) >> 3;
888
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));
911 }
912 return (SKEIN_SUCCESS);
913 }
914 #endif
915