1 /***********************************************************************
3 ** Implementation of the Skein hash function.
5 ** Source code author: Doug Whiting, 2008.
7 ** This algorithm and source code is released to the public domain.
9 ************************************************************************/
11 #include <sys/cdefs.h>
12 __FBSDID("$FreeBSD$");
14 #include <sys/endian.h>
15 #include <sys/types.h>
17 /* get the memcpy/memset functions */
19 #include <sys/systm.h>
24 #define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */
26 #include "skein.h" /* get the Skein API definitions */
27 #include "skein_iv.h" /* get precomputed IVs */
29 /*****************************************************************/
30 /* External function to process blkCnt (nonzero) full block(s) of data. */
31 void Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
32 void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
33 void Skein1024_Process_Block(Skein1024_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd);
35 /*****************************************************************/
37 /*****************************************************************/
39 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
40 /* init the context for a straight hashing operation */
41 int Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen)
45 u08b_t b[SKEIN_256_STATE_BYTES];
46 u64b_t w[SKEIN_256_STATE_WORDS];
47 } cfg; /* config block */
49 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
50 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
53 { /* use pre-computed values, where available */
54 #ifndef SKEIN_NO_PRECOMP
55 case 256: memcpy(ctx->X,SKEIN_256_IV_256,sizeof(ctx->X)); break;
56 case 224: memcpy(ctx->X,SKEIN_256_IV_224,sizeof(ctx->X)); break;
57 case 160: memcpy(ctx->X,SKEIN_256_IV_160,sizeof(ctx->X)); break;
58 case 128: memcpy(ctx->X,SKEIN_256_IV_128,sizeof(ctx->X)); break;
61 /* here if there is no precomputed IV value available */
62 /* build/process the config block, type == CONFIG (could be precomputed) */
63 Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */
65 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */
66 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
67 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
68 memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */
70 /* compute the initial chaining values from config block */
71 memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */
72 Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
75 /* The chaining vars ctx->X are now initialized for the given hashBitLen. */
76 /* Set up to process the data message portion of the hash (default) */
77 Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */
82 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
83 /* init the context for a MAC and/or tree hash operation */
84 /* [identical to Skein_256_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */
85 int Skein_256_InitExt(Skein_256_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes)
89 u08b_t b[SKEIN_256_STATE_BYTES];
90 u64b_t w[SKEIN_256_STATE_WORDS];
91 } cfg; /* config block */
93 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
94 Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);
96 /* compute the initial chaining values ctx->X[], based on key */
97 if (keyBytes == 0) /* is there a key? */
99 memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */
101 else /* here to pre-process a key */
103 Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X));
104 /* do a mini-Init right here */
105 ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */
106 Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */
107 memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */
108 Skein_256_Update(ctx,key,keyBytes); /* hash the key */
109 Skein_256_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */
110 memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */
114 for (i=0;i<SKEIN_256_STATE_WORDS;i++) /* convert key bytes to context words */
115 ctx->X[i] = Skein_Swap64(ctx->X[i]);
119 /* build/process the config block, type == CONFIG (could be precomputed for each key) */
120 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
121 Skein_Start_New_Type(ctx,CFG_FINAL);
123 memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */
124 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
125 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
126 cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
128 Skein_Show_Key(256,&ctx->h,key,keyBytes);
130 /* compute the initial chaining values from config block */
131 Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
133 /* The chaining vars ctx->X are now initialized */
134 /* Set up to process the data message portion of the hash (default) */
135 ctx->h.bCnt = 0; /* buffer b[] starts out empty */
136 Skein_Start_New_Type(ctx,MSG);
138 return SKEIN_SUCCESS;
141 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
142 /* process the input bytes */
143 int Skein_256_Update(Skein_256_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
147 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
149 /* process full blocks, if any */
150 if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES)
152 if (ctx->h.bCnt) /* finish up any buffered message data */
154 n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
157 Skein_assert(n < msgByteCnt); /* check on our logic here */
158 memcpy(&ctx->b[ctx->h.bCnt],msg,n);
163 Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES);
164 Skein_256_Process_Block(ctx,ctx->b,1,SKEIN_256_BLOCK_BYTES);
167 /* now process any remaining full blocks, directly from input message data */
168 if (msgByteCnt > SKEIN_256_BLOCK_BYTES)
170 n = (msgByteCnt-1) / SKEIN_256_BLOCK_BYTES; /* number of full blocks to process */
171 Skein_256_Process_Block(ctx,msg,n,SKEIN_256_BLOCK_BYTES);
172 msgByteCnt -= n * SKEIN_256_BLOCK_BYTES;
173 msg += n * SKEIN_256_BLOCK_BYTES;
175 Skein_assert(ctx->h.bCnt == 0);
178 /* copy any remaining source message data bytes into b[] */
181 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES);
182 memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);
183 ctx->h.bCnt += msgByteCnt;
186 return SKEIN_SUCCESS;
189 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
190 /* finalize the hash computation and output the result */
191 int Skein_256_Final(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)
194 u64b_t X[SKEIN_256_STATE_WORDS];
195 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
197 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
198 if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) /* zero pad b[] if necessary */
199 memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
201 Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
203 /* now output the result */
204 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
206 /* run Threefish in "counter mode" to generate output */
207 memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
208 memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
209 for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++)
211 ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
212 Skein_Start_New_Type(ctx,OUT_FINAL);
213 Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
214 n = byteCnt - i*SKEIN_256_BLOCK_BYTES; /* number of output bytes left to go */
215 if (n >= SKEIN_256_BLOCK_BYTES)
216 n = SKEIN_256_BLOCK_BYTES;
217 Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
218 Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES);
219 memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
221 return SKEIN_SUCCESS;
224 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
225 size_t Skein_256_API_CodeSize(void)
227 return ((u08b_t *) Skein_256_API_CodeSize) -
228 ((u08b_t *) Skein_256_Init);
232 /*****************************************************************/
234 /*****************************************************************/
236 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
237 /* init the context for a straight hashing operation */
238 int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
242 u08b_t b[SKEIN_512_STATE_BYTES];
243 u64b_t w[SKEIN_512_STATE_WORDS];
244 } cfg; /* config block */
246 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
247 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
250 { /* use pre-computed values, where available */
251 #ifndef SKEIN_NO_PRECOMP
252 case 512: memcpy(ctx->X,SKEIN_512_IV_512,sizeof(ctx->X)); break;
253 case 384: memcpy(ctx->X,SKEIN_512_IV_384,sizeof(ctx->X)); break;
254 case 256: memcpy(ctx->X,SKEIN_512_IV_256,sizeof(ctx->X)); break;
255 case 224: memcpy(ctx->X,SKEIN_512_IV_224,sizeof(ctx->X)); break;
258 /* here if there is no precomputed IV value available */
259 /* build/process the config block, type == CONFIG (could be precomputed) */
260 Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */
262 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */
263 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
264 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
265 memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */
267 /* compute the initial chaining values from config block */
268 memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */
269 Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
273 /* The chaining vars ctx->X are now initialized for the given hashBitLen. */
274 /* Set up to process the data message portion of the hash (default) */
275 Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */
277 return SKEIN_SUCCESS;
280 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
281 /* init the context for a MAC and/or tree hash operation */
282 /* [identical to Skein_512_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */
283 int Skein_512_InitExt(Skein_512_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes)
287 u08b_t b[SKEIN_512_STATE_BYTES];
288 u64b_t w[SKEIN_512_STATE_WORDS];
289 } cfg; /* config block */
291 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
292 Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);
294 /* compute the initial chaining values ctx->X[], based on key */
295 if (keyBytes == 0) /* is there a key? */
297 memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */
299 else /* here to pre-process a key */
301 Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X));
302 /* do a mini-Init right here */
303 ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */
304 Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */
305 memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */
306 Skein_512_Update(ctx,key,keyBytes); /* hash the key */
307 Skein_512_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */
308 memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */
312 for (i=0;i<SKEIN_512_STATE_WORDS;i++) /* convert key bytes to context words */
313 ctx->X[i] = Skein_Swap64(ctx->X[i]);
317 /* build/process the config block, type == CONFIG (could be precomputed for each key) */
318 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
319 Skein_Start_New_Type(ctx,CFG_FINAL);
321 memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */
322 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
323 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
324 cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
326 Skein_Show_Key(512,&ctx->h,key,keyBytes);
328 /* compute the initial chaining values from config block */
329 Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
331 /* The chaining vars ctx->X are now initialized */
332 /* Set up to process the data message portion of the hash (default) */
333 ctx->h.bCnt = 0; /* buffer b[] starts out empty */
334 Skein_Start_New_Type(ctx,MSG);
336 return SKEIN_SUCCESS;
339 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
340 /* process the input bytes */
341 int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
345 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
347 /* process full blocks, if any */
348 if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES)
350 if (ctx->h.bCnt) /* finish up any buffered message data */
352 n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
355 Skein_assert(n < msgByteCnt); /* check on our logic here */
356 memcpy(&ctx->b[ctx->h.bCnt],msg,n);
361 Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES);
362 Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES);
365 /* now process any remaining full blocks, directly from input message data */
366 if (msgByteCnt > SKEIN_512_BLOCK_BYTES)
368 n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES; /* number of full blocks to process */
369 Skein_512_Process_Block(ctx,msg,n,SKEIN_512_BLOCK_BYTES);
370 msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
371 msg += n * SKEIN_512_BLOCK_BYTES;
373 Skein_assert(ctx->h.bCnt == 0);
376 /* copy any remaining source message data bytes into b[] */
379 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES);
380 memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);
381 ctx->h.bCnt += msgByteCnt;
384 return SKEIN_SUCCESS;
387 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
388 /* finalize the hash computation and output the result */
389 int Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
392 u64b_t X[SKEIN_512_STATE_WORDS];
393 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
395 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
396 if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */
397 memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
399 Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
401 /* now output the result */
402 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
404 /* run Threefish in "counter mode" to generate output */
405 memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
406 memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
407 for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++)
409 ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
410 Skein_Start_New_Type(ctx,OUT_FINAL);
411 Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
412 n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */
413 if (n >= SKEIN_512_BLOCK_BYTES)
414 n = SKEIN_512_BLOCK_BYTES;
415 Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
416 Skein_Show_Final(512,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES);
417 memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
419 return SKEIN_SUCCESS;
422 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
423 size_t Skein_512_API_CodeSize(void)
425 return ((u08b_t *) Skein_512_API_CodeSize) -
426 ((u08b_t *) Skein_512_Init);
430 /*****************************************************************/
432 /*****************************************************************/
434 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
435 /* init the context for a straight hashing operation */
436 int Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen)
440 u08b_t b[SKEIN1024_STATE_BYTES];
441 u64b_t w[SKEIN1024_STATE_WORDS];
442 } cfg; /* config block */
444 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
445 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
448 { /* use pre-computed values, where available */
449 #ifndef SKEIN_NO_PRECOMP
450 case 512: memcpy(ctx->X,SKEIN1024_IV_512 ,sizeof(ctx->X)); break;
451 case 384: memcpy(ctx->X,SKEIN1024_IV_384 ,sizeof(ctx->X)); break;
452 case 1024: memcpy(ctx->X,SKEIN1024_IV_1024,sizeof(ctx->X)); break;
455 /* here if there is no precomputed IV value available */
456 /* build/process the config block, type == CONFIG (could be precomputed) */
457 Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */
459 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */
460 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
461 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
462 memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */
464 /* compute the initial chaining values from config block */
465 memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */
466 Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
470 /* The chaining vars ctx->X are now initialized for the given hashBitLen. */
471 /* Set up to process the data message portion of the hash (default) */
472 Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */
474 return SKEIN_SUCCESS;
477 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
478 /* init the context for a MAC and/or tree hash operation */
479 /* [identical to Skein1024_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */
480 int Skein1024_InitExt(Skein1024_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes)
484 u08b_t b[SKEIN1024_STATE_BYTES];
485 u64b_t w[SKEIN1024_STATE_WORDS];
486 } cfg; /* config block */
488 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
489 Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);
491 /* compute the initial chaining values ctx->X[], based on key */
492 if (keyBytes == 0) /* is there a key? */
494 memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */
496 else /* here to pre-process a key */
498 Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X));
499 /* do a mini-Init right here */
500 ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */
501 Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */
502 memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */
503 Skein1024_Update(ctx,key,keyBytes); /* hash the key */
504 Skein1024_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */
505 memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */
509 for (i=0;i<SKEIN1024_STATE_WORDS;i++) /* convert key bytes to context words */
510 ctx->X[i] = Skein_Swap64(ctx->X[i]);
514 /* build/process the config block, type == CONFIG (could be precomputed for each key) */
515 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
516 Skein_Start_New_Type(ctx,CFG_FINAL);
518 memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */
519 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER);
520 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
521 cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
523 Skein_Show_Key(1024,&ctx->h,key,keyBytes);
525 /* compute the initial chaining values from config block */
526 Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
528 /* The chaining vars ctx->X are now initialized */
529 /* Set up to process the data message portion of the hash (default) */
530 ctx->h.bCnt = 0; /* buffer b[] starts out empty */
531 Skein_Start_New_Type(ctx,MSG);
533 return SKEIN_SUCCESS;
536 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
537 /* process the input bytes */
538 int Skein1024_Update(Skein1024_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
542 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
544 /* process full blocks, if any */
545 if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES)
547 if (ctx->h.bCnt) /* finish up any buffered message data */
549 n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
552 Skein_assert(n < msgByteCnt); /* check on our logic here */
553 memcpy(&ctx->b[ctx->h.bCnt],msg,n);
558 Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES);
559 Skein1024_Process_Block(ctx,ctx->b,1,SKEIN1024_BLOCK_BYTES);
562 /* now process any remaining full blocks, directly from input message data */
563 if (msgByteCnt > SKEIN1024_BLOCK_BYTES)
565 n = (msgByteCnt-1) / SKEIN1024_BLOCK_BYTES; /* number of full blocks to process */
566 Skein1024_Process_Block(ctx,msg,n,SKEIN1024_BLOCK_BYTES);
567 msgByteCnt -= n * SKEIN1024_BLOCK_BYTES;
568 msg += n * SKEIN1024_BLOCK_BYTES;
570 Skein_assert(ctx->h.bCnt == 0);
573 /* copy any remaining source message data bytes into b[] */
576 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES);
577 memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);
578 ctx->h.bCnt += msgByteCnt;
581 return SKEIN_SUCCESS;
584 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
585 /* finalize the hash computation and output the result */
586 int Skein1024_Final(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)
589 u64b_t X[SKEIN1024_STATE_WORDS];
590 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
592 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
593 if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) /* zero pad b[] if necessary */
594 memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
596 Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
598 /* now output the result */
599 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
601 /* run Threefish in "counter mode" to generate output */
602 memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
603 memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
604 for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++)
606 ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
607 Skein_Start_New_Type(ctx,OUT_FINAL);
608 Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
609 n = byteCnt - i*SKEIN1024_BLOCK_BYTES; /* number of output bytes left to go */
610 if (n >= SKEIN1024_BLOCK_BYTES)
611 n = SKEIN1024_BLOCK_BYTES;
612 Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
613 Skein_Show_Final(1024,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES);
614 memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
616 return SKEIN_SUCCESS;
619 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
620 size_t Skein1024_API_CodeSize(void)
622 return ((u08b_t *) Skein1024_API_CodeSize) -
623 ((u08b_t *) Skein1024_Init);
627 /**************** Functions to support MAC/tree hashing ***************/
628 /* (this code is identical for Optimized and Reference versions) */
630 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
631 /* finalize the hash computation and output the block, no OUTPUT stage */
632 int Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)
634 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
636 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
637 if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) /* zero pad b[] if necessary */
638 memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt);
639 Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
641 Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_256_BLOCK_BYTES); /* "output" the state bytes */
643 return SKEIN_SUCCESS;
646 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
647 /* finalize the hash computation and output the block, no OUTPUT stage */
648 int Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
650 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
652 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
653 if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */
654 memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
655 Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
657 Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_512_BLOCK_BYTES); /* "output" the state bytes */
659 return SKEIN_SUCCESS;
662 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
663 /* finalize the hash computation and output the block, no OUTPUT stage */
664 int Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)
666 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
668 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
669 if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) /* zero pad b[] if necessary */
670 memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt);
671 Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
673 Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN1024_BLOCK_BYTES); /* "output" the state bytes */
675 return SKEIN_SUCCESS;
679 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
680 /* just do the OUTPUT stage */
681 int Skein_256_Output(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)
684 u64b_t X[SKEIN_256_STATE_WORDS];
685 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
687 /* now output the result */
688 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
690 /* run Threefish in "counter mode" to generate output */
691 memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
692 memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
693 for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++)
695 ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
696 Skein_Start_New_Type(ctx,OUT_FINAL);
697 Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
698 n = byteCnt - i*SKEIN_256_BLOCK_BYTES; /* number of output bytes left to go */
699 if (n >= SKEIN_256_BLOCK_BYTES)
700 n = SKEIN_256_BLOCK_BYTES;
701 Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
702 Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES);
703 memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
705 return SKEIN_SUCCESS;
708 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
709 /* just do the OUTPUT stage */
710 int Skein_512_Output(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
713 u64b_t X[SKEIN_512_STATE_WORDS];
714 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
716 /* now output the result */
717 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
719 /* run Threefish in "counter mode" to generate output */
720 memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
721 memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
722 for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++)
724 ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
725 Skein_Start_New_Type(ctx,OUT_FINAL);
726 Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
727 n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */
728 if (n >= SKEIN_512_BLOCK_BYTES)
729 n = SKEIN_512_BLOCK_BYTES;
730 Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
731 Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES);
732 memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
734 return SKEIN_SUCCESS;
737 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
738 /* just do the OUTPUT stage */
739 int Skein1024_Output(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)
742 u64b_t X[SKEIN1024_STATE_WORDS];
743 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
745 /* now output the result */
746 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
748 /* run Threefish in "counter mode" to generate output */
749 memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
750 memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
751 for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++)
753 ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
754 Skein_Start_New_Type(ctx,OUT_FINAL);
755 Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
756 n = byteCnt - i*SKEIN1024_BLOCK_BYTES; /* number of output bytes left to go */
757 if (n >= SKEIN1024_BLOCK_BYTES)
758 n = SKEIN1024_BLOCK_BYTES;
759 Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
760 Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES);
761 memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
763 return SKEIN_SUCCESS;
767 /* Adapt the functions to match the prototype expected by libmd */
769 SKEIN256_Init(SKEIN256_CTX * ctx)
772 Skein_256_Init(ctx, 256);
776 SKEIN512_Init(SKEIN512_CTX * ctx)
779 Skein_512_Init(ctx, 512);
783 SKEIN1024_Init(SKEIN1024_CTX * ctx)
786 Skein1024_Init(ctx, 1024);
790 SKEIN256_Update(SKEIN256_CTX * ctx, const void *in, size_t len)
793 Skein_256_Update(ctx, in, len);
797 SKEIN512_Update(SKEIN512_CTX * ctx, const void *in, size_t len)
800 Skein_512_Update(ctx, in, len);
804 SKEIN1024_Update(SKEIN1024_CTX * ctx, const void *in, size_t len)
807 Skein1024_Update(ctx, in, len);
811 SKEIN256_Final(unsigned char digest[static SKEIN_256_BLOCK_BYTES], SKEIN256_CTX *ctx)
814 Skein_256_Final(ctx, digest);
818 SKEIN512_Final(unsigned char digest[static SKEIN_512_BLOCK_BYTES], SKEIN512_CTX *ctx)
821 Skein_512_Final(ctx, digest);
825 SKEIN1024_Final(unsigned char digest[static SKEIN1024_BLOCK_BYTES], SKEIN1024_CTX *ctx)
828 Skein1024_Final(ctx, digest);
832 /* When building libmd, provide weak references. Note: this is not
833 activated in the context of compiling these sources for internal
837 __weak_reference(_libmd_SKEIN256_Init, SKEIN256_Init);
838 #undef SKEIN256_Update
839 __weak_reference(_libmd_SKEIN256_Update, SKEIN256_Update);
840 #undef SKEIN256_Final
841 __weak_reference(_libmd_SKEIN256_Final, SKEIN256_Final);
844 __weak_reference(_libmd_SKEIN512_Init, SKEIN512_Init);
845 #undef SKEIN512_Update
846 __weak_reference(_libmd_SKEIN512_Update, SKEIN512_Update);
847 #undef SKEIN512_Final
848 __weak_reference(_libmd_SKEIN512_Final, SKEIN512_Final);
850 #undef SKEIN1024_Init
851 __weak_reference(_libmd_SKEIN1024_Init, SKEIN1024_Init);
852 #undef SKEIN1024_Update
853 __weak_reference(_libmd_SKEIN1024_Update, SKEIN1024_Update);
854 #undef SKEIN1024_Final
855 __weak_reference(_libmd_SKEIN1024_Final, SKEIN1024_Final);