/* hash.c Aug 2011 * * Groestl implementation for different versions. * Author: Krystian Matusiewicz, Günther A. Roland, Martin Schläffer * * This code is placed in the public domain */ #include "hash-groestl.h" #include "miner.h" #ifndef NO_AES_NI #include "groestl-version.h" #ifdef TASM #ifdef VAES #include "groestl-asm-aes.h" #else #ifdef VAVX #include "groestl-asm-avx.h" #else #ifdef VVPERM #include "groestl-asm-vperm.h" #else #error NO VERSION SPECIFIED (-DV[AES/AVX/VVPERM]) #endif #endif #endif #else #ifdef TINTR #ifdef VAES #include "groestl-intr-aes.h" #else #ifdef VAVX #include "groestl-intr-avx.h" #else #ifdef VVPERM #include "groestl-intr-vperm.h" #else #error NO VERSION SPECIFIED (-DV[AES/AVX/VVPERM]) #endif #endif #endif #else #error NO TYPE SPECIFIED (-DT[ASM/INTR]) #endif #endif /* digest up to len bytes of input (full blocks only) */ void Transform(hashState_groestl *ctx, const u8 *in, unsigned long long len) { /* increment block counter */ ctx->block_counter += len/SIZE; /* digest message, one block at a time */ for (; len >= SIZE; len -= SIZE, in += SIZE) #if LENGTH<=256 TF512((u64*)ctx->chaining, (u64*)in); #else TF1024((u64*)ctx->chaining, (u64*)in); #endif asm volatile ("emms"); } /* given state h, do h <- P(h)+h */ void OutputTransformation(hashState_groestl *ctx) { /* determine variant */ #if (LENGTH <= 256) OF512((u64*)ctx->chaining); #else OF1024((u64*)ctx->chaining); #endif asm volatile ("emms"); } /* initialise context */ HashReturn_gr init_groestl(hashState_groestl* ctx) { u8 i = 0; /* output size (in bits) must be a positive integer less than or equal to 512, and divisible by 8 */ if (LENGTH <= 0 || (LENGTH%8) || LENGTH > 512) return BAD_HASHBITLEN_GR; /* set number of state columns and state size depending on variant */ ctx->columns = COLS; ctx->statesize = SIZE; #if (LENGTH <= 256) ctx->v = SHoRT; #else ctx->v = LoNG; #endif SET_CONSTANTS(); for (i=0; ichaining[i] = 0; for (i=0; ibuffer[i] = 0; if (ctx->chaining == NULL || ctx->buffer == NULL) return FAIL_GR; /* set initial value */ ctx->chaining[ctx->columns-1] = U64BIG((u64)LENGTH); INIT(ctx->chaining); /* set other variables */ ctx->buf_ptr = 0; ctx->block_counter = 0; ctx->bits_in_last_byte = 0; return SUCCESS_GR; } HashReturn_gr reinit_groestl(hashState_groestl* ctx) { int i; for (i=0; ichaining[i] = 0; for (i=0; ibuffer[i] = 0; if (ctx->chaining == NULL || ctx->buffer == NULL) return FAIL_GR; /* set initial value */ ctx->chaining[ctx->columns-1] = U64BIG((u64)LENGTH); INIT(ctx->chaining); /* set other variables */ ctx->buf_ptr = 0; ctx->block_counter = 0; // not used ctx->bits_in_last_byte = 0; return SUCCESS_GR; } /* update state with databitlen bits of input */ HashReturn_gr update_groestl(hashState_groestl* ctx, const BitSequence_gr* input, DataLength_gr databitlen) { int index = 0; int msglen = (int)(databitlen/8); int rem = (int)(databitlen%8); // not used // The only data length used is either 64 bytes (512 bits, // or 80 bytes (640 bits). The sph version of groestl used a byte // size for the data length, so odd bits aren't supported there. // No need to support them here either, change the arg to bytes // for consistency. /* non-integral number of message bytes can only be supplied in the last call to this function */ if (ctx->bits_in_last_byte) return FAIL_GR; /* if the buffer contains data that has not yet been digested, first add data to buffer until full */ //// This code can never run, it is indeed dead. buf_ptr is initialized //// to 0 in init_groestl and hasn't been changed yet // The following block of code never gets hit when hashing x11 or quark // leave it here in case it might be needed. // if (ctx->buf_ptr) // { // while (ctx->buf_ptr < ctx->statesize && index < msglen) // { // ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; // } // if (ctx->buf_ptr < ctx->statesize) // { // /* buffer still not full, return */ // if (rem) // { // ctx->bits_in_last_byte = rem; // ctx->buffer[(int)ctx->buf_ptr++] = input[index]; // } // return SUCCESS_GR; // } // /* digest buffer */ // ctx->buf_ptr = 0; // printf("error\n"); // Transform(ctx, ctx->buffer, ctx->statesize); // end dead code // } /* digest bulk of message */ Transform(ctx, input+index, msglen-index); // index is always zero here, the following line sets it == msglen // meaning the next while test will always fail. it's all part of // supporting odd bits. index += ((msglen-index)/ctx->statesize)*ctx->statesize; /* store remaining data in buffer */ while (index < msglen) { ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; } // buf_ptr should be msglen now. //// This code isn't quite dead but but would only run if datalen /// is not a multiple of 8. As a result bits_in_last_byte is never //// modified from its initial zero. // Another block that doesn't get used by x11 or quark // /* if non-integral number of bytes have been supplied, store // remaining bits in last byte, together with information about // number of bits */ // if (rem) // { // ctx->bits_in_last_byte = rem; // ctx->buffer[(int)ctx->buf_ptr++] = input[index]; // } return SUCCESS_GR; } #define BILB ctx->bits_in_last_byte /* finalise: process remaining data (including padding), perform output transformation, and write hash result to 'output' */ HashReturn_gr final_groestl(hashState_groestl* ctx, BitSequence_gr* output) { int i, j = 0, hashbytelen = LENGTH/8; u8 *s = (BitSequence_gr*)ctx->chaining; /* pad with '1'-bit and first few '0'-bits */ if (BILB) { ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB); BILB = 0; } //This sets the first pad byte else ctx->buffer[(int)ctx->buf_ptr++] = 0x80; // buf_ptr is left == msglen after update_groestl, 64 (bytes). // It has now been incrememnted to 65. The test below should fail // with 64 and 80 and require 1 pad block. Why does 64 bit need a pad block? // length padding? /* pad with '0'-bits */ if (ctx->buf_ptr > ctx->statesize-LENGTHFIELDLEN) { /* padding requires two blocks */ while (ctx->buf_ptr < ctx->statesize) { ctx->buffer[(int)ctx->buf_ptr++] = 0; } /* digest first padding block */ Transform(ctx, ctx->buffer, ctx->statesize); ctx->buf_ptr = 0; } // the padding can be vectorized, including the first pad byte above // 64 bit: buffer[64..79] = {0x80000000,0,0,0} // buffer[80..95] = {0,0,0,0} // buffer[96..111] = {0,0,0,0} // buffer[112..128 = {0,0,length padding} // 80 bit: buffer[64..79] = unchanged // buffer[80..95] = {0x800000000,0,0,0} // buffer[96..111] = {0,0,0,0} // buffer[112..128 = {0,0,length padding} // this will pad up to 120 bytes while (ctx->buf_ptr < ctx->statesize-LENGTHFIELDLEN) { ctx->buffer[(int)ctx->buf_ptr++] = 0; } /* length padding */ ctx->block_counter++; ctx->buf_ptr = ctx->statesize; while (ctx->buf_ptr > ctx->statesize-LENGTHFIELDLEN) { ctx->buffer[(int)--ctx->buf_ptr] = (u8)ctx->block_counter; ctx->block_counter >>= 8; } /* digest final padding block */ Transform(ctx, ctx->buffer, ctx->statesize); /* perform output transformation */ OutputTransformation(ctx); /* store hash result in output */ for (i = ctx->statesize-hashbytelen; i < ctx->statesize; i++,j++) { output[j] = s[i]; } // the following is redundant as init_groestl will reset to zero. /* zeroise relevant variables and deallocate memory */ for (i = 0; i < ctx->columns; i++) { ctx->chaining[i] = 0; } for (i = 0; i < ctx->statesize; i++) { ctx->buffer[i] = 0; } // free(ctx->chaining); // free(ctx->buffer); return SUCCESS_GR; } /* hash bit sequence */ HashReturn_gr hash_groestl(int hashbitlen, const BitSequence_gr* data, DataLength_gr databitlen, BitSequence_gr* hashval) { HashReturn_gr ret; hashState_groestl context; /* initialise */ if ((ret = init_groestl(&context)) != SUCCESS_GR) return ret; /* process message */ if ((ret = update_groestl(&context, data, databitlen)) != SUCCESS_GR) return ret; /* finalise */ ret = final_groestl(&context, hashval); return ret; } /* eBash API */ #ifdef crypto_hash_BYTES int crypto_hash(unsigned char *out, const unsigned char *in, unsigned long long inlen) { if (hash_groestl(crypto_hash_BYTES * 8, in, inlen * 8,out) == SUCCESS_GR) return 0; return -1; } #endif #endif