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