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