/* given state h, do h <- P(h)+h */ static void OutputTransformation(hashState *ctx) { int j; uint32_t temp[2*COLS512]; uint32_t y[2*COLS512]; uint32_t z[2*COLS512]; for (j = 0; j < 2*COLS512; j++) { temp[j] = ctx->chaining[j]; } RND512P((uint8_t*)temp, y, 0x00000000); RND512P((uint8_t*)y, z, 0x00000001); RND512P((uint8_t*)z, y, 0x00000002); RND512P((uint8_t*)y, z, 0x00000003); RND512P((uint8_t*)z, y, 0x00000004); RND512P((uint8_t*)y, z, 0x00000005); RND512P((uint8_t*)z, y, 0x00000006); RND512P((uint8_t*)y, z, 0x00000007); RND512P((uint8_t*)z, y, 0x00000008); RND512P((uint8_t*)y, temp, 0x00000009); for (j = 0; j < 2*COLS512; j++) { ctx->chaining[j] ^= temp[j]; } }
void P(uint32_t *h, uint32_t *m) { int i; uint32_t roundConstantAddingValue; uint32_t roundConstant; for (i = 0; i < 2*COLS512; i++) { m[i] = h[i]^m[i]; } roundConstantAddingValue = 0x01010101; roundConstant = 0; for(i=0;i<10;i++) { RND512P(m, roundConstant); roundConstant += roundConstantAddingValue; } for (i = 0; i < 2*COLS512; i++) { h[i] ^= m[i]; } }
void F512(uint32_t *h, uint32_t *m) { int i; uint32_t roundConstantAddingValue; uint32_t roundConstant; uint32_t x[2*COLS512]; for (i = 0; i < 2*COLS512; i++) { x[i] = h[i]^m[i]; } roundConstantAddingValue = 0x01010101; roundConstant = 0; for(i=0;i<10;i++) { RND512Q(m, roundConstant); roundConstant += roundConstantAddingValue; } roundConstant = 0; for(i=0;i<10;i++) { RND512P(x, roundConstant); roundConstant += roundConstantAddingValue; } for (i = 0; i < 2*COLS512; i++) { h[i] ^= x[i]^m[i]; } }
/* given state h, do h <- P(h)+h */ void OutputTransformation(hashState *ctx) { int j; u64 temp[COLS1024]; u64 y[COLS1024]; u64 z[COLS1024]; /* determine variant */ switch (ctx->size) { case SHORT : for (j = 0; j < COLS512; j++) { temp[j] = ctx->chaining[j]; } RND512P(temp,z,U64BIG(0x0000000000000000ull)); RND512P(z,y,U64BIG(0x0100000000000000ull)); RND512P(y,z,U64BIG(0x0200000000000000ull)); RND512P(z,y,U64BIG(0x0300000000000000ull)); RND512P(y,z,U64BIG(0x0400000000000000ull)); RND512P(z,y,U64BIG(0x0500000000000000ull)); RND512P(y,z,U64BIG(0x0600000000000000ull)); RND512P(z,y,U64BIG(0x0700000000000000ull)); RND512P(y,z,U64BIG(0x0800000000000000ull)); RND512P(z,temp,U64BIG(0x0900000000000000ull)); for (j = 0; j < COLS512; j++) { ctx->chaining[j] ^= temp[j]; } break; case LONG : for (j = 0; j < COLS1024; j++) { temp[j] = ctx->chaining[j]; } RND1024P(temp,y,0); for (j = 1; j < ROUNDS1024-1; j += 2) { RND1024P(y,z,U64BIG(((u64)j)<<56)); RND1024P(z,y,U64BIG(((u64)j+1)<<56)); } RND1024P(y,temp,U64BIG(((u64)(ROUNDS1024-1))<<56)); for (j = 0; j < COLS1024; j++) { ctx->chaining[j] ^= temp[j]; } break; } }
/* compute compression function (short variants) */ static void F512(uint32_t *h, const uint32_t *m) { int i; uint32_t Ptmp[2*COLS512]; uint32_t Qtmp[2*COLS512]; uint32_t y[2*COLS512]; uint32_t z[2*COLS512]; for (i = 0; i < 2*COLS512; i++) { z[i] = m[i]; Ptmp[i] = h[i]^m[i]; } /* compute Q(m) */ RND512Q((uint8_t*)z, y, 0x00000000); RND512Q((uint8_t*)y, z, 0x01000000); RND512Q((uint8_t*)z, y, 0x02000000); RND512Q((uint8_t*)y, z, 0x03000000); RND512Q((uint8_t*)z, y, 0x04000000); RND512Q((uint8_t*)y, z, 0x05000000); RND512Q((uint8_t*)z, y, 0x06000000); RND512Q((uint8_t*)y, z, 0x07000000); RND512Q((uint8_t*)z, y, 0x08000000); RND512Q((uint8_t*)y, Qtmp, 0x09000000); /* compute P(h+m) */ RND512P((uint8_t*)Ptmp, y, 0x00000000); RND512P((uint8_t*)y, z, 0x00000001); RND512P((uint8_t*)z, y, 0x00000002); RND512P((uint8_t*)y, z, 0x00000003); RND512P((uint8_t*)z, y, 0x00000004); RND512P((uint8_t*)y, z, 0x00000005); RND512P((uint8_t*)z, y, 0x00000006); RND512P((uint8_t*)y, z, 0x00000007); RND512P((uint8_t*)z, y, 0x00000008); RND512P((uint8_t*)y, Ptmp, 0x00000009); /* compute P(h+m) + Q(m) + h */ for (i = 0; i < 2*COLS512; i++) { h[i] ^= Ptmp[i]^Qtmp[i]; } }
int crypto_hash(unsigned char *hashval, const unsigned char *data, unsigned long long databytelen) { uint8_t state[SIZE512]; uint8_t message_block[SIZE512]; uint32_t i, j, w; uint32_t bytes_remaining; uint64_t full_message_blocks = databytelen/64; //Setting initial state for(i=0;i<(SIZE512/sizeof(uint32_t));i++) { ((uint32_t*)state)[i] = 0; } //256BIT_HASH_SPECIFIC line state[55] = 1; //Initial value for hash length 256 bit when saving state in row order! while(full_message_blocks--) { for (i = 0; i < SIZE512; i++) { message_block[(i%8)*8+i/8] = data[i]; //zeilenweise speichern } P((uint32_t*)state, (uint32_t*)message_block); for (i = 0; i < SIZE512; i++) { message_block[(i%8)*8+i/8] = data[i]; //zeilenweise speichern } Q((uint32_t*)state, (uint32_t*)message_block); data += SIZE512; } //Padding bytes_remaining = ((uint32_t)databytelen)%64; if(bytes_remaining > (SIZE512-64/8-1)) //if only one padding block is needed (64 bit w + 1 byte for appending bit 1) { for(j=0;j<2;j++) { for(i=0;i<bytes_remaining;i++) { message_block[(i%8)*8+i/8] = data[i]; //zeilenweise speichern } //setting padding bit 1 message_block[(i%8)*8+i/8] = 0x80; i++; for(;i<SIZE512;i++) { message_block[(i%8)*8+i/8] = 0; } if(j==0) { P((uint32_t*)state, (uint32_t*)message_block); } else { Q((uint32_t*)state, (uint32_t*)message_block); } } } w = (-((uint32_t)8*databytelen)-65)&0x1FF; databytelen = (8*databytelen+w+65)/(SIZE512*8); for(j=0;j<2;j++) //j is 2 at this moment { i=0; if(bytes_remaining <= (SIZE512-64/8-1)) { for(;i<bytes_remaining;i++) { message_block[(i%8)*8+i/8] = data[i]; //zeilenweise speichern } message_block[(i%8)*8+i/8] = 0x80; i++; } for(;i<(SIZE512-(64/8));i++) { message_block[(i%8)*8+i/8] = 0; } full_message_blocks = databytelen; //temp copy of padding value for(i=SIZE512-1;i>=(SIZE512-64/8);i--) { message_block[(i%8)*8+i/8] = (uint8_t)full_message_blocks; full_message_blocks >>= 8; } if(j==0) { P((uint32_t*)state, (uint32_t*)message_block); } else { Q((uint32_t*)state, (uint32_t*)message_block); } } for (i = 0; i < SIZE512/sizeof(uint32_t); i++) { ((uint32_t*)message_block)[i] = ((uint32_t*)state)[i]; } w = 0; //round constant for(i=0;i<10;i++) { RND512P((uint32_t*)state, w); w += 0x01010101; } for (i = 0; i < 2*COLS512; i++) { ((uint32_t*)state)[i] ^= ((uint32_t*)message_block)[i]; } for (i = SIZE512-HASH_BIT_LEN/8; i < SIZE512; i++) { hashval[i-(SIZE512-HASH_BIT_LEN/8)] = state[(i%8)*8+i/8]; //zeilenweise speichern } return 0; }
/* the compression function (short variants) */ inline void F512(u64 *h, const u64 *m, u64 *c) { //modified u64 y[COLS512] __attribute__((aligned(16))); u64 z[COLS512] __attribute__((aligned(16))); u64 outQ[COLS512] __attribute__((aligned(16))); u64 inP[COLS512] __attribute__((aligned(16))); int i,j=0; //ADDED By Gurpreet u64 ml[COLS512] __attribute__((aligned(16))); //msg_left u64 mr[COLS512] __attribute__((aligned(16))); //msg_right j=0; /*divide msg into two 512 blocks*/ for (i = 0; i < COLS1024; i++) { //modified if(i<COLS512){ ml[i] = m[i]; } else { mr[j] = m[i]; j++; } } //--------------- /* compute c+ml h+mr */ for (i = 0; i < COLS512; i++) { inP[i] = c[i] ^ ml[i]; z[i] = h[i]^mr[i]; } /* compute Q(h+mr) */ RND512Q(z,y,U64BIG(0x0000000000000000ull)); RND512Q(y,z,U64BIG(0x0000000000000001ull)); RND512Q(z,y,U64BIG(0x0000000000000002ull)); RND512Q(y,z,U64BIG(0x0000000000000003ull)); RND512Q(z,y,U64BIG(0x0000000000000004ull)); RND512Q(y,z,U64BIG(0x0000000000000005ull)); RND512Q(z,y,U64BIG(0x0000000000000006ull)); RND512Q(y,z,U64BIG(0x0000000000000007ull)); RND512Q(z,y,U64BIG(0x0000000000000008ull)); RND512Q(y,outQ,U64BIG(0x0000000000000009ull)); /* compute P(c+ml) */ RND512P(inP,y,U64BIG(0x0000000000000000ull)); RND512P(y,z, U64BIG(0x0100000000000000ull)); RND512P(z,y, U64BIG(0x0200000000000000ull)); RND512P(y,z, U64BIG(0x0300000000000000ull)); RND512P(z,y, U64BIG(0x0400000000000000ull)); RND512P(y,z, U64BIG(0x0500000000000000ull)); RND512P(z,y, U64BIG(0x0600000000000000ull)); RND512P(y,z, U64BIG(0x0700000000000000ull)); RND512P(z,y, U64BIG(0x0800000000000000ull)); RND512P(y,inP, U64BIG(0x0900000000000000ull)); //ADDED by GURPREET /* compute P(c+ml) + Q(h+mr) */ for (i = 0; i < COLS512; i++) { inP[i] = inP[i]^outQ[i]; } /* compute P(P(h+ml) + Q(h+mr)) */ RND512P(inP,z,U64BIG(0x0000000000000000ull)); RND512P(z,y, U64BIG(0x0100000000000000ull)); RND512P(y,z, U64BIG(0x0200000000000000ull)); RND512P(z,y, U64BIG(0x0300000000000000ull)); RND512P(y,z, U64BIG(0x0400000000000000ull)); RND512P(z,y, U64BIG(0x0500000000000000ull)); RND512P(y,z, U64BIG(0x0600000000000000ull)); RND512P(z,y, U64BIG(0x0700000000000000ull)); RND512P(y,z, U64BIG(0x0800000000000000ull)); RND512P(z,inP, U64BIG(0x0900000000000000ull)); /* compute P(P(h+ml) + Q(h+mr)) + Q(h+mr) + h */ #pragma vector aligned for (i = 0; i < COLS512; i++) { h[i] ^= inP[i] ^ outQ[i]; } }