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