1 /***********************************************************************
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 #include <sys/cdefs.h>
12 __FBSDID("$FreeBSD$");
13
14 #include <sys/endian.h>
15 #include <sys/types.h>
16
17 /* get the memcpy/memset functions */
18 #ifdef _KERNEL
19 #include <sys/systm.h>
20 #else
21 #include <string.h>
22 #endif
23
24 #define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */
25
26 #include "skein.h" /* get the Skein API definitions */
27 #include "skein_iv.h" /* get precomputed IVs */
28
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);
34
35 /*****************************************************************/
36 /* 256-bit Skein */
37 /*****************************************************************/
38
39 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
40 /* init the context for a straight hashing operation */
41 int Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen)
42 {
43 union
44 {
45 u08b_t b[SKEIN_256_STATE_BYTES];
46 u64b_t w[SKEIN_256_STATE_WORDS];
47 } cfg; /* config block */
48
49 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
50 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
51
52 switch (hashBitLen)
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;
59 #endif
60 default:
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 */
64
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 */
69
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);
73 break;
74 }
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 */
78
79 return SKEIN_SUCCESS;
80 }
81
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)
86 {
87 union
88 {
89 u08b_t b[SKEIN_256_STATE_BYTES];
90 u64b_t w[SKEIN_256_STATE_WORDS];
91 } cfg; /* config block */
92
93 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
94 Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);
95
96 /* compute the initial chaining values ctx->X[], based on key */
97 if (keyBytes == 0) /* is there a key? */
98 {
99 memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */
100 }
101 else /* here to pre-process a key */
102 {
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[] */
111 #if SKEIN_NEED_SWAP
112 {
113 uint_t i;
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]);
116 }
117 #endif
118 }
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);
122
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) */
127
128 Skein_Show_Key(256,&ctx->h,key,keyBytes);
129
130 /* compute the initial chaining values from config block */
131 Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
132
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);
137
138 return SKEIN_SUCCESS;
139 }
140
141 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
142 /* process the input bytes */
143 int Skein_256_Update(Skein_256_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
144 {
145 size_t n;
146
147 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
148
149 /* process full blocks, if any */
150 if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES)
151 {
152 if (ctx->h.bCnt) /* finish up any buffered message data */
153 {
154 n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
155 if (n)
156 {
157 Skein_assert(n < msgByteCnt); /* check on our logic here */
158 memcpy(&ctx->b[ctx->h.bCnt],msg,n);
159 msgByteCnt -= n;
160 msg += n;
161 ctx->h.bCnt += n;
162 }
163 Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES);
164 Skein_256_Process_Block(ctx,ctx->b,1,SKEIN_256_BLOCK_BYTES);
165 ctx->h.bCnt = 0;
166 }
167 /* now process any remaining full blocks, directly from input message data */
168 if (msgByteCnt > SKEIN_256_BLOCK_BYTES)
169 {
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;
174 }
175 Skein_assert(ctx->h.bCnt == 0);
176 }
177
178 /* copy any remaining source message data bytes into b[] */
179 if (msgByteCnt)
180 {
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;
184 }
185
186 return SKEIN_SUCCESS;
187 }
188
189 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
190 /* finalize the hash computation and output the result */
191 int Skein_256_Final(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)
192 {
193 size_t i,n,byteCnt;
194 u64b_t X[SKEIN_256_STATE_WORDS];
195 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
196
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);
200
201 Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
202
203 /* now output the result */
204 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
205
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++)
210 {
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 */
220 }
221 return SKEIN_SUCCESS;
222 }
223
224 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
225 size_t Skein_256_API_CodeSize(void)
226 {
227 return ((u08b_t *) Skein_256_API_CodeSize) -
228 ((u08b_t *) Skein_256_Init);
229 }
230 #endif
231
232 /*****************************************************************/
233 /* 512-bit Skein */
234 /*****************************************************************/
235
236 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
237 /* init the context for a straight hashing operation */
238 int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
239 {
240 union
241 {
242 u08b_t b[SKEIN_512_STATE_BYTES];
243 u64b_t w[SKEIN_512_STATE_WORDS];
244 } cfg; /* config block */
245
246 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
247 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
248
249 switch (hashBitLen)
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;
256 #endif
257 default:
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 */
261
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 */
266
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);
270 break;
271 }
272
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 */
276
277 return SKEIN_SUCCESS;
278 }
279
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)
284 {
285 union
286 {
287 u08b_t b[SKEIN_512_STATE_BYTES];
288 u64b_t w[SKEIN_512_STATE_WORDS];
289 } cfg; /* config block */
290
291 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
292 Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);
293
294 /* compute the initial chaining values ctx->X[], based on key */
295 if (keyBytes == 0) /* is there a key? */
296 {
297 memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */
298 }
299 else /* here to pre-process a key */
300 {
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[] */
309 #if SKEIN_NEED_SWAP
310 {
311 uint_t i;
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]);
314 }
315 #endif
316 }
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);
320
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) */
325
326 Skein_Show_Key(512,&ctx->h,key,keyBytes);
327
328 /* compute the initial chaining values from config block */
329 Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
330
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);
335
336 return SKEIN_SUCCESS;
337 }
338
339 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
340 /* process the input bytes */
341 int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
342 {
343 size_t n;
344
345 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
346
347 /* process full blocks, if any */
348 if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES)
349 {
350 if (ctx->h.bCnt) /* finish up any buffered message data */
351 {
352 n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
353 if (n)
354 {
355 Skein_assert(n < msgByteCnt); /* check on our logic here */
356 memcpy(&ctx->b[ctx->h.bCnt],msg,n);
357 msgByteCnt -= n;
358 msg += n;
359 ctx->h.bCnt += n;
360 }
361 Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES);
362 Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES);
363 ctx->h.bCnt = 0;
364 }
365 /* now process any remaining full blocks, directly from input message data */
366 if (msgByteCnt > SKEIN_512_BLOCK_BYTES)
367 {
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;
372 }
373 Skein_assert(ctx->h.bCnt == 0);
374 }
375
376 /* copy any remaining source message data bytes into b[] */
377 if (msgByteCnt)
378 {
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;
382 }
383
384 return SKEIN_SUCCESS;
385 }
386
387 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
388 /* finalize the hash computation and output the result */
389 int Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
390 {
391 size_t i,n,byteCnt;
392 u64b_t X[SKEIN_512_STATE_WORDS];
393 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
394
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);
398
399 Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
400
401 /* now output the result */
402 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
403
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++)
408 {
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 */
418 }
419 return SKEIN_SUCCESS;
420 }
421
422 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
423 size_t Skein_512_API_CodeSize(void)
424 {
425 return ((u08b_t *) Skein_512_API_CodeSize) -
426 ((u08b_t *) Skein_512_Init);
427 }
428 #endif
429
430 /*****************************************************************/
431 /* 1024-bit Skein */
432 /*****************************************************************/
433
434 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
435 /* init the context for a straight hashing operation */
436 int Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen)
437 {
438 union
439 {
440 u08b_t b[SKEIN1024_STATE_BYTES];
441 u64b_t w[SKEIN1024_STATE_WORDS];
442 } cfg; /* config block */
443
444 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
445 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
446
447 switch (hashBitLen)
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;
453 #endif
454 default:
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 */
458
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 */
463
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);
467 break;
468 }
469
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 */
473
474 return SKEIN_SUCCESS;
475 }
476
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)
481 {
482 union
483 {
484 u08b_t b[SKEIN1024_STATE_BYTES];
485 u64b_t w[SKEIN1024_STATE_WORDS];
486 } cfg; /* config block */
487
488 Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
489 Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL);
490
491 /* compute the initial chaining values ctx->X[], based on key */
492 if (keyBytes == 0) /* is there a key? */
493 {
494 memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */
495 }
496 else /* here to pre-process a key */
497 {
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[] */
506 #if SKEIN_NEED_SWAP
507 {
508 uint_t i;
509 for (i=0;i<SKEIN1024_STATE_WORDS;i++) /* convert key bytes to context words */
510 ctx->X[i] = Skein_Swap64(ctx->X[i]);
511 }
512 #endif
513 }
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);
517
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) */
522
523 Skein_Show_Key(1024,&ctx->h,key,keyBytes);
524
525 /* compute the initial chaining values from config block */
526 Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
527
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);
532
533 return SKEIN_SUCCESS;
534 }
535
536 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
537 /* process the input bytes */
538 int Skein1024_Update(Skein1024_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
539 {
540 size_t n;
541
542 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
543
544 /* process full blocks, if any */
545 if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES)
546 {
547 if (ctx->h.bCnt) /* finish up any buffered message data */
548 {
549 n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
550 if (n)
551 {
552 Skein_assert(n < msgByteCnt); /* check on our logic here */
553 memcpy(&ctx->b[ctx->h.bCnt],msg,n);
554 msgByteCnt -= n;
555 msg += n;
556 ctx->h.bCnt += n;
557 }
558 Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES);
559 Skein1024_Process_Block(ctx,ctx->b,1,SKEIN1024_BLOCK_BYTES);
560 ctx->h.bCnt = 0;
561 }
562 /* now process any remaining full blocks, directly from input message data */
563 if (msgByteCnt > SKEIN1024_BLOCK_BYTES)
564 {
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;
569 }
570 Skein_assert(ctx->h.bCnt == 0);
571 }
572
573 /* copy any remaining source message data bytes into b[] */
574 if (msgByteCnt)
575 {
576 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES);
577 memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);
578 ctx->h.bCnt += msgByteCnt;
579 }
580
581 return SKEIN_SUCCESS;
582 }
583
584 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
585 /* finalize the hash computation and output the result */
586 int Skein1024_Final(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)
587 {
588 size_t i,n,byteCnt;
589 u64b_t X[SKEIN1024_STATE_WORDS];
590 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
591
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);
595
596 Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
597
598 /* now output the result */
599 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
600
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++)
605 {
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 */
615 }
616 return SKEIN_SUCCESS;
617 }
618
619 #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
620 size_t Skein1024_API_CodeSize(void)
621 {
622 return ((u08b_t *) Skein1024_API_CodeSize) -
623 ((u08b_t *) Skein1024_Init);
624 }
625 #endif
626
627 /**************** Functions to support MAC/tree hashing ***************/
628 /* (this code is identical for Optimized and Reference versions) */
629
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)
633 {
634 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
635
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 */
640
641 Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_256_BLOCK_BYTES); /* "output" the state bytes */
642
643 return SKEIN_SUCCESS;
644 }
645
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)
649 {
650 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
651
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 */
656
657 Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_512_BLOCK_BYTES); /* "output" the state bytes */
658
659 return SKEIN_SUCCESS;
660 }
661
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)
665 {
666 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
667
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 */
672
673 Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN1024_BLOCK_BYTES); /* "output" the state bytes */
674
675 return SKEIN_SUCCESS;
676 }
677
678 #if SKEIN_TREE_HASH
679 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
680 /* just do the OUTPUT stage */
681 int Skein_256_Output(Skein_256_Ctxt_t *ctx, u08b_t *hashVal)
682 {
683 size_t i,n,byteCnt;
684 u64b_t X[SKEIN_256_STATE_WORDS];
685 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
686
687 /* now output the result */
688 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
689
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++)
694 {
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 */
704 }
705 return SKEIN_SUCCESS;
706 }
707
708 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
709 /* just do the OUTPUT stage */
710 int Skein_512_Output(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
711 {
712 size_t i,n,byteCnt;
713 u64b_t X[SKEIN_512_STATE_WORDS];
714 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
715
716 /* now output the result */
717 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
718
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++)
723 {
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 */
733 }
734 return SKEIN_SUCCESS;
735 }
736
737 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
738 /* just do the OUTPUT stage */
739 int Skein1024_Output(Skein1024_Ctxt_t *ctx, u08b_t *hashVal)
740 {
741 size_t i,n,byteCnt;
742 u64b_t X[SKEIN1024_STATE_WORDS];
743 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
744
745 /* now output the result */
746 byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
747
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++)
752 {
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 */
762 }
763 return SKEIN_SUCCESS;
764 }
765
766
767 /* Adapt the functions to match the prototype expected by libmd */
768 void
769 SKEIN256_Init(SKEIN256_CTX * ctx)
770 {
771
772 Skein_256_Init(ctx, 256);
773 }
774
775 void
776 SKEIN512_Init(SKEIN512_CTX * ctx)
777 {
778
779 Skein_512_Init(ctx, 512);
780 }
781
782 void
783 SKEIN1024_Init(SKEIN1024_CTX * ctx)
784 {
785
786 Skein1024_Init(ctx, 1024);
787 }
788
789 void
790 SKEIN256_Update(SKEIN256_CTX * ctx, const void *in, size_t len)
791 {
792
793 Skein_256_Update(ctx, in, len);
794 }
795
796 void
797 SKEIN512_Update(SKEIN512_CTX * ctx, const void *in, size_t len)
798 {
799
800 Skein_512_Update(ctx, in, len);
801 }
802
803 void
804 SKEIN1024_Update(SKEIN1024_CTX * ctx, const void *in, size_t len)
805 {
806
807 Skein1024_Update(ctx, in, len);
808 }
809
810 void
811 SKEIN256_Final(unsigned char digest[static SKEIN_256_BLOCK_BYTES], SKEIN256_CTX *ctx)
812 {
813
814 Skein_256_Final(ctx, digest);
815 explicit_bzero(ctx, sizeof(*ctx));
816 }
817
818 void
819 SKEIN512_Final(unsigned char digest[static SKEIN_512_BLOCK_BYTES], SKEIN512_CTX *ctx)
820 {
821
822 Skein_512_Final(ctx, digest);
823 explicit_bzero(ctx, sizeof(*ctx));
824 }
825
826 void
827 SKEIN1024_Final(unsigned char digest[static SKEIN1024_BLOCK_BYTES], SKEIN1024_CTX *ctx)
828 {
829
830 Skein1024_Final(ctx, digest);
831 explicit_bzero(ctx, sizeof(*ctx));
832 }
833
834 #ifdef WEAK_REFS
835 /* When building libmd, provide weak references. Note: this is not
836 activated in the context of compiling these sources for internal
837 use in libcrypt.
838 */
839 #undef SKEIN256_Init
840 __weak_reference(_libmd_SKEIN256_Init, SKEIN256_Init);
841 #undef SKEIN256_Update
842 __weak_reference(_libmd_SKEIN256_Update, SKEIN256_Update);
843 #undef SKEIN256_Final
844 __weak_reference(_libmd_SKEIN256_Final, SKEIN256_Final);
845
846 #undef SKEIN512_Init
847 __weak_reference(_libmd_SKEIN512_Init, SKEIN512_Init);
848 #undef SKEIN512_Update
849 __weak_reference(_libmd_SKEIN512_Update, SKEIN512_Update);
850 #undef SKEIN512_Final
851 __weak_reference(_libmd_SKEIN512_Final, SKEIN512_Final);
852
853 #undef SKEIN1024_Init
854 __weak_reference(_libmd_SKEIN1024_Init, SKEIN1024_Init);
855 #undef SKEIN1024_Update
856 __weak_reference(_libmd_SKEIN1024_Update, SKEIN1024_Update);
857 #undef SKEIN1024_Final
858 __weak_reference(_libmd_SKEIN1024_Final, SKEIN1024_Final);
859 #endif
860
861 #endif
Cache object: f14764bf9499d92980119953667eb56a
|