Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/crypto/skein/skein.c
39478 views
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 */
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] */
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 */
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 */
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)
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 */
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] */
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 */
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 */
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)
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 */
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] */
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 */
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 */
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)
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 */
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 */
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 */
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 */
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 */
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 */
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
767
SKEIN256_Init(SKEIN256_CTX * ctx)
768
{
769
770
Skein_256_Init(ctx, 256);
771
}
772
773
void
774
SKEIN512_Init(SKEIN512_CTX * ctx)
775
{
776
777
Skein_512_Init(ctx, 512);
778
}
779
780
void
781
SKEIN1024_Init(SKEIN1024_CTX * ctx)
782
{
783
784
Skein1024_Init(ctx, 1024);
785
}
786
787
void
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
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
802
SKEIN1024_Update(SKEIN1024_CTX * ctx, const void *in, size_t len)
803
{
804
805
Skein1024_Update(ctx, in, len);
806
}
807
808
void
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
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
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
861