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