inline void Hash( hash_context &c, double d ) { union { double doublePart; unsigned long long intPart; } value; value.doublePart = d; const unsigned long long i = value.intPart; unsigned char syncBuffer[8] = { i & 0xFF, (i >> 8) & 0xFF, (i >> 16) & 0xFF, (i >> 24) & 0xFF, (i >> 32) & 0xFF, (i >> 40) & 0xFF, (i >> 48) & 0xFF, (i >> 56) & 0xFF, }; hash_process( &c, (unsigned char *)syncBuffer, 8 ); }
void HashData( char *_data, char *_result ) { hash_context c; hash_initial(&c); hash_process(&c, (unsigned char *) _data, strlen(_data)); uint32 hash[5]; hash_final(&c, hash); sprintf(_result, "hsh%04x%04x%04x%04x%04x", hash[0], hash[1], hash[2], hash[3], hash[4]); }
inline void Hash( hash_context &c, unsigned i ) { unsigned char syncBuffer[4] = { i & 0xFF, (i >> 8) & 0xFF, (i >> 16) & 0xFF, (i >> 24) & 0xFF }; hash_process( &c, (unsigned char *)syncBuffer, 4 ); }
void HashData( char *_data, int _hashToken, char *_result ) { hash_context c; hash_initial(&c); char fullString[512]; sprintf( fullString, "%s-%d", _data, _hashToken ); hash_process(&c, (unsigned char *) fullString, strlen(fullString)); uint32 hash[5]; hash_final(&c, hash); sprintf(_result, "hsh%04x%04x%04x%04x%04x", hash[0], hash[1], hash[2], hash[3], hash[4]); }
void cryptonight_hash_ctx_aes_ni(void* output, const void* input, size_t len, struct cryptonight_ctx* ctx) { hash_process(&ctx->state.hs, (const uint8_t*) input, len); ctx->aes_ctx = (oaes_ctx*) oaes_alloc(); size_t i, j; memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); oaes_key_import_data(ctx->aes_ctx, ctx->state.hs.b, AES_KEY_SIZE); for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) { fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 0], ctx->aes_ctx->key->exp_data); fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 1], ctx->aes_ctx->key->exp_data); fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 2], ctx->aes_ctx->key->exp_data); fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 3], ctx->aes_ctx->key->exp_data); fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 4], ctx->aes_ctx->key->exp_data); fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 5], ctx->aes_ctx->key->exp_data); fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 6], ctx->aes_ctx->key->exp_data); fast_aesb_pseudo_round_mut(&ctx->text[AES_BLOCK_SIZE * 7], ctx->aes_ctx->key->exp_data); memcpy(&ctx->long_state[i], ctx->text, INIT_SIZE_BYTE); } xor_blocks_dst(&ctx->state.k[0], &ctx->state.k[32], ctx->a); xor_blocks_dst(&ctx->state.k[16], &ctx->state.k[48], ctx->b); for (i = 0; likely(i < ITER / 4); ++i) { /* Dependency chain: address -> read value ------+ * written value <-+ hard function (AES or MUL) <+ * next address <-+ */ /* Iteration 1 */ j = e2i(ctx->a); fast_aesb_single_round(&ctx->long_state[j], ctx->c, ctx->a); xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j]); /* Iteration 2 */ mul_sum_xor_dst(ctx->c, ctx->a, &ctx->long_state[e2i(ctx->c)]); /* Iteration 3 */ j = e2i(ctx->a); fast_aesb_single_round(&ctx->long_state[j], ctx->b, ctx->a); xor_blocks_dst(ctx->b, ctx->c, &ctx->long_state[j]); /* Iteration 4 */ mul_sum_xor_dst(ctx->b, ctx->a, &ctx->long_state[e2i(ctx->b)]); } memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE); for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) { xor_blocks(&ctx->text[0 * AES_BLOCK_SIZE], &ctx->long_state[i + 0 * AES_BLOCK_SIZE]); fast_aesb_pseudo_round_mut(&ctx->text[0 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); xor_blocks(&ctx->text[1 * AES_BLOCK_SIZE], &ctx->long_state[i + 1 * AES_BLOCK_SIZE]); fast_aesb_pseudo_round_mut(&ctx->text[1 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); xor_blocks(&ctx->text[2 * AES_BLOCK_SIZE], &ctx->long_state[i + 2 * AES_BLOCK_SIZE]); fast_aesb_pseudo_round_mut(&ctx->text[2 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); xor_blocks(&ctx->text[3 * AES_BLOCK_SIZE], &ctx->long_state[i + 3 * AES_BLOCK_SIZE]); fast_aesb_pseudo_round_mut(&ctx->text[3 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); xor_blocks(&ctx->text[4 * AES_BLOCK_SIZE], &ctx->long_state[i + 4 * AES_BLOCK_SIZE]); fast_aesb_pseudo_round_mut(&ctx->text[4 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); xor_blocks(&ctx->text[5 * AES_BLOCK_SIZE], &ctx->long_state[i + 5 * AES_BLOCK_SIZE]); fast_aesb_pseudo_round_mut(&ctx->text[5 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); xor_blocks(&ctx->text[6 * AES_BLOCK_SIZE], &ctx->long_state[i + 6 * AES_BLOCK_SIZE]); fast_aesb_pseudo_round_mut(&ctx->text[6 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); xor_blocks(&ctx->text[7 * AES_BLOCK_SIZE], &ctx->long_state[i + 7 * AES_BLOCK_SIZE]); fast_aesb_pseudo_round_mut(&ctx->text[7 * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); } memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE); hash_permutation(&ctx->state.hs); /*memcpy(hash, &state, 32);*/ extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output); oaes_free((OAES_CTX **) &ctx->aes_ctx); }
void cryptonight_hash(const char* input, char* output, uint32_t len) { uint8_t long_state[MEMORY]; union cn_slow_hash_state state; uint8_t text[INIT_SIZE_BYTE]; uint8_t a[AES_BLOCK_SIZE]; uint8_t b[AES_BLOCK_SIZE]; uint8_t c[AES_BLOCK_SIZE]; uint8_t d[AES_BLOCK_SIZE]; size_t i, j; uint8_t aes_key[AES_KEY_SIZE]; OAES_CTX* aes_ctx; hash_process(&state.hs, (const uint8_t*) input, len); memcpy(text, state.init, INIT_SIZE_BYTE); memcpy(aes_key, state.hs.b, AES_KEY_SIZE); aes_ctx = oaes_alloc(); oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE); for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { for (j = 0; j < INIT_SIZE_BLK; j++) { oaes_pseudo_encrypt_ecb(aes_ctx, &text[AES_BLOCK_SIZE * j]); } memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); } for (i = 0; i < 16; i++) { a[i] = state.k[i] ^ state.k[32 + i]; b[i] = state.k[16 + i] ^ state.k[48 + i]; } for (i = 0; i < ITER / 2; i++) { /* Dependency chain: address -> read value ------+ * written value <-+ hard function (AES or MUL) <+ * next address <-+ */ /* Iteration 1 */ j = e2i(a, MEMORY / AES_BLOCK_SIZE); copy_block(c, &long_state[j * AES_BLOCK_SIZE]); oaes_encryption_round(a, c); xor_blocks(b, c); swap_blocks(b, c); copy_block(&long_state[j * AES_BLOCK_SIZE], c); assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); swap_blocks(a, b); /* Iteration 2 */ j = e2i(a, MEMORY / AES_BLOCK_SIZE); copy_block(c, &long_state[j * AES_BLOCK_SIZE]); mul(a, c, d); sum_half_blocks(b, d); swap_blocks(b, c); xor_blocks(b, c); copy_block(&long_state[j * AES_BLOCK_SIZE], c); swap_blocks(a, b); } memcpy(text, state.init, INIT_SIZE_BYTE); oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE); for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { for (j = 0; j < INIT_SIZE_BLK; j++) { xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); oaes_pseudo_encrypt_ecb(aes_ctx, &text[j * AES_BLOCK_SIZE]); } } memcpy(state.init, text, INIT_SIZE_BYTE); hash_permutation(&state.hs); /*memcpy(hash, &state, 32);*/ extra_hashes[state.hs.b[0] & 3](&state, 200, output); oaes_free(&aes_ctx); }
void cn_fast_hash(const void *data, size_t length, char *hash) { union hash_state state; hash_process(&state, data, length); memcpy(hash, &state, HASH_SIZE); }
void CryptData::SetCryptKeys(char *Password,unsigned char *Salt,bool Encrypt,bool OldOnly) { if (*Password==0) return; if (OldOnly) { #ifndef SFX_MODULE if (CRCTab[1]==0) InitCRC(); unsigned char Psw[MAXPASSWORD]; SetOldKeys(Password); Key[0]=0xD3A3B879L; Key[1]=0x3F6D12F7L; Key[2]=0x7515A235L; Key[3]=0xA4E7F123L; memset(Psw,0,sizeof(Psw)); #if defined(_WIN_32) && !defined(GUI) CharToOemBuff(Password,(char*)Psw,strlen(Password)); #else strncpy((char *)Psw,Password,MAXPASSWORD-1); #endif int PswLength=strlen(Password); memcpy(SubstTable,InitSubstTable,sizeof(SubstTable)); for (int J=0;J<256;J++) for (int I=0;I<PswLength;I+=2) { unsigned int N1=(unsigned char)CRCTab[(Psw[I]-J)&0xff]; unsigned int N2=(unsigned char)CRCTab[(Psw[I+1]+J)&0xff]; for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++) Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xff]); } for (int I=0;I<PswLength;I+=16) EncryptBlock20(&Psw[I]); #endif return; } bool Cached=false; for (int I=0;I<sizeof(Cache)/sizeof(Cache[0]);I++) if (strcmp(Cache[I].Password,Password)==0 && (Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL && Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0)) { memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey)); memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit)); Cached=true; break; } if (!Cached) { wchar PswW[MAXPASSWORD]; CharToWide(Password,PswW,MAXPASSWORD-1); PswW[MAXPASSWORD-1]=0; unsigned char RawPsw[2*MAXPASSWORD+SALT_SIZE]; WideToRaw(PswW,RawPsw); int RawLength=2*strlenw(PswW); if (Salt!=NULL) { memcpy(RawPsw+RawLength,Salt,SALT_SIZE); RawLength+=SALT_SIZE; } hash_context c; hash_initial(&c); const int HashRounds=0x40000; for (int I=0;I<HashRounds;I++) { hash_process( &c, RawPsw, RawLength); unsigned char PswNum[3]; PswNum[0]=(unsigned char)I; PswNum[1]=(unsigned char)(I>>8); PswNum[2]=(unsigned char)(I>>16); hash_process( &c, PswNum, 3); if (I%(HashRounds/16)==0) { hash_context tempc=c; uint32 digest[5]; hash_final( &tempc, digest); AESInit[I/(HashRounds/16)]=(unsigned char)digest[4]; } } uint32 digest[5]; hash_final( &c, digest); for (int I=0;I<4;I++) for (int J=0;J<4;J++) AESKey[I*4+J]=(unsigned char)(digest[I]>>(J*8)); strcpy(Cache[CachePos].Password,Password); if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true) memcpy(Cache[CachePos].Salt,Salt,SALT_SIZE); memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey)); memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit)); CachePos=(CachePos+1)%(sizeof(Cache)/sizeof(Cache[0])); }
void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt) { byte AESKey[16],AESInit[16]; bool Cached=false; for (uint I=0;I<ASIZE(Cache);I++) if (Cache[I].Password==*Password && ((Salt==NULL && !Cache[I].SaltPresent) || (Salt!=NULL && Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SIZE_SALT30)==0))) { memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey)); memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit)); Cached=true; break; } if (!Cached) { byte RawPsw[2*MAXPASSWORD+SIZE_SALT30]; WideToRaw(PwdW,RawPsw,ASIZE(RawPsw)); size_t RawLength=2*unrar_wcslen(PwdW); if (Salt!=NULL) { memcpy(RawPsw+RawLength,Salt,SIZE_SALT30); RawLength+=SIZE_SALT30; } hash_context c; hash_initial(&c); const int HashRounds=0x40000; for (int I=0;I<HashRounds;I++) { hash_process( &c, RawPsw, RawLength, false); byte PswNum[3]; PswNum[0]=(byte)I; PswNum[1]=(byte)(I>>8); PswNum[2]=(byte)(I>>16); hash_process( &c, PswNum, 3, false); if (I%(HashRounds/16)==0) { hash_context tempc=c; uint32 digest[5]; hash_final( &tempc, digest, false); AESInit[I/(HashRounds/16)]=(byte)digest[4]; } } uint32 digest[5]; hash_final( &c, digest, false); for (int I=0;I<4;I++) for (int J=0;J<4;J++) AESKey[I*4+J]=(byte)(digest[I]>>(J*8)); Cache[CachePos].Password=*Password; if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true) memcpy(Cache[CachePos].Salt,Salt,SIZE_SALT30); memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey)); memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit)); CachePos=(CachePos+1)%ASIZE(Cache); cleandata(RawPsw,sizeof(RawPsw)); }
void CryptData::SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash) { if (*Password==0) return; if (OldOnly) { #ifndef SFX_MODULE if (CRCTab[1]==0) InitCRC(); char Psw[MAXPASSWORD]; memset(Psw,0,sizeof(Psw)); // We need to use ASCII password for older encryption algorithms. WideToChar(Password,Psw,ASIZE(Psw)); Psw[ASIZE(Psw)-1]=0; size_t PswLength=strlen(Psw); SetOldKeys(Psw); Key[0]=0xD3A3B879L; Key[1]=0x3F6D12F7L; Key[2]=0x7515A235L; Key[3]=0xA4E7F123L; memcpy(SubstTable,InitSubstTable,sizeof(SubstTable)); for (int J=0;J<256;J++) for (size_t I=0;I<PswLength;I+=2) { uint N1=(byte)CRCTab [ (byte(Psw[I]) - J) &0xff]; uint N2=(byte)CRCTab [ (byte(Psw[I+1]) + J) &0xff]; for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++) Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xff]); } for (size_t I=0;I<PswLength;I+=16) EncryptBlock20((byte *)&Psw[I]); #endif return; } bool Cached=false; for (uint I=0;I<ASIZE(Cache);I++) if (wcscmp(Cache[I].Password,Password)==0 && (Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL && Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) && Cache[I].HandsOffHash==HandsOffHash) { memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey)); memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit)); Cached=true; break; } if (!Cached) { byte RawPsw[2*MAXPASSWORD+SALT_SIZE]; WideToRaw(Password,RawPsw); size_t RawLength=2*wcslen(Password); if (Salt!=NULL) { memcpy(RawPsw+RawLength,Salt,SALT_SIZE); RawLength+=SALT_SIZE; } hash_context c; hash_initial(&c); const int HashRounds=0x40000; for (int I=0;I<HashRounds;I++) { hash_process( &c, RawPsw, RawLength, HandsOffHash); byte PswNum[3]; PswNum[0]=(byte)I; PswNum[1]=(byte)(I>>8); PswNum[2]=(byte)(I>>16); hash_process( &c, PswNum, 3, HandsOffHash); if (I%(HashRounds/16)==0) { hash_context tempc=c; uint32 digest[5]; hash_final( &tempc, digest, HandsOffHash); AESInit[I/(HashRounds/16)]=(byte)digest[4]; } } uint32 digest[5]; hash_final( &c, digest, HandsOffHash); for (int I=0;I<4;I++) for (int J=0;J<4;J++) AESKey[I*4+J]=(byte)(digest[I]>>(J*8)); wcscpy(Cache[CachePos].Password,Password); if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true) memcpy(Cache[CachePos].Salt,Salt,SALT_SIZE); Cache[CachePos].HandsOffHash=HandsOffHash; memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey)); memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit)); CachePos=(CachePos+1)%(sizeof(Cache)/sizeof(Cache[0])); }
void cryptonight_fast_hash(const char* input, char* output, uint32_t len) { union hash_state state; hash_process(&state, (const uint8_t*) input, len); memcpy(output, &state, HASH_SIZE); }
void cryptonight_hash(const char* input, char* output, uint32_t len, int variant, uint64_t height) { struct cryptonight_ctx *ctx = alloca(sizeof(struct cryptonight_ctx)); hash_process(&ctx->state.hs, (const uint8_t*) input, len); memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); memcpy(ctx->aes_key, ctx->state.hs.b, AES_KEY_SIZE); ctx->aes_ctx = (oaes_ctx*) oaes_alloc(); size_t i, j; VARIANT1_INIT(); VARIANT2_INIT(ctx->b, ctx->state); VARIANT4_RANDOM_MATH_INIT(ctx->state); oaes_key_import_data(ctx->aes_ctx, ctx->aes_key, AES_KEY_SIZE); for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { for (j = 0; j < INIT_SIZE_BLK; j++) { aesb_pseudo_round(&ctx->text[AES_BLOCK_SIZE * j], &ctx->text[AES_BLOCK_SIZE * j], ctx->aes_ctx->key->exp_data); } memcpy(&ctx->long_state[i * INIT_SIZE_BYTE], ctx->text, INIT_SIZE_BYTE); } for (i = 0; i < 16; i++) { ctx->a[i] = ctx->state.k[i] ^ ctx->state.k[32 + i]; ctx->b[i] = ctx->state.k[16 + i] ^ ctx->state.k[48 + i]; } for (i = 0; i < ITER / 2; i++) { /* Dependency chain: address -> read value ------+ * written value <-+ hard function (AES or MUL) <+ * next address <-+ */ /* Iteration 1 */ j = e2i(ctx->a); aesb_single_round(&ctx->long_state[j * AES_BLOCK_SIZE], ctx->c, ctx->a); VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b, ctx->c); xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j * AES_BLOCK_SIZE]); VARIANT1_1((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]); /* Iteration 2 */ j = e2i(ctx->c); uint64_t* dst = (uint64_t*)&ctx->long_state[j * AES_BLOCK_SIZE]; uint64_t t[2]; t[0] = dst[0]; t[1] = dst[1]; VARIANT2_INTEGER_MATH(t, ctx->c); copy_block(ctx->a1, ctx->a); VARIANT4_RANDOM_MATH(ctx->a, t, r, ctx->b, ctx->b + AES_BLOCK_SIZE); uint64_t hi; uint64_t lo = mul128(((uint64_t*)ctx->c)[0], t[0], &hi); VARIANT2_2(); VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a1, ctx->b, ctx->c); ((uint64_t*)ctx->a)[0] += hi; ((uint64_t*)ctx->a)[1] += lo; dst[0] = ((uint64_t*)ctx->a)[0]; dst[1] = ((uint64_t*)ctx->a)[1]; ((uint64_t*)ctx->a)[0] ^= t[0]; ((uint64_t*)ctx->a)[1] ^= t[1]; VARIANT1_2((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]); copy_block(ctx->b + AES_BLOCK_SIZE, ctx->b); copy_block(ctx->b, ctx->c); } memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE); for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { for (j = 0; j < INIT_SIZE_BLK; j++) { xor_blocks(&ctx->text[j * AES_BLOCK_SIZE], &ctx->long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); aesb_pseudo_round(&ctx->text[j * AES_BLOCK_SIZE], &ctx->text[j * AES_BLOCK_SIZE], ctx->aes_ctx->key->exp_data); } } memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE); hash_permutation(&ctx->state.hs); /*memcpy(hash, &state, 32);*/ extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output); oaes_free((OAES_CTX **) &ctx->aes_ctx); }
void cn_slow_hash(const void *data, size_t length, char *hash) { uint8_t long_state[MEMORY]; union cn_slow_hash_state state; uint8_t text[INIT_SIZE_BYTE]; uint8_t a[AES_BLOCK_SIZE]; uint8_t b[AES_BLOCK_SIZE]; uint8_t c[AES_BLOCK_SIZE]; uint8_t d[AES_BLOCK_SIZE]; size_t i, j; uint8_t aes_key[AES_KEY_SIZE]; oaes_ctx *aes_ctx; hash_process(&state.hs, data, length); memcpy(text, state.init, INIT_SIZE_BYTE); memcpy(aes_key, state.hs.b, AES_KEY_SIZE); aes_ctx = (oaes_ctx *) oaes_alloc(); oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE); for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { for (j = 0; j < INIT_SIZE_BLK; j++) { aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); } memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE); } for (i = 0; i < 16; i++) { a[i] = state.k[ i] ^ state.k[32 + i]; b[i] = state.k[16 + i] ^ state.k[48 + i]; } for (i = 0; i < ITER / 2; i++) { /* Dependency chain: address -> read value ------+ * written value <-+ hard function (AES or MUL) <+ * next address <-+ */ /* Iteration 1 */ j = e2i(a, MEMORY / AES_BLOCK_SIZE); copy_block(c, &long_state[j * AES_BLOCK_SIZE]); aesb_single_round(c, c, a); xor_blocks(b, c); swap_blocks(b, c); copy_block(&long_state[j * AES_BLOCK_SIZE], c); //assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); swap_blocks(a, b); /* Iteration 2 */ j = e2i(a, MEMORY / AES_BLOCK_SIZE); copy_block(c, &long_state[j * AES_BLOCK_SIZE]); mul(a, c, d); sum_half_blocks(b, d); swap_blocks(b, c); xor_blocks(b, c); copy_block(&long_state[j * AES_BLOCK_SIZE], c); //assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE)); swap_blocks(a, b); } memcpy(text, state.init, INIT_SIZE_BYTE); oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE); for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) { for (j = 0; j < INIT_SIZE_BLK; j++) { xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]); aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data); } } memcpy(state.init, text, INIT_SIZE_BYTE); hash_permutation(&state.hs); extra_hashes[state.hs.b[0] & 3](&state, 200, hash); oaes_free((OAES_CTX **) &aes_ctx); }