void _stdcall sha512_hmac(const void *k, size_t k_len, const void *d, size_t d_len, char *out) { sha512_ctx ctx; unsigned char buf[SHA512_BLOCK_SIZE]; unsigned char hval[SHA512_DIGEST_SIZE]; unsigned long i; // zero key buffer memset(buf, 0, sizeof(buf)); // compress hmac key if (k_len > SHA512_BLOCK_SIZE) { sha512_init(&ctx); sha512_hash(&ctx, (const unsigned char*)k, k_len); sha512_done(&ctx, buf); } else { memcpy(buf, k, k_len); } // create the hash initial vector for (i = 0; i < (SHA512_BLOCK_SIZE / 4); i++) { ((unsigned long*)buf)[i] ^= 0x36363636; } // hash key and data sha512_init(&ctx); sha512_hash(&ctx, buf, SHA512_BLOCK_SIZE); sha512_hash(&ctx, (const unsigned char*)d, d_len); sha512_done(&ctx, hval); // create the second HMAC vector for (i = 0; i < (SHA512_BLOCK_SIZE / 4); i++) { ((unsigned long*)buf)[i] ^= 0x6A6A6A6A; } // calculate "outer" hash sha512_init(&ctx); sha512_hash(&ctx, buf, SHA512_BLOCK_SIZE); sha512_hash(&ctx, hval, SHA512_DIGEST_SIZE); sha512_done(&ctx, (unsigned char*)out); // test buffers size alignment at compile-time static_assert( !(sizeof(buf) % sizeof(unsigned long)), "sizeof must be 4 byte aligned"); static_assert( !(sizeof(hval) % sizeof(unsigned long)), "sizeof must be 4 byte aligned"); static_assert( !(sizeof(ctx) % sizeof(unsigned long)), "sizeof must be 4 byte aligned"); // prevent leaks __stosd((unsigned long*)&buf, 0, (sizeof(buf) / sizeof(unsigned long))); __stosd((unsigned long*)&hval, 0, (sizeof(hval) / sizeof(unsigned long))); __stosd((unsigned long*)&ctx, 0, (sizeof(ctx) / sizeof(unsigned long))); }
// __asm__ blocks are only checked for inline functions that end up being // emitted, so call functions with __asm__ blocks to make sure their inline // assembly parses. void f() { __movsb(0, 0, 0); __movsd(0, 0, 0); __movsw(0, 0, 0); __stosd(0, 0, 0); __stosw(0, 0, 0); #ifdef _M_X64 __movsq(0, 0, 0); __stosq(0, 0, 0); #endif int info[4]; __cpuid(info, 0); __cpuidex(info, 0, 0); _xgetbv(0); __halt(); __nop(); __readmsr(0); // FIXME: Call these in 64-bit too once the intrinsics have been fixed to // work there, PR19301 #ifndef _M_X64 __readcr3(); __writecr3(0); #endif #ifdef _M_ARM __dmb(_ARM_BARRIER_ISHST); #endif }
void _stdcall sha512_pkcs5_2(int i_count, const void *pwd, size_t pwd_len, const char *salt, size_t salt_len, char *dk, size_t dklen) { unsigned char buff[128]; unsigned char blk[SHA512_DIGEST_SIZE]; unsigned char hmac[SHA512_DIGEST_SIZE]; unsigned long block = 1; size_t c_len; int j, i; while (dklen != 0) { // first interation memcpy(buff, salt, salt_len); ((unsigned long*)(buff + salt_len))[0] = _byteswap_ulong(block); sha512_hmac(pwd, pwd_len, buff, salt_len + 4, (char*)hmac); memcpy(blk, hmac, SHA512_DIGEST_SIZE); // next interations for (i = 1; i < i_count; i++) { sha512_hmac(pwd, pwd_len, hmac, SHA512_DIGEST_SIZE, (char*)hmac); for (j = 0; j < (SHA512_DIGEST_SIZE / 4); j++) { ((unsigned long*)blk)[j] ^= ((unsigned long*)hmac)[j]; } } memcpy(dk, blk, (c_len = dklen < SHA512_DIGEST_SIZE ? dklen : SHA512_DIGEST_SIZE)); dk += c_len; dklen -= c_len; block++; } // test buffers size alignment at compile-time static_assert( !(sizeof(buff) % sizeof(unsigned long)), "sizeof must be 4 byte aligned"); static_assert( !(sizeof(blk) % sizeof(unsigned long)), "sizeof must be 4 byte aligned"); static_assert( !(sizeof(hmac) % sizeof(unsigned long)), "sizeof must be 4 byte aligned"); // prevent leaks __stosd((unsigned long*)&buff, 0, (sizeof(buff) / sizeof(unsigned long))); __stosd((unsigned long*)&blk, 0, (sizeof(blk) / sizeof(unsigned long))); __stosd((unsigned long*)&hmac, 0, (sizeof(hmac) / sizeof(unsigned long))); }
void Clear_REF(void* dest, size_t size) { __stosd(reinterpret_cast<unsigned long*>(dest), 0, size/4); }
void memset_d(unsigned long* pBuffer, unsigned long value, std::size_t count) { __stosd(pBuffer, value, count); }