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.
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>
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
);
24 /* init the context for a straight hashing operation */
26 Skein_256_Init(Skein_256_Ctxt_t
*ctx
, size_t hashBitLen
)
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
39 bcopy(SKEIN_256_IV_256
, ctx
->X
, sizeof (ctx
->X
));
42 bcopy(SKEIN_256_IV_224
, ctx
->X
, sizeof (ctx
->X
));
45 bcopy(SKEIN_256_IV_160
, ctx
->X
, sizeof (ctx
->X
));
48 bcopy(SKEIN_256_IV_128
, ctx
->X
, sizeof (ctx
->X
));
52 /* here if there is no precomputed IV value available */
54 * build/process the config block, type == CONFIG (could be
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
);
75 * The chaining vars ctx->X are now initialized for the given
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]
90 Skein_256_InitExt(Skein_256_Ctxt_t
*ctx
, size_t hashBitLen
, uint64_t treeInfo
,
91 const uint8_t *key
, size_t keyBytes
)
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
));
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
));
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
]);
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
)
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 */
169 /* # bytes free in buffer b[] */
170 n
= SKEIN_256_BLOCK_BYTES
- ctx
->h
.bCnt
;
172 /* check on our logic here */
173 Skein_assert(n
< msgByteCnt
);
174 bcopy(msg
, &ctx
->b
[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
);
185 * now process any remaining full blocks, directly from input
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[] */
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
);
260 /* init the context for a straight hashing operation */
262 Skein_512_Init(Skein_512_Ctxt_t
*ctx
, size_t hashBitLen
)
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
275 bcopy(SKEIN_512_IV_512
, ctx
->X
, sizeof (ctx
->X
));
278 bcopy(SKEIN_512_IV_384
, ctx
->X
, sizeof (ctx
->X
));
281 bcopy(SKEIN_512_IV_256
, ctx
->X
, sizeof (ctx
->X
));
284 bcopy(SKEIN_512_IV_224
, ctx
->X
, sizeof (ctx
->X
));
289 * here if there is no precomputed IV value available
290 * build/process the config block, type == CONFIG (could be
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
);
312 * The chaining vars ctx->X are now initialized for the given
313 * hashBitLen. Set up to process the data message portion of the
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
)
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
));
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
]);
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
)
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 */
405 /* # bytes free in buffer b[] */
406 n
= SKEIN_512_BLOCK_BYTES
- ctx
->h
.bCnt
;
408 /* check on our logic here */
409 Skein_assert(n
< msgByteCnt
);
410 bcopy(msg
, &ctx
->b
[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
);
421 * now process any remaining full blocks, directly from input
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[] */
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
);
496 /* init the context for a straight hashing operation */
498 Skein1024_Init(Skein1024_Ctxt_t
*ctx
, size_t hashBitLen
)
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
511 bcopy(SKEIN1024_IV_512
, ctx
->X
, sizeof (ctx
->X
));
514 bcopy(SKEIN1024_IV_384
, ctx
->X
, sizeof (ctx
->X
));
517 bcopy(SKEIN1024_IV_1024
, ctx
->X
, sizeof (ctx
->X
));
521 /* here if there is no precomputed IV value available */
523 * build/process the config block, type == CONFIG (could be
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
);
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
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
)
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
));
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
]);
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
)
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 */
638 /* # bytes free in buffer b[] */
639 n
= SKEIN1024_BLOCK_BYTES
- ctx
->h
.bCnt
;
641 /* check on our logic here */
642 Skein_assert(n
< msgByteCnt
);
643 bcopy(msg
, &ctx
->b
[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
);
654 * now process any remaining full blocks, directly from
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[] */
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
);
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
);