1300819Sallanjude/*********************************************************************** 2300819Sallanjude** 3300819Sallanjude** Implementation of the Skein hash function. 4300819Sallanjude** 5300819Sallanjude** Source code author: Doug Whiting, 2008. 6300819Sallanjude** 7300819Sallanjude** This algorithm and source code is released to the public domain. 8300819Sallanjude** 9300819Sallanjude************************************************************************/ 10300819Sallanjude 11300921Sallanjude#include <sys/cdefs.h> 12300921Sallanjude__FBSDID("$FreeBSD: releng/11.0/sys/crypto/skein/skein.c 300921 2016-05-29 01:15:36Z allanjude $"); 13300921Sallanjude 14300921Sallanjude#include <sys/endian.h> 15300921Sallanjude#include <sys/types.h> 16300921Sallanjude 17300921Sallanjude/* get the memcpy/memset functions */ 18300921Sallanjude#ifdef _KERNEL 19300921Sallanjude#include <sys/systm.h> 20300921Sallanjude#else 21300921Sallanjude#include <string.h> 22300921Sallanjude#endif 23300921Sallanjude 24300819Sallanjude#define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */ 25300819Sallanjude 26300819Sallanjude#include "skein.h" /* get the Skein API definitions */ 27300819Sallanjude#include "skein_iv.h" /* get precomputed IVs */ 28300819Sallanjude 29300819Sallanjude/*****************************************************************/ 30300819Sallanjude/* External function to process blkCnt (nonzero) full block(s) of data. */ 31300819Sallanjudevoid Skein_256_Process_Block(Skein_256_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd); 32300819Sallanjudevoid Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd); 33300819Sallanjudevoid Skein1024_Process_Block(Skein1024_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd); 34300819Sallanjude 35300819Sallanjude/*****************************************************************/ 36300819Sallanjude/* 256-bit Skein */ 37300819Sallanjude/*****************************************************************/ 38300819Sallanjude 39300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 40300819Sallanjude/* init the context for a straight hashing operation */ 41300819Sallanjudeint Skein_256_Init(Skein_256_Ctxt_t *ctx, size_t hashBitLen) 42300819Sallanjude { 43300819Sallanjude union 44300819Sallanjude { 45300819Sallanjude u08b_t b[SKEIN_256_STATE_BYTES]; 46300819Sallanjude u64b_t w[SKEIN_256_STATE_WORDS]; 47300819Sallanjude } cfg; /* config block */ 48300819Sallanjude 49300819Sallanjude Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); 50300819Sallanjude ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 51300819Sallanjude 52300819Sallanjude switch (hashBitLen) 53300819Sallanjude { /* use pre-computed values, where available */ 54300819Sallanjude#ifndef SKEIN_NO_PRECOMP 55300819Sallanjude case 256: memcpy(ctx->X,SKEIN_256_IV_256,sizeof(ctx->X)); break; 56300819Sallanjude case 224: memcpy(ctx->X,SKEIN_256_IV_224,sizeof(ctx->X)); break; 57300819Sallanjude case 160: memcpy(ctx->X,SKEIN_256_IV_160,sizeof(ctx->X)); break; 58300819Sallanjude case 128: memcpy(ctx->X,SKEIN_256_IV_128,sizeof(ctx->X)); break; 59300819Sallanjude#endif 60300819Sallanjude default: 61300819Sallanjude /* here if there is no precomputed IV value available */ 62300819Sallanjude /* build/process the config block, type == CONFIG (could be precomputed) */ 63300819Sallanjude Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */ 64300819Sallanjude 65300819Sallanjude cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */ 66300819Sallanjude cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ 67300819Sallanjude cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); 68300819Sallanjude memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */ 69300819Sallanjude 70300819Sallanjude /* compute the initial chaining values from config block */ 71300819Sallanjude memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */ 72300819Sallanjude Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); 73300819Sallanjude break; 74300819Sallanjude } 75300819Sallanjude /* The chaining vars ctx->X are now initialized for the given hashBitLen. */ 76300819Sallanjude /* Set up to process the data message portion of the hash (default) */ 77300819Sallanjude Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */ 78300819Sallanjude 79300819Sallanjude return SKEIN_SUCCESS; 80300819Sallanjude } 81300819Sallanjude 82300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 83300819Sallanjude/* init the context for a MAC and/or tree hash operation */ 84300819Sallanjude/* [identical to Skein_256_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */ 85300819Sallanjudeint Skein_256_InitExt(Skein_256_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes) 86300819Sallanjude { 87300819Sallanjude union 88300819Sallanjude { 89300819Sallanjude u08b_t b[SKEIN_256_STATE_BYTES]; 90300819Sallanjude u64b_t w[SKEIN_256_STATE_WORDS]; 91300819Sallanjude } cfg; /* config block */ 92300819Sallanjude 93300819Sallanjude Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); 94300819Sallanjude Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL); 95300819Sallanjude 96300819Sallanjude /* compute the initial chaining values ctx->X[], based on key */ 97300819Sallanjude if (keyBytes == 0) /* is there a key? */ 98300819Sallanjude { 99300819Sallanjude memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */ 100300819Sallanjude } 101300819Sallanjude else /* here to pre-process a key */ 102300819Sallanjude { 103300819Sallanjude Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X)); 104300819Sallanjude /* do a mini-Init right here */ 105300819Sallanjude ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */ 106300819Sallanjude Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */ 107300819Sallanjude memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */ 108300819Sallanjude Skein_256_Update(ctx,key,keyBytes); /* hash the key */ 109300819Sallanjude Skein_256_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */ 110300819Sallanjude memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */ 111300819Sallanjude#if SKEIN_NEED_SWAP 112300819Sallanjude { 113300819Sallanjude uint_t i; 114300819Sallanjude for (i=0;i<SKEIN_256_STATE_WORDS;i++) /* convert key bytes to context words */ 115300819Sallanjude ctx->X[i] = Skein_Swap64(ctx->X[i]); 116300819Sallanjude } 117300819Sallanjude#endif 118300819Sallanjude } 119300819Sallanjude /* build/process the config block, type == CONFIG (could be precomputed for each key) */ 120300819Sallanjude ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 121300819Sallanjude Skein_Start_New_Type(ctx,CFG_FINAL); 122300819Sallanjude 123300819Sallanjude memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */ 124300819Sallanjude cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); 125300819Sallanjude cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ 126300819Sallanjude cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ 127300819Sallanjude 128300819Sallanjude Skein_Show_Key(256,&ctx->h,key,keyBytes); 129300819Sallanjude 130300819Sallanjude /* compute the initial chaining values from config block */ 131300819Sallanjude Skein_256_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); 132300819Sallanjude 133300819Sallanjude /* The chaining vars ctx->X are now initialized */ 134300819Sallanjude /* Set up to process the data message portion of the hash (default) */ 135300819Sallanjude ctx->h.bCnt = 0; /* buffer b[] starts out empty */ 136300819Sallanjude Skein_Start_New_Type(ctx,MSG); 137300819Sallanjude 138300819Sallanjude return SKEIN_SUCCESS; 139300819Sallanjude } 140300819Sallanjude 141300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 142300819Sallanjude/* process the input bytes */ 143300819Sallanjudeint Skein_256_Update(Skein_256_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt) 144300819Sallanjude { 145300819Sallanjude size_t n; 146300819Sallanjude 147300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 148300819Sallanjude 149300819Sallanjude /* process full blocks, if any */ 150300819Sallanjude if (msgByteCnt + ctx->h.bCnt > SKEIN_256_BLOCK_BYTES) 151300819Sallanjude { 152300819Sallanjude if (ctx->h.bCnt) /* finish up any buffered message data */ 153300819Sallanjude { 154300819Sallanjude n = SKEIN_256_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */ 155300819Sallanjude if (n) 156300819Sallanjude { 157300819Sallanjude Skein_assert(n < msgByteCnt); /* check on our logic here */ 158300819Sallanjude memcpy(&ctx->b[ctx->h.bCnt],msg,n); 159300819Sallanjude msgByteCnt -= n; 160300819Sallanjude msg += n; 161300819Sallanjude ctx->h.bCnt += n; 162300819Sallanjude } 163300819Sallanjude Skein_assert(ctx->h.bCnt == SKEIN_256_BLOCK_BYTES); 164300819Sallanjude Skein_256_Process_Block(ctx,ctx->b,1,SKEIN_256_BLOCK_BYTES); 165300819Sallanjude ctx->h.bCnt = 0; 166300819Sallanjude } 167300819Sallanjude /* now process any remaining full blocks, directly from input message data */ 168300819Sallanjude if (msgByteCnt > SKEIN_256_BLOCK_BYTES) 169300819Sallanjude { 170300819Sallanjude n = (msgByteCnt-1) / SKEIN_256_BLOCK_BYTES; /* number of full blocks to process */ 171300819Sallanjude Skein_256_Process_Block(ctx,msg,n,SKEIN_256_BLOCK_BYTES); 172300819Sallanjude msgByteCnt -= n * SKEIN_256_BLOCK_BYTES; 173300819Sallanjude msg += n * SKEIN_256_BLOCK_BYTES; 174300819Sallanjude } 175300819Sallanjude Skein_assert(ctx->h.bCnt == 0); 176300819Sallanjude } 177300819Sallanjude 178300819Sallanjude /* copy any remaining source message data bytes into b[] */ 179300819Sallanjude if (msgByteCnt) 180300819Sallanjude { 181300819Sallanjude Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES); 182300819Sallanjude memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt); 183300819Sallanjude ctx->h.bCnt += msgByteCnt; 184300819Sallanjude } 185300819Sallanjude 186300819Sallanjude return SKEIN_SUCCESS; 187300819Sallanjude } 188300819Sallanjude 189300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 190300819Sallanjude/* finalize the hash computation and output the result */ 191300819Sallanjudeint Skein_256_Final(Skein_256_Ctxt_t *ctx, u08b_t *hashVal) 192300819Sallanjude { 193300819Sallanjude size_t i,n,byteCnt; 194300819Sallanjude u64b_t X[SKEIN_256_STATE_WORDS]; 195300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 196300819Sallanjude 197300819Sallanjude ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 198300819Sallanjude if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) /* zero pad b[] if necessary */ 199300819Sallanjude memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt); 200300819Sallanjude 201300819Sallanjude Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ 202300819Sallanjude 203300819Sallanjude /* now output the result */ 204300819Sallanjude byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ 205300819Sallanjude 206300819Sallanjude /* run Threefish in "counter mode" to generate output */ 207300819Sallanjude memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ 208300819Sallanjude memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ 209300819Sallanjude for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++) 210300819Sallanjude { 211300819Sallanjude ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ 212300819Sallanjude Skein_Start_New_Type(ctx,OUT_FINAL); 213300819Sallanjude Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ 214300819Sallanjude n = byteCnt - i*SKEIN_256_BLOCK_BYTES; /* number of output bytes left to go */ 215300819Sallanjude if (n >= SKEIN_256_BLOCK_BYTES) 216300819Sallanjude n = SKEIN_256_BLOCK_BYTES; 217300819Sallanjude Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ 218300819Sallanjude Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES); 219300819Sallanjude memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ 220300819Sallanjude } 221300819Sallanjude return SKEIN_SUCCESS; 222300819Sallanjude } 223300819Sallanjude 224300819Sallanjude#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) 225300819Sallanjudesize_t Skein_256_API_CodeSize(void) 226300819Sallanjude { 227300819Sallanjude return ((u08b_t *) Skein_256_API_CodeSize) - 228300819Sallanjude ((u08b_t *) Skein_256_Init); 229300819Sallanjude } 230300819Sallanjude#endif 231300819Sallanjude 232300819Sallanjude/*****************************************************************/ 233300819Sallanjude/* 512-bit Skein */ 234300819Sallanjude/*****************************************************************/ 235300819Sallanjude 236300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 237300819Sallanjude/* init the context for a straight hashing operation */ 238300819Sallanjudeint Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen) 239300819Sallanjude { 240300819Sallanjude union 241300819Sallanjude { 242300819Sallanjude u08b_t b[SKEIN_512_STATE_BYTES]; 243300819Sallanjude u64b_t w[SKEIN_512_STATE_WORDS]; 244300819Sallanjude } cfg; /* config block */ 245300819Sallanjude 246300819Sallanjude Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); 247300819Sallanjude ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 248300819Sallanjude 249300819Sallanjude switch (hashBitLen) 250300819Sallanjude { /* use pre-computed values, where available */ 251300819Sallanjude#ifndef SKEIN_NO_PRECOMP 252300819Sallanjude case 512: memcpy(ctx->X,SKEIN_512_IV_512,sizeof(ctx->X)); break; 253300819Sallanjude case 384: memcpy(ctx->X,SKEIN_512_IV_384,sizeof(ctx->X)); break; 254300819Sallanjude case 256: memcpy(ctx->X,SKEIN_512_IV_256,sizeof(ctx->X)); break; 255300819Sallanjude case 224: memcpy(ctx->X,SKEIN_512_IV_224,sizeof(ctx->X)); break; 256300819Sallanjude#endif 257300819Sallanjude default: 258300819Sallanjude /* here if there is no precomputed IV value available */ 259300819Sallanjude /* build/process the config block, type == CONFIG (could be precomputed) */ 260300819Sallanjude Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */ 261300819Sallanjude 262300819Sallanjude cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */ 263300819Sallanjude cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ 264300819Sallanjude cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); 265300819Sallanjude memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */ 266300819Sallanjude 267300819Sallanjude /* compute the initial chaining values from config block */ 268300819Sallanjude memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */ 269300819Sallanjude Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); 270300819Sallanjude break; 271300819Sallanjude } 272300819Sallanjude 273300819Sallanjude /* The chaining vars ctx->X are now initialized for the given hashBitLen. */ 274300819Sallanjude /* Set up to process the data message portion of the hash (default) */ 275300819Sallanjude Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */ 276300819Sallanjude 277300819Sallanjude return SKEIN_SUCCESS; 278300819Sallanjude } 279300819Sallanjude 280300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 281300819Sallanjude/* init the context for a MAC and/or tree hash operation */ 282300819Sallanjude/* [identical to Skein_512_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */ 283300819Sallanjudeint Skein_512_InitExt(Skein_512_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes) 284300819Sallanjude { 285300819Sallanjude union 286300819Sallanjude { 287300819Sallanjude u08b_t b[SKEIN_512_STATE_BYTES]; 288300819Sallanjude u64b_t w[SKEIN_512_STATE_WORDS]; 289300819Sallanjude } cfg; /* config block */ 290300819Sallanjude 291300819Sallanjude Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); 292300819Sallanjude Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL); 293300819Sallanjude 294300819Sallanjude /* compute the initial chaining values ctx->X[], based on key */ 295300819Sallanjude if (keyBytes == 0) /* is there a key? */ 296300819Sallanjude { 297300819Sallanjude memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */ 298300819Sallanjude } 299300819Sallanjude else /* here to pre-process a key */ 300300819Sallanjude { 301300819Sallanjude Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X)); 302300819Sallanjude /* do a mini-Init right here */ 303300819Sallanjude ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */ 304300819Sallanjude Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */ 305300819Sallanjude memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */ 306300819Sallanjude Skein_512_Update(ctx,key,keyBytes); /* hash the key */ 307300819Sallanjude Skein_512_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */ 308300819Sallanjude memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */ 309300819Sallanjude#if SKEIN_NEED_SWAP 310300819Sallanjude { 311300819Sallanjude uint_t i; 312300819Sallanjude for (i=0;i<SKEIN_512_STATE_WORDS;i++) /* convert key bytes to context words */ 313300819Sallanjude ctx->X[i] = Skein_Swap64(ctx->X[i]); 314300819Sallanjude } 315300819Sallanjude#endif 316300819Sallanjude } 317300819Sallanjude /* build/process the config block, type == CONFIG (could be precomputed for each key) */ 318300819Sallanjude ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 319300819Sallanjude Skein_Start_New_Type(ctx,CFG_FINAL); 320300819Sallanjude 321300819Sallanjude memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */ 322300819Sallanjude cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); 323300819Sallanjude cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ 324300819Sallanjude cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ 325300819Sallanjude 326300819Sallanjude Skein_Show_Key(512,&ctx->h,key,keyBytes); 327300819Sallanjude 328300819Sallanjude /* compute the initial chaining values from config block */ 329300819Sallanjude Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); 330300819Sallanjude 331300819Sallanjude /* The chaining vars ctx->X are now initialized */ 332300819Sallanjude /* Set up to process the data message portion of the hash (default) */ 333300819Sallanjude ctx->h.bCnt = 0; /* buffer b[] starts out empty */ 334300819Sallanjude Skein_Start_New_Type(ctx,MSG); 335300819Sallanjude 336300819Sallanjude return SKEIN_SUCCESS; 337300819Sallanjude } 338300819Sallanjude 339300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 340300819Sallanjude/* process the input bytes */ 341300819Sallanjudeint Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt) 342300819Sallanjude { 343300819Sallanjude size_t n; 344300819Sallanjude 345300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 346300819Sallanjude 347300819Sallanjude /* process full blocks, if any */ 348300819Sallanjude if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) 349300819Sallanjude { 350300819Sallanjude if (ctx->h.bCnt) /* finish up any buffered message data */ 351300819Sallanjude { 352300819Sallanjude n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */ 353300819Sallanjude if (n) 354300819Sallanjude { 355300819Sallanjude Skein_assert(n < msgByteCnt); /* check on our logic here */ 356300819Sallanjude memcpy(&ctx->b[ctx->h.bCnt],msg,n); 357300819Sallanjude msgByteCnt -= n; 358300819Sallanjude msg += n; 359300819Sallanjude ctx->h.bCnt += n; 360300819Sallanjude } 361300819Sallanjude Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES); 362300819Sallanjude Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES); 363300819Sallanjude ctx->h.bCnt = 0; 364300819Sallanjude } 365300819Sallanjude /* now process any remaining full blocks, directly from input message data */ 366300819Sallanjude if (msgByteCnt > SKEIN_512_BLOCK_BYTES) 367300819Sallanjude { 368300819Sallanjude n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES; /* number of full blocks to process */ 369300819Sallanjude Skein_512_Process_Block(ctx,msg,n,SKEIN_512_BLOCK_BYTES); 370300819Sallanjude msgByteCnt -= n * SKEIN_512_BLOCK_BYTES; 371300819Sallanjude msg += n * SKEIN_512_BLOCK_BYTES; 372300819Sallanjude } 373300819Sallanjude Skein_assert(ctx->h.bCnt == 0); 374300819Sallanjude } 375300819Sallanjude 376300819Sallanjude /* copy any remaining source message data bytes into b[] */ 377300819Sallanjude if (msgByteCnt) 378300819Sallanjude { 379300819Sallanjude Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES); 380300819Sallanjude memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt); 381300819Sallanjude ctx->h.bCnt += msgByteCnt; 382300819Sallanjude } 383300819Sallanjude 384300819Sallanjude return SKEIN_SUCCESS; 385300819Sallanjude } 386300819Sallanjude 387300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 388300819Sallanjude/* finalize the hash computation and output the result */ 389300819Sallanjudeint Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal) 390300819Sallanjude { 391300819Sallanjude size_t i,n,byteCnt; 392300819Sallanjude u64b_t X[SKEIN_512_STATE_WORDS]; 393300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 394300819Sallanjude 395300819Sallanjude ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 396300819Sallanjude if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */ 397300819Sallanjude memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); 398300819Sallanjude 399300819Sallanjude Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ 400300819Sallanjude 401300819Sallanjude /* now output the result */ 402300819Sallanjude byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ 403300819Sallanjude 404300819Sallanjude /* run Threefish in "counter mode" to generate output */ 405300819Sallanjude memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ 406300819Sallanjude memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ 407300819Sallanjude for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++) 408300819Sallanjude { 409300819Sallanjude ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ 410300819Sallanjude Skein_Start_New_Type(ctx,OUT_FINAL); 411300819Sallanjude Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ 412300819Sallanjude n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */ 413300819Sallanjude if (n >= SKEIN_512_BLOCK_BYTES) 414300819Sallanjude n = SKEIN_512_BLOCK_BYTES; 415300819Sallanjude Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ 416300819Sallanjude Skein_Show_Final(512,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES); 417300819Sallanjude memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ 418300819Sallanjude } 419300819Sallanjude return SKEIN_SUCCESS; 420300819Sallanjude } 421300819Sallanjude 422300819Sallanjude#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) 423300819Sallanjudesize_t Skein_512_API_CodeSize(void) 424300819Sallanjude { 425300819Sallanjude return ((u08b_t *) Skein_512_API_CodeSize) - 426300819Sallanjude ((u08b_t *) Skein_512_Init); 427300819Sallanjude } 428300819Sallanjude#endif 429300819Sallanjude 430300819Sallanjude/*****************************************************************/ 431300819Sallanjude/* 1024-bit Skein */ 432300819Sallanjude/*****************************************************************/ 433300819Sallanjude 434300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 435300819Sallanjude/* init the context for a straight hashing operation */ 436300819Sallanjudeint Skein1024_Init(Skein1024_Ctxt_t *ctx, size_t hashBitLen) 437300819Sallanjude { 438300819Sallanjude union 439300819Sallanjude { 440300819Sallanjude u08b_t b[SKEIN1024_STATE_BYTES]; 441300819Sallanjude u64b_t w[SKEIN1024_STATE_WORDS]; 442300819Sallanjude } cfg; /* config block */ 443300819Sallanjude 444300819Sallanjude Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); 445300819Sallanjude ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 446300819Sallanjude 447300819Sallanjude switch (hashBitLen) 448300819Sallanjude { /* use pre-computed values, where available */ 449300819Sallanjude#ifndef SKEIN_NO_PRECOMP 450300819Sallanjude case 512: memcpy(ctx->X,SKEIN1024_IV_512 ,sizeof(ctx->X)); break; 451300819Sallanjude case 384: memcpy(ctx->X,SKEIN1024_IV_384 ,sizeof(ctx->X)); break; 452300819Sallanjude case 1024: memcpy(ctx->X,SKEIN1024_IV_1024,sizeof(ctx->X)); break; 453300819Sallanjude#endif 454300819Sallanjude default: 455300819Sallanjude /* here if there is no precomputed IV value available */ 456300819Sallanjude /* build/process the config block, type == CONFIG (could be precomputed) */ 457300819Sallanjude Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */ 458300819Sallanjude 459300819Sallanjude cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */ 460300819Sallanjude cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ 461300819Sallanjude cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); 462300819Sallanjude memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */ 463300819Sallanjude 464300819Sallanjude /* compute the initial chaining values from config block */ 465300819Sallanjude memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */ 466300819Sallanjude Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); 467300819Sallanjude break; 468300819Sallanjude } 469300819Sallanjude 470300819Sallanjude /* The chaining vars ctx->X are now initialized for the given hashBitLen. */ 471300819Sallanjude /* Set up to process the data message portion of the hash (default) */ 472300819Sallanjude Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */ 473300819Sallanjude 474300819Sallanjude return SKEIN_SUCCESS; 475300819Sallanjude } 476300819Sallanjude 477300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 478300819Sallanjude/* init the context for a MAC and/or tree hash operation */ 479300819Sallanjude/* [identical to Skein1024_Init() when keyBytes == 0 && treeInfo == SKEIN_CFG_TREE_INFO_SEQUENTIAL] */ 480300819Sallanjudeint Skein1024_InitExt(Skein1024_Ctxt_t *ctx,size_t hashBitLen,u64b_t treeInfo, const u08b_t *key, size_t keyBytes) 481300819Sallanjude { 482300819Sallanjude union 483300819Sallanjude { 484300819Sallanjude u08b_t b[SKEIN1024_STATE_BYTES]; 485300819Sallanjude u64b_t w[SKEIN1024_STATE_WORDS]; 486300819Sallanjude } cfg; /* config block */ 487300819Sallanjude 488300819Sallanjude Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); 489300819Sallanjude Skein_Assert(keyBytes == 0 || key != NULL,SKEIN_FAIL); 490300819Sallanjude 491300819Sallanjude /* compute the initial chaining values ctx->X[], based on key */ 492300819Sallanjude if (keyBytes == 0) /* is there a key? */ 493300819Sallanjude { 494300819Sallanjude memset(ctx->X,0,sizeof(ctx->X)); /* no key: use all zeroes as key for config block */ 495300819Sallanjude } 496300819Sallanjude else /* here to pre-process a key */ 497300819Sallanjude { 498300819Sallanjude Skein_assert(sizeof(cfg.b) >= sizeof(ctx->X)); 499300819Sallanjude /* do a mini-Init right here */ 500300819Sallanjude ctx->h.hashBitLen=8*sizeof(ctx->X); /* set output hash bit count = state size */ 501300819Sallanjude Skein_Start_New_Type(ctx,KEY); /* set tweaks: T0 = 0; T1 = KEY type */ 502300819Sallanjude memset(ctx->X,0,sizeof(ctx->X)); /* zero the initial chaining variables */ 503300819Sallanjude Skein1024_Update(ctx,key,keyBytes); /* hash the key */ 504300819Sallanjude Skein1024_Final_Pad(ctx,cfg.b); /* put result into cfg.b[] */ 505300819Sallanjude memcpy(ctx->X,cfg.b,sizeof(cfg.b)); /* copy over into ctx->X[] */ 506300819Sallanjude#if SKEIN_NEED_SWAP 507300819Sallanjude { 508300819Sallanjude uint_t i; 509300819Sallanjude for (i=0;i<SKEIN1024_STATE_WORDS;i++) /* convert key bytes to context words */ 510300819Sallanjude ctx->X[i] = Skein_Swap64(ctx->X[i]); 511300819Sallanjude } 512300819Sallanjude#endif 513300819Sallanjude } 514300819Sallanjude /* build/process the config block, type == CONFIG (could be precomputed for each key) */ 515300819Sallanjude ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ 516300819Sallanjude Skein_Start_New_Type(ctx,CFG_FINAL); 517300819Sallanjude 518300819Sallanjude memset(&cfg.w,0,sizeof(cfg.w)); /* pre-pad cfg.w[] with zeroes */ 519300819Sallanjude cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); 520300819Sallanjude cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ 521300819Sallanjude cfg.w[2] = Skein_Swap64(treeInfo); /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */ 522300819Sallanjude 523300819Sallanjude Skein_Show_Key(1024,&ctx->h,key,keyBytes); 524300819Sallanjude 525300819Sallanjude /* compute the initial chaining values from config block */ 526300819Sallanjude Skein1024_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); 527300819Sallanjude 528300819Sallanjude /* The chaining vars ctx->X are now initialized */ 529300819Sallanjude /* Set up to process the data message portion of the hash (default) */ 530300819Sallanjude ctx->h.bCnt = 0; /* buffer b[] starts out empty */ 531300819Sallanjude Skein_Start_New_Type(ctx,MSG); 532300819Sallanjude 533300819Sallanjude return SKEIN_SUCCESS; 534300819Sallanjude } 535300819Sallanjude 536300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 537300819Sallanjude/* process the input bytes */ 538300819Sallanjudeint Skein1024_Update(Skein1024_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt) 539300819Sallanjude { 540300819Sallanjude size_t n; 541300819Sallanjude 542300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 543300819Sallanjude 544300819Sallanjude /* process full blocks, if any */ 545300819Sallanjude if (msgByteCnt + ctx->h.bCnt > SKEIN1024_BLOCK_BYTES) 546300819Sallanjude { 547300819Sallanjude if (ctx->h.bCnt) /* finish up any buffered message data */ 548300819Sallanjude { 549300819Sallanjude n = SKEIN1024_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */ 550300819Sallanjude if (n) 551300819Sallanjude { 552300819Sallanjude Skein_assert(n < msgByteCnt); /* check on our logic here */ 553300819Sallanjude memcpy(&ctx->b[ctx->h.bCnt],msg,n); 554300819Sallanjude msgByteCnt -= n; 555300819Sallanjude msg += n; 556300819Sallanjude ctx->h.bCnt += n; 557300819Sallanjude } 558300819Sallanjude Skein_assert(ctx->h.bCnt == SKEIN1024_BLOCK_BYTES); 559300819Sallanjude Skein1024_Process_Block(ctx,ctx->b,1,SKEIN1024_BLOCK_BYTES); 560300819Sallanjude ctx->h.bCnt = 0; 561300819Sallanjude } 562300819Sallanjude /* now process any remaining full blocks, directly from input message data */ 563300819Sallanjude if (msgByteCnt > SKEIN1024_BLOCK_BYTES) 564300819Sallanjude { 565300819Sallanjude n = (msgByteCnt-1) / SKEIN1024_BLOCK_BYTES; /* number of full blocks to process */ 566300819Sallanjude Skein1024_Process_Block(ctx,msg,n,SKEIN1024_BLOCK_BYTES); 567300819Sallanjude msgByteCnt -= n * SKEIN1024_BLOCK_BYTES; 568300819Sallanjude msg += n * SKEIN1024_BLOCK_BYTES; 569300819Sallanjude } 570300819Sallanjude Skein_assert(ctx->h.bCnt == 0); 571300819Sallanjude } 572300819Sallanjude 573300819Sallanjude /* copy any remaining source message data bytes into b[] */ 574300819Sallanjude if (msgByteCnt) 575300819Sallanjude { 576300819Sallanjude Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES); 577300819Sallanjude memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt); 578300819Sallanjude ctx->h.bCnt += msgByteCnt; 579300819Sallanjude } 580300819Sallanjude 581300819Sallanjude return SKEIN_SUCCESS; 582300819Sallanjude } 583300819Sallanjude 584300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 585300819Sallanjude/* finalize the hash computation and output the result */ 586300819Sallanjudeint Skein1024_Final(Skein1024_Ctxt_t *ctx, u08b_t *hashVal) 587300819Sallanjude { 588300819Sallanjude size_t i,n,byteCnt; 589300819Sallanjude u64b_t X[SKEIN1024_STATE_WORDS]; 590300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 591300819Sallanjude 592300819Sallanjude ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 593300819Sallanjude if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) /* zero pad b[] if necessary */ 594300819Sallanjude memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt); 595300819Sallanjude 596300819Sallanjude Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ 597300819Sallanjude 598300819Sallanjude /* now output the result */ 599300819Sallanjude byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ 600300819Sallanjude 601300819Sallanjude /* run Threefish in "counter mode" to generate output */ 602300819Sallanjude memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ 603300819Sallanjude memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ 604300819Sallanjude for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++) 605300819Sallanjude { 606300819Sallanjude ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ 607300819Sallanjude Skein_Start_New_Type(ctx,OUT_FINAL); 608300819Sallanjude Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ 609300819Sallanjude n = byteCnt - i*SKEIN1024_BLOCK_BYTES; /* number of output bytes left to go */ 610300819Sallanjude if (n >= SKEIN1024_BLOCK_BYTES) 611300819Sallanjude n = SKEIN1024_BLOCK_BYTES; 612300819Sallanjude Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ 613300819Sallanjude Skein_Show_Final(1024,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES); 614300819Sallanjude memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ 615300819Sallanjude } 616300819Sallanjude return SKEIN_SUCCESS; 617300819Sallanjude } 618300819Sallanjude 619300819Sallanjude#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) 620300819Sallanjudesize_t Skein1024_API_CodeSize(void) 621300819Sallanjude { 622300819Sallanjude return ((u08b_t *) Skein1024_API_CodeSize) - 623300819Sallanjude ((u08b_t *) Skein1024_Init); 624300819Sallanjude } 625300819Sallanjude#endif 626300819Sallanjude 627300819Sallanjude/**************** Functions to support MAC/tree hashing ***************/ 628300819Sallanjude/* (this code is identical for Optimized and Reference versions) */ 629300819Sallanjude 630300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 631300819Sallanjude/* finalize the hash computation and output the block, no OUTPUT stage */ 632300819Sallanjudeint Skein_256_Final_Pad(Skein_256_Ctxt_t *ctx, u08b_t *hashVal) 633300819Sallanjude { 634300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 635300819Sallanjude 636300819Sallanjude ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 637300819Sallanjude if (ctx->h.bCnt < SKEIN_256_BLOCK_BYTES) /* zero pad b[] if necessary */ 638300819Sallanjude memset(&ctx->b[ctx->h.bCnt],0,SKEIN_256_BLOCK_BYTES - ctx->h.bCnt); 639300819Sallanjude Skein_256_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ 640300819Sallanjude 641300819Sallanjude Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_256_BLOCK_BYTES); /* "output" the state bytes */ 642300819Sallanjude 643300819Sallanjude return SKEIN_SUCCESS; 644300819Sallanjude } 645300819Sallanjude 646300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 647300819Sallanjude/* finalize the hash computation and output the block, no OUTPUT stage */ 648300819Sallanjudeint Skein_512_Final_Pad(Skein_512_Ctxt_t *ctx, u08b_t *hashVal) 649300819Sallanjude { 650300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 651300819Sallanjude 652300819Sallanjude ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 653300819Sallanjude if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */ 654300819Sallanjude memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); 655300819Sallanjude Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ 656300819Sallanjude 657300819Sallanjude Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN_512_BLOCK_BYTES); /* "output" the state bytes */ 658300819Sallanjude 659300819Sallanjude return SKEIN_SUCCESS; 660300819Sallanjude } 661300819Sallanjude 662300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 663300819Sallanjude/* finalize the hash computation and output the block, no OUTPUT stage */ 664300819Sallanjudeint Skein1024_Final_Pad(Skein1024_Ctxt_t *ctx, u08b_t *hashVal) 665300819Sallanjude { 666300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 667300819Sallanjude 668300819Sallanjude ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ 669300819Sallanjude if (ctx->h.bCnt < SKEIN1024_BLOCK_BYTES) /* zero pad b[] if necessary */ 670300819Sallanjude memset(&ctx->b[ctx->h.bCnt],0,SKEIN1024_BLOCK_BYTES - ctx->h.bCnt); 671300819Sallanjude Skein1024_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ 672300819Sallanjude 673300819Sallanjude Skein_Put64_LSB_First(hashVal,ctx->X,SKEIN1024_BLOCK_BYTES); /* "output" the state bytes */ 674300819Sallanjude 675300819Sallanjude return SKEIN_SUCCESS; 676300819Sallanjude } 677300819Sallanjude 678300819Sallanjude#if SKEIN_TREE_HASH 679300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 680300819Sallanjude/* just do the OUTPUT stage */ 681300819Sallanjudeint Skein_256_Output(Skein_256_Ctxt_t *ctx, u08b_t *hashVal) 682300819Sallanjude { 683300819Sallanjude size_t i,n,byteCnt; 684300819Sallanjude u64b_t X[SKEIN_256_STATE_WORDS]; 685300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN_256_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 686300819Sallanjude 687300819Sallanjude /* now output the result */ 688300819Sallanjude byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ 689300819Sallanjude 690300819Sallanjude /* run Threefish in "counter mode" to generate output */ 691300819Sallanjude memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ 692300819Sallanjude memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ 693300819Sallanjude for (i=0;i*SKEIN_256_BLOCK_BYTES < byteCnt;i++) 694300819Sallanjude { 695300819Sallanjude ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ 696300819Sallanjude Skein_Start_New_Type(ctx,OUT_FINAL); 697300819Sallanjude Skein_256_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ 698300819Sallanjude n = byteCnt - i*SKEIN_256_BLOCK_BYTES; /* number of output bytes left to go */ 699300819Sallanjude if (n >= SKEIN_256_BLOCK_BYTES) 700300819Sallanjude n = SKEIN_256_BLOCK_BYTES; 701300819Sallanjude Skein_Put64_LSB_First(hashVal+i*SKEIN_256_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ 702300819Sallanjude Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_256_BLOCK_BYTES); 703300819Sallanjude memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ 704300819Sallanjude } 705300819Sallanjude return SKEIN_SUCCESS; 706300819Sallanjude } 707300819Sallanjude 708300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 709300819Sallanjude/* just do the OUTPUT stage */ 710300819Sallanjudeint Skein_512_Output(Skein_512_Ctxt_t *ctx, u08b_t *hashVal) 711300819Sallanjude { 712300819Sallanjude size_t i,n,byteCnt; 713300819Sallanjude u64b_t X[SKEIN_512_STATE_WORDS]; 714300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 715300819Sallanjude 716300819Sallanjude /* now output the result */ 717300819Sallanjude byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ 718300819Sallanjude 719300819Sallanjude /* run Threefish in "counter mode" to generate output */ 720300819Sallanjude memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ 721300819Sallanjude memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ 722300819Sallanjude for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++) 723300819Sallanjude { 724300819Sallanjude ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ 725300819Sallanjude Skein_Start_New_Type(ctx,OUT_FINAL); 726300819Sallanjude Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ 727300819Sallanjude n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */ 728300819Sallanjude if (n >= SKEIN_512_BLOCK_BYTES) 729300819Sallanjude n = SKEIN_512_BLOCK_BYTES; 730300819Sallanjude Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ 731300819Sallanjude Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES); 732300819Sallanjude memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ 733300819Sallanjude } 734300819Sallanjude return SKEIN_SUCCESS; 735300819Sallanjude } 736300819Sallanjude 737300819Sallanjude/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 738300819Sallanjude/* just do the OUTPUT stage */ 739300819Sallanjudeint Skein1024_Output(Skein1024_Ctxt_t *ctx, u08b_t *hashVal) 740300819Sallanjude { 741300819Sallanjude size_t i,n,byteCnt; 742300819Sallanjude u64b_t X[SKEIN1024_STATE_WORDS]; 743300819Sallanjude Skein_Assert(ctx->h.bCnt <= SKEIN1024_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ 744300819Sallanjude 745300819Sallanjude /* now output the result */ 746300819Sallanjude byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ 747300819Sallanjude 748300819Sallanjude /* run Threefish in "counter mode" to generate output */ 749300819Sallanjude memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ 750300819Sallanjude memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ 751300819Sallanjude for (i=0;i*SKEIN1024_BLOCK_BYTES < byteCnt;i++) 752300819Sallanjude { 753300819Sallanjude ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ 754300819Sallanjude Skein_Start_New_Type(ctx,OUT_FINAL); 755300819Sallanjude Skein1024_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ 756300819Sallanjude n = byteCnt - i*SKEIN1024_BLOCK_BYTES; /* number of output bytes left to go */ 757300819Sallanjude if (n >= SKEIN1024_BLOCK_BYTES) 758300819Sallanjude n = SKEIN1024_BLOCK_BYTES; 759300819Sallanjude Skein_Put64_LSB_First(hashVal+i*SKEIN1024_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ 760300819Sallanjude Skein_Show_Final(256,&ctx->h,n,hashVal+i*SKEIN1024_BLOCK_BYTES); 761300819Sallanjude memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ 762300819Sallanjude } 763300819Sallanjude return SKEIN_SUCCESS; 764300819Sallanjude } 765300921Sallanjude 766300921Sallanjude 767300921Sallanjude/* Adapt the functions to match the prototype expected by libmd */ 768300921Sallanjudevoid 769300921SallanjudeSKEIN256_Init(SKEIN256_CTX * ctx) 770300921Sallanjude{ 771300921Sallanjude 772300921Sallanjude Skein_256_Init(ctx, 256); 773300921Sallanjude} 774300921Sallanjude 775300921Sallanjudevoid 776300921SallanjudeSKEIN512_Init(SKEIN512_CTX * ctx) 777300921Sallanjude{ 778300921Sallanjude 779300921Sallanjude Skein_512_Init(ctx, 512); 780300921Sallanjude} 781300921Sallanjude 782300921Sallanjudevoid 783300921SallanjudeSKEIN1024_Init(SKEIN1024_CTX * ctx) 784300921Sallanjude{ 785300921Sallanjude 786300921Sallanjude Skein1024_Init(ctx, 1024); 787300921Sallanjude} 788300921Sallanjude 789300921Sallanjudevoid 790300921SallanjudeSKEIN256_Update(SKEIN256_CTX * ctx, const void *in, size_t len) 791300921Sallanjude{ 792300921Sallanjude 793300921Sallanjude Skein_256_Update(ctx, in, len); 794300921Sallanjude} 795300921Sallanjude 796300921Sallanjudevoid 797300921SallanjudeSKEIN512_Update(SKEIN512_CTX * ctx, const void *in, size_t len) 798300921Sallanjude{ 799300921Sallanjude 800300921Sallanjude Skein_512_Update(ctx, in, len); 801300921Sallanjude} 802300921Sallanjude 803300921Sallanjudevoid 804300921SallanjudeSKEIN1024_Update(SKEIN1024_CTX * ctx, const void *in, size_t len) 805300921Sallanjude{ 806300921Sallanjude 807300921Sallanjude Skein1024_Update(ctx, in, len); 808300921Sallanjude} 809300921Sallanjude 810300921Sallanjudevoid 811300921SallanjudeSKEIN256_Final(unsigned char digest[static SKEIN_256_BLOCK_BYTES], SKEIN256_CTX *ctx) 812300921Sallanjude{ 813300921Sallanjude 814300921Sallanjude Skein_256_Final(ctx, digest); 815300921Sallanjude} 816300921Sallanjude 817300921Sallanjudevoid 818300921SallanjudeSKEIN512_Final(unsigned char digest[static SKEIN_512_BLOCK_BYTES], SKEIN512_CTX *ctx) 819300921Sallanjude{ 820300921Sallanjude 821300921Sallanjude Skein_512_Final(ctx, digest); 822300921Sallanjude} 823300921Sallanjude 824300921Sallanjudevoid 825300921SallanjudeSKEIN1024_Final(unsigned char digest[static SKEIN1024_BLOCK_BYTES], SKEIN1024_CTX *ctx) 826300921Sallanjude{ 827300921Sallanjude 828300921Sallanjude Skein1024_Final(ctx, digest); 829300921Sallanjude} 830300921Sallanjude 831300921Sallanjude#ifdef WEAK_REFS 832300921Sallanjude/* When building libmd, provide weak references. Note: this is not 833300921Sallanjude activated in the context of compiling these sources for internal 834300921Sallanjude use in libcrypt. 835300921Sallanjude */ 836300921Sallanjude#undef SKEIN256_Init 837300921Sallanjude__weak_reference(_libmd_SKEIN256_Init, SKEIN256_Init); 838300921Sallanjude#undef SKEIN256_Update 839300921Sallanjude__weak_reference(_libmd_SKEIN256_Update, SKEIN256_Update); 840300921Sallanjude#undef SKEIN256_Final 841300921Sallanjude__weak_reference(_libmd_SKEIN256_Final, SKEIN256_Final); 842300921Sallanjude 843300921Sallanjude#undef SKEIN512_Init 844300921Sallanjude__weak_reference(_libmd_SKEIN512_Init, SKEIN512_Init); 845300921Sallanjude#undef SKEIN512_Update 846300921Sallanjude__weak_reference(_libmd_SKEIN512_Update, SKEIN512_Update); 847300921Sallanjude#undef SKEIN512_Final 848300921Sallanjude__weak_reference(_libmd_SKEIN512_Final, SKEIN512_Final); 849300921Sallanjude 850300921Sallanjude#undef SKEIN1024_Init 851300921Sallanjude__weak_reference(_libmd_SKEIN1024_Init, SKEIN1024_Init); 852300921Sallanjude#undef SKEIN1024_Update 853300921Sallanjude__weak_reference(_libmd_SKEIN1024_Update, SKEIN1024_Update); 854300921Sallanjude#undef SKEIN1024_Final 855300921Sallanjude__weak_reference(_libmd_SKEIN1024_Final, SKEIN1024_Final); 856300819Sallanjude#endif 857300921Sallanjude 858300921Sallanjude#endif 859