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