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