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