/* * SHA-160 * (C) 1999-2008,2011 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include namespace Botan { std::unique_ptr SHA_160::copy_state() const { return std::unique_ptr(new SHA_160(*this)); } namespace SHA1_F { namespace { /* * SHA-160 F1 Function */ inline void F1(uint32_t A, uint32_t& B, uint32_t C, uint32_t D, uint32_t& E, uint32_t msg) { E += (D ^ (B & (C ^ D))) + msg + 0x5A827999 + rotate_left(A, 5); B = rotate_left(B, 30); } /* * SHA-160 F2 Function */ inline void F2(uint32_t A, uint32_t& B, uint32_t C, uint32_t D, uint32_t& E, uint32_t msg) { E += (B ^ C ^ D) + msg + 0x6ED9EBA1 + rotate_left(A, 5); B = rotate_left(B, 30); } /* * SHA-160 F3 Function */ inline void F3(uint32_t A, uint32_t& B, uint32_t C, uint32_t D, uint32_t& E, uint32_t msg) { E += ((B & C) | ((B | C) & D)) + msg + 0x8F1BBCDC + rotate_left(A, 5); B = rotate_left(B, 30); } /* * SHA-160 F4 Function */ inline void F4(uint32_t A, uint32_t& B, uint32_t C, uint32_t D, uint32_t& E, uint32_t msg) { E += (B ^ C ^ D) + msg + 0xCA62C1D6 + rotate_left(A, 5); B = rotate_left(B, 30); } } } /* * SHA-160 Compression Function */ void SHA_160::compress_n(const uint8_t input[], size_t blocks) { using namespace SHA1_F; #if defined(BOTAN_HAS_SHA1_X86_SHA_NI) if(CPUID::has_intel_sha()) { return sha1_compress_x86(m_digest, input, blocks); } #endif #if defined(BOTAN_HAS_SHA1_ARMV8) if(CPUID::has_arm_sha1()) { return sha1_armv8_compress_n(m_digest, input, blocks); } #endif #if defined(BOTAN_HAS_SHA1_SSE2) if(CPUID::has_sse2()) { return sse2_compress_n(m_digest, input, blocks); } #endif uint32_t A = m_digest[0], B = m_digest[1], C = m_digest[2], D = m_digest[3], E = m_digest[4]; m_W.resize(80); for(size_t i = 0; i != blocks; ++i) { load_be(m_W.data(), input, 16); for(size_t j = 16; j != 80; j += 8) { m_W[j ] = rotate_left((m_W[j-3] ^ m_W[j-8] ^ m_W[j-14] ^ m_W[j-16]), 1); m_W[j+1] = rotate_left((m_W[j-2] ^ m_W[j-7] ^ m_W[j-13] ^ m_W[j-15]), 1); m_W[j+2] = rotate_left((m_W[j-1] ^ m_W[j-6] ^ m_W[j-12] ^ m_W[j-14]), 1); m_W[j+3] = rotate_left((m_W[j ] ^ m_W[j-5] ^ m_W[j-11] ^ m_W[j-13]), 1); m_W[j+4] = rotate_left((m_W[j+1] ^ m_W[j-4] ^ m_W[j-10] ^ m_W[j-12]), 1); m_W[j+5] = rotate_left((m_W[j+2] ^ m_W[j-3] ^ m_W[j- 9] ^ m_W[j-11]), 1); m_W[j+6] = rotate_left((m_W[j+3] ^ m_W[j-2] ^ m_W[j- 8] ^ m_W[j-10]), 1); m_W[j+7] = rotate_left((m_W[j+4] ^ m_W[j-1] ^ m_W[j- 7] ^ m_W[j- 9]), 1); } F1(A, B, C, D, E, m_W[ 0]); F1(E, A, B, C, D, m_W[ 1]); F1(D, E, A, B, C, m_W[ 2]); F1(C, D, E, A, B, m_W[ 3]); F1(B, C, D, E, A, m_W[ 4]); F1(A, B, C, D, E, m_W[ 5]); F1(E, A, B, C, D, m_W[ 6]); F1(D, E, A, B, C, m_W[ 7]); F1(C, D, E, A, B, m_W[ 8]); F1(B, C, D, E, A, m_W[ 9]); F1(A, B, C, D, E, m_W[10]); F1(E, A, B, C, D, m_W[11]); F1(D, E, A, B, C, m_W[12]); F1(C, D, E, A, B, m_W[13]); F1(B, C, D, E, A, m_W[14]); F1(A, B, C, D, E, m_W[15]); F1(E, A, B, C, D, m_W[16]); F1(D, E, A, B, C, m_W[17]); F1(C, D, E, A, B, m_W[18]); F1(B, C, D, E, A, m_W[19]); F2(A, B, C, D, E, m_W[20]); F2(E, A, B, C, D, m_W[21]); F2(D, E, A, B, C, m_W[22]); F2(C, D, E, A, B, m_W[23]); F2(B, C, D, E, A, m_W[24]); F2(A, B, C, D, E, m_W[25]); F2(E, A, B, C, D, m_W[26]); F2(D, E, A, B, C, m_W[27]); F2(C, D, E, A, B, m_W[28]); F2(B, C, D, E, A, m_W[29]); F2(A, B, C, D, E, m_W[30]); F2(E, A, B, C, D, m_W[31]); F2(D, E, A, B, C, m_W[32]); F2(C, D, E, A, B, m_W[33]); F2(B, C, D, E, A, m_W[34]); F2(A, B, C, D, E, m_W[35]); F2(E, A, B, C, D, m_W[36]); F2(D, E, A, B, C, m_W[37]); F2(C, D, E, A, B, m_W[38]); F2(B, C, D, E, A, m_W[39]); F3(A, B, C, D, E, m_W[40]); F3(E, A, B, C, D, m_W[41]); F3(D, E, A, B, C, m_W[42]); F3(C, D, E, A, B, m_W[43]); F3(B, C, D, E, A, m_W[44]); F3(A, B, C, D, E, m_W[45]); F3(E, A, B, C, D, m_W[46]); F3(D, E, A, B, C, m_W[47]); F3(C, D, E, A, B, m_W[48]); F3(B, C, D, E, A, m_W[49]); F3(A, B, C, D, E, m_W[50]); F3(E, A, B, C, D, m_W[51]); F3(D, E, A, B, C, m_W[52]); F3(C, D, E, A, B, m_W[53]); F3(B, C, D, E, A, m_W[54]); F3(A, B, C, D, E, m_W[55]); F3(E, A, B, C, D, m_W[56]); F3(D, E, A, B, C, m_W[57]); F3(C, D, E, A, B, m_W[58]); F3(B, C, D, E, A, m_W[59]); F4(A, B, C, D, E, m_W[60]); F4(E, A, B, C, D, m_W[61]); F4(D, E, A, B, C, m_W[62]); F4(C, D, E, A, B, m_W[63]); F4(B, C, D, E, A, m_W[64]); F4(A, B, C, D, E, m_W[65]); F4(E, A, B, C, D, m_W[66]); F4(D, E, A, B, C, m_W[67]); F4(C, D, E, A, B, m_W[68]); F4(B, C, D, E, A, m_W[69]); F4(A, B, C, D, E, m_W[70]); F4(E, A, B, C, D, m_W[71]); F4(D, E, A, B, C, m_W[72]); F4(C, D, E, A, B, m_W[73]); F4(B, C, D, E, A, m_W[74]); F4(A, B, C, D, E, m_W[75]); F4(E, A, B, C, D, m_W[76]); F4(D, E, A, B, C, m_W[77]); F4(C, D, E, A, B, m_W[78]); F4(B, C, D, E, A, m_W[79]); A = (m_digest[0] += A); B = (m_digest[1] += B); C = (m_digest[2] += C); D = (m_digest[3] += D); E = (m_digest[4] += E); input += hash_block_size(); } } /* * Copy out the digest */ void SHA_160::copy_out(uint8_t output[]) { copy_out_vec_be(output, output_length(), m_digest); } /* * Clear memory of sensitive data */ void SHA_160::clear() { MDx_HashFunction::clear(); zeroise(m_W); m_digest[0] = 0x67452301; m_digest[1] = 0xEFCDAB89; m_digest[2] = 0x98BADCFE; m_digest[3] = 0x10325476; m_digest[4] = 0xC3D2E1F0; } }