int crypto_hash( unsigned char *out, const unsigned char *in, unsigned long long inlen ) { tKeccakLane state[5 * 5]; #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #define temp out #else unsigned char temp[cKeccakR_SizeInBytes]; #endif memset( state, 0, sizeof(state) ); for ( /* empty */; inlen >= cKeccakR_SizeInBytes; inlen -= cKeccakR_SizeInBytes, in += cKeccakR_SizeInBytes ) { KeccakF( state, (const tKeccakLane*)in, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); } // padding memcpy( temp, in, (size_t)inlen ); temp[inlen++] = 1; memset( temp+inlen, 0, cKeccakR_SizeInBytes - (size_t)inlen ); temp[cKeccakR_SizeInBytes-1] |= 0x80; KeccakF( state, (const tKeccakLane*)temp, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); memcpy( out, state, crypto_hash_BYTES ); #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #undef temp #endif return ( 0 ); }
int crypto_hash( unsigned char *out, const unsigned char *in, unsigned long long inlen ) { #if 1 tSmallUInt i; tSmallUInt len; unsigned char * pState; tKeccakLane state[5 * 5]; memset( state, 0, sizeof(state) ); /* Full blocks */ for ( /* empty */; inlen >= cKeccakR_SizeInBytes; inlen -= cKeccakR_SizeInBytes ) { in = xorLanes( state, in, cKeccakR_SizeInBytes / 8 ); KeccakF( state ); } /* Last uncomplete block */ len = (tSmallUInt)inlen; xorBytes( state, in, len ); pState = (unsigned char*)state + len; /* Padding */ for ( i = 0; i < 4; /* empty */ ) { *(pState++) ^= pgm_read_byte(&KeccakPadding[i++]); if ( ++len == cKeccakR_SizeInBytes ) { KeccakF( state ); pState = (unsigned char*)state; len = 0; } } if ( len != 0 ) { KeccakF( state ); } memcpy( out, state, crypto_hash_BYTES ); return ( 0 ); #else hashState state; Init( &state ); Update( &state, in, inlen * 8 ); return (Final( &state, out, crypto_hash_BYTES ) ); #endif }
HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) { tSmallUInt trailingBits; tSmallUInt len; if ( (state->bytesInQueue == 0xFF) || (state->trailingBitsInQueue != 0) ) { /* Final() already called or bits already in queue not modulo 8. */ return ( FAIL ); } trailingBits = (unsigned char)databitlen & 7; databitlen >>= 3; /* becomes byte length */ /* If already data in queue, continue queuing first */ if ( (state->bytesInQueue != 0) && (databitlen != 0) ) { len = cKeccakR_SizeInBytes - state->bytesInQueue; if ( databitlen < len ) { len = (unsigned char)databitlen; } data = xorBytes( state->state + state->bytesInQueue, data, len ); databitlen -= len; if ( (state->bytesInQueue += len) == cKeccakR_SizeInBytes ) { KeccakF( (tKeccakLane *)state->state ); state->bytesInQueue = 0; } } /* Absorb complete blocks */ for ( /* */; databitlen >= cKeccakR_SizeInBytes; databitlen -= cKeccakR_SizeInBytes ) { data = xorLanes( state->state, data, cKeccakR_SizeInBytes / 8 ); KeccakF( (tKeccakLane *)state->state ); } /* Queue remaining data bytes */ if ( (unsigned char)databitlen != 0 ) { data = xorBytes( state->state, data, (unsigned char)databitlen ); state->bytesInQueue = (unsigned char)databitlen; } /* Queue eventual remaining data bits plus add first padding bit */ if ( trailingBits != 0 ) { state->trailingBitsInQueue = 1; state->state[state->bytesInQueue++] ^= (*data >> (8 - trailingBits)) | (1 << trailingBits); }
int crypto_hash( unsigned char *out, const unsigned char *in, unsigned long long inlen ) { tKeccakLane state[5 * 5]; #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #define temp out #else unsigned char temp[cKeccakR_SizeInBytes]; #endif memset( state, 0, sizeof(state) ); for ( /* empty */; inlen >= cKeccakR_SizeInBytes; inlen -= cKeccakR_SizeInBytes, in += cKeccakR_SizeInBytes ) { KeccakF( state, (const tKeccakLane*)in, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); } /* Last data and padding */ memcpy( temp, in, (size_t)inlen ); temp[inlen++] = 1; memset( temp+inlen, 0, cKeccakR_SizeInBytes - (size_t)inlen ); temp[cKeccakR_SizeInBytes-1] |= 0x80; KeccakF( state, (const tKeccakLane*)temp, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) || (cKeccakB == 200) memcpy( out, state, crypto_hash_BYTES ); #else for ( i = 0; i < (crypto_hash_BYTES / sizeof(tKeccakLane)); ++i ) { tSmallUInt j; tKeccakLane t; t = state[i]; for ( j = 0; j < sizeof(tKeccakLane); ++j ) { *(out++) = (unsigned char)t; t >>= 8; } } #endif #if (crypto_hash_BYTES >= cKeccakR_SizeInBytes) #undef temp #endif return ( 0 ); }
HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) { if ( (state->bitsInQueue < 0) || ((state->bitsInQueue % 8) != 0) ) { /* Final() already called or bits already in queue not modulo 8. */ return ( FAIL ); } /* If already data in queue, continue queuing first */ for ( /* empty */; (databitlen >= 8) && (state->bitsInQueue != 0); databitlen -= 8 ) { state->state[state->bitsInQueue / 8] ^= *(data++); if ( (state->bitsInQueue += 8) == cKeccakR ) { KeccakF( (tKeccakLane *)state->state, 0, 0 ); state->bitsInQueue = 0; } } /* Absorb complete blocks */ for ( /* */; databitlen >= cKeccakR; databitlen -= cKeccakR, data += cKeccakR_SizeInBytes ) { KeccakF( (tKeccakLane *)state->state, (const tKeccakLane *)data, cKeccakR_SizeInBytes / sizeof(tKeccakLane) ); } /* Queue remaining data bytes */ for ( /* empty */; databitlen >=8; databitlen -= 8, state->bitsInQueue += 8 ) { state->state[state->bitsInQueue / 8] ^= *(data++); } /* Queue eventual remaining data bits plus add first padding bit */ if ( databitlen != 0 ) { state->state[state->bitsInQueue / 8] ^= (*data >> (8 - databitlen)); state->bitsInQueue += (int)databitlen; }
// DO NOT MODIFY THE HEADING OF THIS FUNCTION unsigned char* Hash(unsigned char* message, unsigned int length) { //Initialization and padding // Step 1 S[x,y] = 0 unsigned long** S = malloc(5 * sizeof(unsigned long)); //defining the state array S int x; for (x = 0; x < 5; x++) { S[x] = malloc(5 * sizeof(unsigned long)); // Allocating the required memory for S array } //Here I am initializing and assignning the Value 0 to the state array S S[0][0] = 0; S[1][0] = 0; S[2][0] = 0; S[3][0] = 0; S[4][0] = 0; S[0][1] = 0; S[1][1] = 0; S[2][1] = 0; S[3][1] = 0; S[4][1] = 0; S[0][2] = 0; S[1][2] = 0; S[2][2] = 0; S[3][2] = 0; S[4][2] = 0; S[0][3] = 0; S[1][3] = 0; S[2][3] = 0; S[3][3] = 0; S[4][3] = 0; S[0][4] = 0; S[1][4] = 0; S[2][4] = 0; S[3][4] = 0; S[4][4] = 0; /* ------------------------------------------------------------------------------------------------------------------- */ //P = M || 0x01 || 0x00 || … || 0x00 //P = P xor (0x00 || … || 0x00 || 0x80) unsigned int how_many_blocks, padding_length, padding_byte; //Declaring the variables used. how_many_blocks = (length / 128) + 1; // calculating how many blocks are required for the padding length padding_length = how_many_blocks; padding_byte = 128 - (length % 128); // Calculating how many Bytes of _Padding is required unsigned char* padded_msg = malloc(length + padding_byte); memcpy(padded_msg, message, 251); //Copying the message to an array called padded_msg which will be padded in later stages //If there is just one byte to be padded then the last byte will be padded as 0x81 if (padding_byte == 1) { memcpy(padded_msg + length, "\x81", 1); } else { memcpy(padded_msg + length, "\x01", 1); //In other cases, first byte to be padded is 0x01 int i, pbpl; pbpl = (padding_byte + length) - 1; for (i = length + 1; i < pbpl; i++) { memcpy(padded_msg + i, "\x00", 1); //All the other bytes untill last byte will be padded as 0x00 } memcpy(padded_msg + i, "\x80", 1); //Last byte will padded as 0x80 } /*-------------------------------------- Making the P-Blocks of length 128 bytes-------------------------------------------------*/ // Here the padded _msg will be divided into different blocks of 128 bytes each int k = 0; unsigned long** P = malloc(padding_length * sizeof(unsigned long)); //Defining the array P for (x = 0; x < padding_length; x++) { P[x] = malloc(16 * sizeof(unsigned long)); //Allocating required memory to P } for (int i = 0; i < padding_length; i++) { for (int j = 0; j < 16; j++,k+=8) { unsigned char* temp_array = malloc(sizeof(unsigned long)); //a temporary arry for copying memcpy(temp_array, padded_msg + k, 8); //Copying the padded_msg byte by byte memcpy(&P[i][j], temp_array, 8); // In very time temp_array is copied to array P } } /* --------------------------------------------------------------------------------------------------------------------------------*/ // Absorbing phase // forall block Pi in P // S[x,y] = S[x,y] xor Pi[x+5*y], forall (x,y) such that x+5*y < r/w // S = Keccak-f[r+c](S) for (int m = 0; m < padding_length; m++) { for (int x = 0; x < 5; x++) { for (int y = 0; y < 5; y++) { if ((x + (5 * y)) < (R/w)) // Defined R =1024 and w = 64 globally { S[x][y] ^= P[m][x + (5 * y)]; } } } S = KeccakF(S); //In each iteration the function state array S is fed to KeaackF from 1st assignment and //not to KeccakF_bytes function } /* ----------------------------------------------- Squeezing phase ------- ----------------------------------------------------*/ /* Z = Z || S[x,y] */ // Here the array Z is concatenated with S from previous step. unsigned char* Z = malloc(R / 8); int c = 0; for (int a = 0; a < 5; a++) { for (int b = 0; b < 5; b++, c+=8) { if (c < (R / 8)) { memcpy(Z + c, &S[b][a], 8); } } } return Z; }
int main(){ unsigned long** INPUT=malloc(5*sizeof(unsigned long)); int x; for(x=0;x<5;x++){ INPUT[x]=malloc(5*sizeof(unsigned long)); } INPUT[0][0]=0; INPUT[1][0]=0; INPUT[2][0]=0; INPUT[3][0]=0; INPUT[4][0]=0; INPUT[0][1]=0; INPUT[1][1]=0; INPUT[2][1]=0; INPUT[3][1]=0; INPUT[4][1]=0; INPUT[0][2]=0; INPUT[1][2]=0; INPUT[2][2]=0; INPUT[3][2]=0; INPUT[4][2]=0; INPUT[0][3]=0; INPUT[1][3]=0; INPUT[2][3]=0; INPUT[3][3]=0; INPUT[4][3]=0; INPUT[0][4]=0; INPUT[1][4]=0; INPUT[2][4]=0; INPUT[3][4]=0; INPUT[4][4]=0; unsigned long** OUTPUT_REF=malloc(5*sizeof(unsigned long)); for(x=0;x<5;x++){ OUTPUT_REF[x]=malloc(5*sizeof(unsigned long)); } OUTPUT_REF[0][0]=0xF1258F7940E1DDE7; OUTPUT_REF[1][0]=0x84D5CCF933C0478A; OUTPUT_REF[2][0]=0xD598261EA65AA9EE; OUTPUT_REF[3][0]=0xBD1547306F80494D; OUTPUT_REF[4][0]=0x8B284E056253D057; OUTPUT_REF[0][1]=0xFF97A42D7F8E6FD4; OUTPUT_REF[1][1]=0x90FEE5A0A44647C4; OUTPUT_REF[2][1]=0x8C5BDA0CD6192E76; OUTPUT_REF[3][1]=0xAD30A6F71B19059C; OUTPUT_REF[4][1]=0x30935AB7D08FFC64; OUTPUT_REF[0][2]=0xEB5AA93F2317D635; OUTPUT_REF[1][2]=0xA9A6E6260D712103; OUTPUT_REF[2][2]=0x81A57C16DBCF555F; OUTPUT_REF[3][2]=0x43B831CD0347C826; OUTPUT_REF[4][2]=0x01F22F1A11A5569F; OUTPUT_REF[0][3]=0x05E5635A21D9AE61; OUTPUT_REF[1][3]=0x64BEFEF28CC970F2; OUTPUT_REF[2][3]=0x613670957BC46611; OUTPUT_REF[3][3]=0xB87C5A554FD00ECB; OUTPUT_REF[4][3]=0x8C3EE88A1CCF32C8; OUTPUT_REF[0][4]=0x940C7922AE3A2614; OUTPUT_REF[1][4]=0x1841F924A2C509E4; OUTPUT_REF[2][4]=0x16F53526E70465C2; OUTPUT_REF[3][4]=0x75F644E97F30A13B; OUTPUT_REF[4][4]=0xEAF1FF7B5CECA249; unsigned long** OUTPUT=KeccakF(INPUT); //check int y; int count=1; for(x=0;x<5;x++){ for(y=0;y<5;y++){ if(OUTPUT[x][y]!=OUTPUT_REF[x][y]){ count=0; } } } if(count==0){ printf("FAIL\n"); } else{ printf("PASS\n"); } for(x=0;x<5;x++){ free(INPUT[x]); free(OUTPUT[x]); free(OUTPUT_REF[x]); } free(INPUT); free(OUTPUT); free(OUTPUT_REF); return 0; }