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