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