1 /* 2 * Implementation of the Skein hash function. 3 * Source code author: Doug Whiting, 2008. 4 * This algorithm and source code is released to the public domain. 5 */ 6 /* Copyright 2013 Doug Whiting. This code is released to the public domain. */ 7 8 #include <sys/sysmacros.h> 9 #include <sys/types.h> 10 #include <sys/skein.h> /* get the Skein API definitions */ 11 #include "skein_impl.h" /* get internal definitions */ 12 13 /* 256-bit Skein */ 14 /* init the context for a straight hashing operation */ 15 int 16 Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen) 17 { 18 union { 19 uint8_t b[SKEIN_256_STATE_BYTES]; 20 uint64_t w[SKEIN_256_STATE_WORDS]; 21 } cfg; /* config block */ 22 23 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); 24 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 25 26 switch (hashBitLen) { /* use pre-computed values, where available */ 27 #ifndef SKEIN_NO_PRECOMP 28 case 256: 29 bcopy(SKEIN_256_IV_256, ctx->X, sizeof (ctx->X)); 30 break; 31 case 224: 32 bcopy(SKEIN_256_IV_224, ctx->X, sizeof (ctx->X)); 33 break; 34 case 160: 35 bcopy(SKEIN_256_IV_160, ctx->X, sizeof (ctx->X)); 36 break; 37 case 128: 38 bcopy(SKEIN_256_IV_128, ctx->X, sizeof (ctx->X)); 39 break; 40 #endif 41 default: 42 /* here if there is no precomputed IV value available */ 43 /* 44 * build/process the config block, type == CONFIG (could be 45 * precomputed) 46 */ 47 /* set tweaks: T0=0; T1=CFG | FINAL */ 48 Skein_Start_New_Type(ctx, CFG_FINAL); 49 50 /* set the schema, version */ 51 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); 52 /* hash result length in bits */ 53 cfg.w[1] = Skein_Swap64(hashBitLen); 54 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); 55 /* zero pad config block */ 56 bzero(&cfg.w[3], sizeof (cfg) - 3 * sizeof (cfg.w[0])); 57 58 /* compute the initial chaining values from config block */ 59 /* zero the chaining variables */ 60 bzero(ctx->X, sizeof (ctx->X)); 61 Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); 62 break; 63 } 64 /* 65 * The chaining vars ctx->X are now initialized for the given 66 * hashBitLen. 67 * Set up to process the data message portion of the hash (default) 68 */ 69 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */ 70 71 return (SKEIN_SUCCESS); 72 } 73 74 /* init the context for a MAC and/or tree hash operation */ 75 /* 76 * [identical to Skein_256_Init() when keyBytes == 0 && 77 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] 78 */ 79 int 80 Skein_256_InitExt(Skein_256_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo, 81 const uint8_t *key, size_t keyBytes) 82 { 83 union { 84 uint8_t b[SKEIN_256_STATE_BYTES]; 85 uint64_t w[SKEIN_256_STATE_WORDS]; 86 } cfg; /* config block */ 87 88 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); 89 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL); 90 91 /* compute the initial chaining values ctx->X[], based on key */ 92 if (keyBytes == 0) { /* is there a key? */ 93 /* no key: use all zeroes as key for config block */ 94 bzero(ctx->X, sizeof (ctx->X)); 95 } else { /* here to pre-process a key */ 96 97 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X)); 98 /* do a mini-Init right here */ 99 /* set output hash bit count = state size */ 100 ctx->h.hashBitLen = 8 * sizeof (ctx->X); 101 /* set tweaks: T0 = 0; T1 = KEY type */ 102 Skein_Start_New_Type(ctx, KEY); 103 /* zero the initial chaining variables */ 104 bzero(ctx->X, sizeof (ctx->X)); 105 /* hash the key */ 106 (void) Skein_256_Update(ctx, key, keyBytes); 107 /* put result into cfg.b[] */ 108 (void) Skein_256_Final_Pad(ctx, cfg.b); 109 /* copy over into ctx->X[] */ 110 bcopy(cfg.b, ctx->X, sizeof (cfg.b)); 111 #if SKEIN_NEED_SWAP 112 { 113 uint_t i; 114 /* convert key bytes to context words */ 115 for (i = 0; i < SKEIN_256_STATE_WORDS; i++) 116 ctx->X[i] = Skein_Swap64(ctx->X[i]); 117 } 118 #endif 119 } 120 /* 121 * build/process the config block, type == CONFIG (could be 122 * precomputed for each key) 123 */ 124 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 125 Skein_Start_New_Type(ctx, CFG_FINAL); 126 127 bzero(&cfg.w, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */ 128 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); 129 cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ 130 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ 131 cfg.w[2] = Skein_Swap64(treeInfo); 132 133 Skein_Show_Key(256, &ctx->h, key, keyBytes); 134 135 /* compute the initial chaining values from config block */ 136 Skein_256_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); 137 138 /* The chaining vars ctx->X are now initialized */ 139 /* Set up to process the data message portion of the hash (default) */ 140 ctx->h.bCnt = 0; /* buffer b[] starts out empty */ 141 Skein_Start_New_Type(ctx, MSG); 142 143 return (SKEIN_SUCCESS); 144 } 145 146 /* process the input bytes */ 147 int 148 Skein_256_Update(Skein_256_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt) 149 { 150 size_t n; 151 152 /* catch uninitialized context */ 153 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL); 154 155 /* process full blocks, if any */ 156 if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES) { 157 /* finish up any buffered message data */ 158 if (ctx->h.bCnt) { 159 /* # bytes free in buffer b[] */ 160 n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt; 161 if (n) { 162 /* check on our logic here */ 163 Skein_assert(n < msgByteCnt); 164 bcopy(msg, &ctx->b[ctx->h.bCnt], n); 165 msgByteCnt -= n; 166 msg += n; 167 ctx->h.bCnt += n; 168 } 169 Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES); 170 Skein_256_Process_Block(ctx, ctx->b, 1, 171 SKEIN_256_BLOCK_BYTES); 172 ctx->h.bCnt = 0; 173 } 174 /* 175 * now process any remaining full blocks, directly from input 176 * message data 177 */ 178 if (msgByteCnt > SKEIN_256_BLOCK_BYTES) { 179 /* number of full blocks to process */ 180 n = (msgByteCnt - 1) / SKEIN_256_BLOCK_BYTES; 181 Skein_256_Process_Block(ctx, msg, n, 182 SKEIN_256_BLOCK_BYTES); 183 msgByteCnt -= n * SKEIN_256_BLOCK_BYTES; 184 msg += n * SKEIN_256_BLOCK_BYTES; 185 } 186 Skein_assert(ctx->h.bCnt == 0); 187 } 188 189 /* copy any remaining source message data bytes into b[] */ 190 if (msgByteCnt) { 191 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES); 192 bcopy(msg, &ctx->b[ctx->h.bCnt], msgByteCnt); 193 ctx->h.bCnt += msgByteCnt; 194 } 195 196 return (SKEIN_SUCCESS); 197 } 198 199 /* finalize the hash computation and output the result */ 200 int 201 Skein_256_Final(Skein_256_Ctxt_t *ctx, uint8_t *hashVal) 202 { 203 size_t i, n, byteCnt; 204 uint64_t X[SKEIN_256_STATE_WORDS]; 205 206 /* catch uninitialized context */ 207 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL); 208 209 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 210 /* zero pad b[] if necessary */ 211 if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) 212 bzero(&ctx->b[ctx->h.bCnt], 213 SKEIN_256_BLOCK_BYTES - ctx->h.bCnt); 214 215 /* process the final block */ 216 Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); 217 218 /* now output the result */ 219 /* total number of output bytes */ 220 byteCnt = (ctx->h.hashBitLen + 7) >> 3; 221 222 /* run Threefish in "counter mode" to generate output */ 223 /* zero out b[], so it can hold the counter */ 224 bzero(ctx->b, sizeof (ctx->b)); 225 /* keep a local copy of counter mode "key" */ 226 bcopy(ctx->X, X, sizeof (X)); 227 for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) { 228 /* build the counter block */ 229 uint64_t tmp = Skein_Swap64((uint64_t)i); 230 bcopy(&tmp, ctx->b, sizeof (tmp)); 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 bcopy(X, ctx->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 bcopy(SKEIN_512_IV_512, ctx->X, sizeof (ctx->X)); 266 break; 267 case 384: 268 bcopy(SKEIN_512_IV_384, ctx->X, sizeof (ctx->X)); 269 break; 270 case 256: 271 bcopy(SKEIN_512_IV_256, ctx->X, sizeof (ctx->X)); 272 break; 273 case 224: 274 bcopy(SKEIN_512_IV_224, ctx->X, 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 bzero(&cfg.w[3], sizeof (cfg) - 3 * sizeof (cfg.w[0])); 293 294 /* compute the initial chaining values from config block */ 295 /* zero the chaining variables */ 296 bzero(ctx->X, 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 bzero(ctx->X, 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 bzero(ctx->X, 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 bcopy(cfg.b, ctx->X, 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 bzero(&cfg.w, 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 bcopy(msg, &ctx->b[ctx->h.bCnt], 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 bcopy(msg, &ctx->b[ctx->h.bCnt], 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 bzero(&ctx->b[ctx->h.bCnt], 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 bzero(ctx->b, sizeof (ctx->b)); 461 /* keep a local copy of counter mode "key" */ 462 bcopy(ctx->X, X, sizeof (X)); 463 for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) { 464 /* build the counter block */ 465 uint64_t tmp = Skein_Swap64((uint64_t)i); 466 bcopy(&tmp, ctx->b, sizeof (tmp)); 467 Skein_Start_New_Type(ctx, OUT_FINAL); 468 /* run "counter mode" */ 469 Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); 470 /* number of output bytes left to go */ 471 n = byteCnt - i * SKEIN_512_BLOCK_BYTES; 472 if (n >= SKEIN_512_BLOCK_BYTES) 473 n = SKEIN_512_BLOCK_BYTES; 474 Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES, 475 ctx->X, n); /* "output" the ctr mode bytes */ 476 Skein_Show_Final(512, &ctx->h, n, 477 hashVal + i * SKEIN_512_BLOCK_BYTES); 478 /* restore the counter mode key for next time */ 479 bcopy(X, ctx->X, sizeof (X)); 480 } 481 return (SKEIN_SUCCESS); 482 } 483 484 /* 1024-bit Skein */ 485 486 /* init the context for a straight hashing operation */ 487 int 488 Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen) 489 { 490 union { 491 uint8_t b[SKEIN1024_STATE_BYTES]; 492 uint64_t w[SKEIN1024_STATE_WORDS]; 493 } cfg; /* config block */ 494 495 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); 496 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 497 498 switch (hashBitLen) { /* use pre-computed values, where available */ 499 #ifndef SKEIN_NO_PRECOMP 500 case 512: 501 bcopy(SKEIN1024_IV_512, ctx->X, sizeof (ctx->X)); 502 break; 503 case 384: 504 bcopy(SKEIN1024_IV_384, ctx->X, sizeof (ctx->X)); 505 break; 506 case 1024: 507 bcopy(SKEIN1024_IV_1024, ctx->X, sizeof (ctx->X)); 508 break; 509 #endif 510 default: 511 /* here if there is no precomputed IV value available */ 512 /* 513 * build/process the config block, type == CONFIG (could be 514 * precomputed) 515 */ 516 /* set tweaks: T0=0; T1=CFG | FINAL */ 517 Skein_Start_New_Type(ctx, CFG_FINAL); 518 519 /* set the schema, version */ 520 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); 521 /* hash result length in bits */ 522 cfg.w[1] = Skein_Swap64(hashBitLen); 523 cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); 524 /* zero pad config block */ 525 bzero(&cfg.w[3], sizeof (cfg) - 3 * sizeof (cfg.w[0])); 526 527 /* compute the initial chaining values from config block */ 528 /* zero the chaining variables */ 529 bzero(ctx->X, sizeof (ctx->X)); 530 Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); 531 break; 532 } 533 534 /* 535 * The chaining vars ctx->X are now initialized for the given 536 * hashBitLen. Set up to process the data message portion of the hash 537 * (default) 538 */ 539 Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */ 540 541 return (SKEIN_SUCCESS); 542 } 543 544 /* init the context for a MAC and/or tree hash operation */ 545 /* 546 * [identical to Skein1024_Init() when keyBytes == 0 && 547 * treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] 548 */ 549 int 550 Skein1024_InitExt(Skein1024_Ctxt_t *ctx, size_t hashBitLen, uint64_t treeInfo, 551 const uint8_t *key, size_t keyBytes) 552 { 553 union { 554 uint8_t b[SKEIN1024_STATE_BYTES]; 555 uint64_t w[SKEIN1024_STATE_WORDS]; 556 } cfg; /* config block */ 557 558 Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); 559 Skein_Assert(keyBytes == 0 || key != NULL, SKEIN_FAIL); 560 561 /* compute the initial chaining values ctx->X[], based on key */ 562 if (keyBytes == 0) { /* is there a key? */ 563 /* no key: use all zeroes as key for config block */ 564 bzero(ctx->X, sizeof (ctx->X)); 565 } else { /* here to pre-process a key */ 566 Skein_assert(sizeof (cfg.b) >= sizeof (ctx->X)); 567 /* do a mini-Init right here */ 568 /* set output hash bit count = state size */ 569 ctx->h.hashBitLen = 8 * sizeof (ctx->X); 570 /* set tweaks: T0 = 0; T1 = KEY type */ 571 Skein_Start_New_Type(ctx, KEY); 572 /* zero the initial chaining variables */ 573 bzero(ctx->X, sizeof (ctx->X)); 574 (void) Skein1024_Update(ctx, key, keyBytes); /* hash the key */ 575 /* put result into cfg.b[] */ 576 (void) Skein1024_Final_Pad(ctx, cfg.b); 577 /* copy over into ctx->X[] */ 578 bcopy(cfg.b, ctx->X, sizeof (cfg.b)); 579 #if SKEIN_NEED_SWAP 580 { 581 uint_t i; 582 /* convert key bytes to context words */ 583 for (i = 0; i < SKEIN1024_STATE_WORDS; i++) 584 ctx->X[i] = Skein_Swap64(ctx->X[i]); 585 } 586 #endif 587 } 588 /* 589 * build/process the config block, type == CONFIG (could be 590 * precomputed for each key) 591 */ 592 ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 593 Skein_Start_New_Type(ctx, CFG_FINAL); 594 595 bzero(&cfg.w, sizeof (cfg.w)); /* pre-pad cfg.w[] with zeroes */ 596 cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); 597 /* hash result length in bits */ 598 cfg.w[1] = Skein_Swap64(hashBitLen); 599 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ 600 cfg.w[2] = Skein_Swap64(treeInfo); 601 602 Skein_Show_Key(1024, &ctx->h, key, keyBytes); 603 604 /* compute the initial chaining values from config block */ 605 Skein1024_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); 606 607 /* The chaining vars ctx->X are now initialized */ 608 /* Set up to process the data message portion of the hash (default) */ 609 ctx->h.bCnt = 0; /* buffer b[] starts out empty */ 610 Skein_Start_New_Type(ctx, MSG); 611 612 return (SKEIN_SUCCESS); 613 } 614 615 /* process the input bytes */ 616 int 617 Skein1024_Update(Skein1024_Ctxt_t *ctx, const uint8_t *msg, size_t msgByteCnt) 618 { 619 size_t n; 620 621 /* catch uninitialized context */ 622 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL); 623 624 /* process full blocks, if any */ 625 if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES) { 626 /* finish up any buffered message data */ 627 if (ctx->h.bCnt) { 628 /* # bytes free in buffer b[] */ 629 n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt; 630 if (n) { 631 /* check on our logic here */ 632 Skein_assert(n < msgByteCnt); 633 bcopy(msg, &ctx->b[ctx->h.bCnt], n); 634 msgByteCnt -= n; 635 msg += n; 636 ctx->h.bCnt += n; 637 } 638 Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES); 639 Skein1024_Process_Block(ctx, ctx->b, 1, 640 SKEIN1024_BLOCK_BYTES); 641 ctx->h.bCnt = 0; 642 } 643 /* 644 * now process any remaining full blocks, directly from 645 * input message data 646 */ 647 if (msgByteCnt > SKEIN1024_BLOCK_BYTES) { 648 /* number of full blocks to process */ 649 n = (msgByteCnt - 1) / SKEIN1024_BLOCK_BYTES; 650 Skein1024_Process_Block(ctx, msg, n, 651 SKEIN1024_BLOCK_BYTES); 652 msgByteCnt -= n * SKEIN1024_BLOCK_BYTES; 653 msg += n * SKEIN1024_BLOCK_BYTES; 654 } 655 Skein_assert(ctx->h.bCnt == 0); 656 } 657 658 /* copy any remaining source message data bytes into b[] */ 659 if (msgByteCnt) { 660 Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES); 661 bcopy(msg, &ctx->b[ctx->h.bCnt], msgByteCnt); 662 ctx->h.bCnt += msgByteCnt; 663 } 664 665 return (SKEIN_SUCCESS); 666 } 667 668 /* finalize the hash computation and output the result */ 669 int 670 Skein1024_Final(Skein1024_Ctxt_t *ctx, uint8_t *hashVal) 671 { 672 size_t i, n, byteCnt; 673 uint64_t X[SKEIN1024_STATE_WORDS]; 674 675 /* catch uninitialized context */ 676 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL); 677 678 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 679 /* zero pad b[] if necessary */ 680 if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) 681 bzero(&ctx->b[ctx->h.bCnt], 682 SKEIN1024_BLOCK_BYTES - ctx->h.bCnt); 683 684 /* process the final block */ 685 Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); 686 687 /* now output the result */ 688 /* total number of output bytes */ 689 byteCnt = (ctx->h.hashBitLen + 7) >> 3; 690 691 /* run Threefish in "counter mode" to generate output */ 692 /* zero out b[], so it can hold the counter */ 693 bzero(ctx->b, sizeof (ctx->b)); 694 /* keep a local copy of counter mode "key" */ 695 bcopy(ctx->X, X, sizeof (X)); 696 for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) { 697 /* build the counter block */ 698 uint64_t tmp = Skein_Swap64((uint64_t)i); 699 bcopy(&tmp, ctx->b, sizeof (tmp)); 700 Skein_Start_New_Type(ctx, OUT_FINAL); 701 /* run "counter mode" */ 702 Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); 703 /* number of output bytes left to go */ 704 n = byteCnt - i * SKEIN1024_BLOCK_BYTES; 705 if (n >= SKEIN1024_BLOCK_BYTES) 706 n = SKEIN1024_BLOCK_BYTES; 707 Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES, 708 ctx->X, n); /* "output" the ctr mode bytes */ 709 Skein_Show_Final(1024, &ctx->h, n, 710 hashVal + i * SKEIN1024_BLOCK_BYTES); 711 /* restore the counter mode key for next time */ 712 bcopy(X, ctx->X, sizeof (X)); 713 } 714 return (SKEIN_SUCCESS); 715 } 716 717 /* Functions to support MAC/tree hashing */ 718 /* (this code is identical for Optimized and Reference versions) */ 719 720 /* finalize the hash computation and output the block, no OUTPUT stage */ 721 int 722 Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, uint8_t *hashVal) 723 { 724 /* catch uninitialized context */ 725 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL); 726 727 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 728 /* zero pad b[] if necessary */ 729 if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) 730 bzero(&ctx->b[ctx->h.bCnt], 731 SKEIN_256_BLOCK_BYTES - ctx->h.bCnt); 732 /* process the final block */ 733 Skein_256_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); 734 735 /* "output" the state bytes */ 736 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_256_BLOCK_BYTES); 737 738 return (SKEIN_SUCCESS); 739 } 740 741 /* finalize the hash computation and output the block, no OUTPUT stage */ 742 int 743 Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, uint8_t *hashVal) 744 { 745 /* catch uninitialized context */ 746 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); 747 748 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 749 /* zero pad b[] if necessary */ 750 if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) 751 bzero(&ctx->b[ctx->h.bCnt], 752 SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); 753 /* process the final block */ 754 Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); 755 756 /* "output" the state bytes */ 757 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN_512_BLOCK_BYTES); 758 759 return (SKEIN_SUCCESS); 760 } 761 762 /* finalize the hash computation and output the block, no OUTPUT stage */ 763 int 764 Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, uint8_t *hashVal) 765 { 766 /* catch uninitialized context */ 767 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL); 768 769 /* tag as the final block */ 770 ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; 771 /* zero pad b[] if necessary */ 772 if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) 773 bzero(&ctx->b[ctx->h.bCnt], 774 SKEIN1024_BLOCK_BYTES - ctx->h.bCnt); 775 /* process the final block */ 776 Skein1024_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); 777 778 /* "output" the state bytes */ 779 Skein_Put64_LSB_First(hashVal, ctx->X, SKEIN1024_BLOCK_BYTES); 780 781 return (SKEIN_SUCCESS); 782 } 783 784 #if SKEIN_TREE_HASH 785 /* just do the OUTPUT stage */ 786 int 787 Skein_256_Output(Skein_256_Ctxt_t *ctx, uint8_t *hashVal) 788 { 789 size_t i, n, byteCnt; 790 uint64_t X[SKEIN_256_STATE_WORDS]; 791 792 /* catch uninitialized context */ 793 Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL); 794 795 /* now output the result */ 796 /* total number of output bytes */ 797 byteCnt = (ctx->h.hashBitLen + 7) >> 3; 798 799 /* run Threefish in "counter mode" to generate output */ 800 /* zero out b[], so it can hold the counter */ 801 bzero(ctx->b, sizeof (ctx->b)); 802 /* keep a local copy of counter mode "key" */ 803 bcopy(ctx->X, X, sizeof (X)); 804 for (i = 0; i * SKEIN_256_BLOCK_BYTES < byteCnt; i++) { 805 /* build the counter block */ 806 uint64_t tmp = Skein_Swap64((uint64_t)i); 807 bcopy(&tmp, ctx->b, sizeof (tmp)); 808 Skein_Start_New_Type(ctx, OUT_FINAL); 809 /* run "counter mode" */ 810 Skein_256_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); 811 /* number of output bytes left to go */ 812 n = byteCnt - i * SKEIN_256_BLOCK_BYTES; 813 if (n >= SKEIN_256_BLOCK_BYTES) 814 n = SKEIN_256_BLOCK_BYTES; 815 Skein_Put64_LSB_First(hashVal + i * SKEIN_256_BLOCK_BYTES, 816 ctx->X, n); /* "output" the ctr mode bytes */ 817 Skein_Show_Final(256, &ctx->h, n, 818 hashVal + i * SKEIN_256_BLOCK_BYTES); 819 /* restore the counter mode key for next time */ 820 bcopy(X, ctx->X, sizeof (X)); 821 } 822 return (SKEIN_SUCCESS); 823 } 824 825 /* just do the OUTPUT stage */ 826 int 827 Skein_512_Output(Skein_512_Ctxt_t *ctx, uint8_t *hashVal) 828 { 829 size_t i, n, byteCnt; 830 uint64_t X[SKEIN_512_STATE_WORDS]; 831 832 /* catch uninitialized context */ 833 Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); 834 835 /* now output the result */ 836 /* total number of output bytes */ 837 byteCnt = (ctx->h.hashBitLen + 7) >> 3; 838 839 /* run Threefish in "counter mode" to generate output */ 840 /* zero out b[], so it can hold the counter */ 841 bzero(ctx->b, sizeof (ctx->b)); 842 /* keep a local copy of counter mode "key" */ 843 bcopy(ctx->X, X, sizeof (X)); 844 for (i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) { 845 /* build the counter block */ 846 uint64_t tmp = Skein_Swap64((uint64_t)i); 847 bcopy(&tmp, ctx->b, sizeof (tmp)); 848 Skein_Start_New_Type(ctx, OUT_FINAL); 849 /* run "counter mode" */ 850 Skein_512_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); 851 /* number of output bytes left to go */ 852 n = byteCnt - i * SKEIN_512_BLOCK_BYTES; 853 if (n >= SKEIN_512_BLOCK_BYTES) 854 n = SKEIN_512_BLOCK_BYTES; 855 Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES, 856 ctx->X, n); /* "output" the ctr mode bytes */ 857 Skein_Show_Final(256, &ctx->h, n, 858 hashVal + i * SKEIN_512_BLOCK_BYTES); 859 /* restore the counter mode key for next time */ 860 bcopy(X, ctx->X, sizeof (X)); 861 } 862 return (SKEIN_SUCCESS); 863 } 864 865 /* just do the OUTPUT stage */ 866 int 867 Skein1024_Output(Skein1024_Ctxt_t *ctx, uint8_t *hashVal) 868 { 869 size_t i, n, byteCnt; 870 uint64_t X[SKEIN1024_STATE_WORDS]; 871 872 /* catch uninitialized context */ 873 Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES, SKEIN_FAIL); 874 875 /* now output the result */ 876 /* total number of output bytes */ 877 byteCnt = (ctx->h.hashBitLen + 7) >> 3; 878 879 /* run Threefish in "counter mode" to generate output */ 880 /* zero out b[], so it can hold the counter */ 881 bzero(ctx->b, sizeof (ctx->b)); 882 /* keep a local copy of counter mode "key" */ 883 bcopy(ctx->X, X, sizeof (X)); 884 for (i = 0; i * SKEIN1024_BLOCK_BYTES < byteCnt; i++) { 885 /* build the counter block */ 886 uint64_t tmp = Skein_Swap64((uint64_t)i); 887 bcopy(&tmp, ctx->b, sizeof (tmp)); 888 Skein_Start_New_Type(ctx, OUT_FINAL); 889 /* run "counter mode" */ 890 Skein1024_Process_Block(ctx, ctx->b, 1, sizeof (uint64_t)); 891 /* number of output bytes left to go */ 892 n = byteCnt - i * SKEIN1024_BLOCK_BYTES; 893 if (n >= SKEIN1024_BLOCK_BYTES) 894 n = SKEIN1024_BLOCK_BYTES; 895 Skein_Put64_LSB_First(hashVal + i * SKEIN1024_BLOCK_BYTES, 896 ctx->X, n); /* "output" the ctr mode bytes */ 897 Skein_Show_Final(256, &ctx->h, n, 898 hashVal + i * SKEIN1024_BLOCK_BYTES); 899 /* restore the counter mode key for next time */ 900 bcopy(X, ctx->X, sizeof (X)); 901 } 902 return (SKEIN_SUCCESS); 903 } 904 #endif 905 906 #ifdef _KERNEL 907 EXPORT_SYMBOL(Skein_512_Init); 908 EXPORT_SYMBOL(Skein_512_InitExt); 909 EXPORT_SYMBOL(Skein_512_Update); 910 EXPORT_SYMBOL(Skein_512_Final); 911 #endif 912