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