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