1 /** 2 * SHA-160 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.hash.sha160; 12 13 import botan.constants; 14 static if (BOTAN_HAS_SHA1): 15 16 import botan.hash.mdx_hash; 17 18 import botan.utils.loadstor; 19 import botan.utils.rotate; 20 import botan.utils.types; 21 import botan.utils.mem_ops; 22 23 /** 24 * NIST's SHA-160 25 */ 26 class SHA160 : MDxHashFunction, HashFunction 27 { 28 public: 29 30 override @property size_t hashBlockSize() const { return super.hashBlockSize(); } 31 override final @property string name() const { return "SHA-160"; } 32 override final @property size_t outputLength() const { return 20; } 33 override HashFunction clone() const { return new SHA160; } 34 35 /* 36 * Clear memory of sensitive data 37 */ 38 override final void clear() 39 { 40 super.clear(); 41 zeroise(m_W); 42 m_digest[0] = 0x67452301; 43 m_digest[1] = 0xEFCDAB89; 44 m_digest[2] = 0x98BADCFE; 45 m_digest[3] = 0x10325476; 46 m_digest[4] = 0xC3D2E1F0; 47 } 48 49 this() 50 { 51 super(64, true, true); 52 m_digest.length = 5; 53 m_W.length = 80; 54 clear(); 55 } 56 protected: 57 /** 58 * Set a custom size for the W array. Normally 80, but some 59 * subclasses need slightly more for best performance/internal 60 * constraints 61 * Params: 62 * W_size = how big to make W 63 */ 64 this(size_t W_size) 65 { 66 super(64, true, true); 67 m_digest.length = 5; 68 m_W.length = W_size; 69 clear(); 70 } 71 72 /* 73 * SHA-160 Compression Function 74 */ 75 override void compressN(const(ubyte)* input, size_t blocks) 76 { 77 uint A = m_digest[0], B = m_digest[1], C = m_digest[2], 78 D = m_digest[3], E = m_digest[4]; 79 80 foreach (size_t i; 0 .. blocks) 81 { 82 loadBigEndian(m_W.ptr, input, 16); 83 84 for (size_t j = 16; j != 80; j += 8) 85 { 86 m_W[j ] = rotateLeft((m_W[j-3] ^ m_W[j-8] ^ m_W[j-14] ^ m_W[j-16]), 1); 87 m_W[j+1] = rotateLeft((m_W[j-2] ^ m_W[j-7] ^ m_W[j-13] ^ m_W[j-15]), 1); 88 m_W[j+2] = rotateLeft((m_W[j-1] ^ m_W[j-6] ^ m_W[j-12] ^ m_W[j-14]), 1); 89 m_W[j+3] = rotateLeft((m_W[j ] ^ m_W[j-5] ^ m_W[j-11] ^ m_W[j-13]), 1); 90 m_W[j+4] = rotateLeft((m_W[j+1] ^ m_W[j-4] ^ m_W[j-10] ^ m_W[j-12]), 1); 91 m_W[j+5] = rotateLeft((m_W[j+2] ^ m_W[j-3] ^ m_W[j- 9] ^ m_W[j-11]), 1); 92 m_W[j+6] = rotateLeft((m_W[j+3] ^ m_W[j-2] ^ m_W[j- 8] ^ m_W[j-10]), 1); 93 m_W[j+7] = rotateLeft((m_W[j+4] ^ m_W[j-1] ^ m_W[j- 7] ^ m_W[j- 9]), 1); 94 } 95 96 F1(A, B, C, D, E, m_W[ 0]); F1(E, A, B, C, D, m_W[ 1]); 97 F1(D, E, A, B, C, m_W[ 2]); F1(C, D, E, A, B, m_W[ 3]); 98 F1(B, C, D, E, A, m_W[ 4]); F1(A, B, C, D, E, m_W[ 5]); 99 F1(E, A, B, C, D, m_W[ 6]); F1(D, E, A, B, C, m_W[ 7]); 100 F1(C, D, E, A, B, m_W[ 8]); F1(B, C, D, E, A, m_W[ 9]); 101 F1(A, B, C, D, E, m_W[10]); F1(E, A, B, C, D, m_W[11]); 102 F1(D, E, A, B, C, m_W[12]); F1(C, D, E, A, B, m_W[13]); 103 F1(B, C, D, E, A, m_W[14]); F1(A, B, C, D, E, m_W[15]); 104 F1(E, A, B, C, D, m_W[16]); F1(D, E, A, B, C, m_W[17]); 105 F1(C, D, E, A, B, m_W[18]); F1(B, C, D, E, A, m_W[19]); 106 107 F2(A, B, C, D, E, m_W[20]); F2(E, A, B, C, D, m_W[21]); 108 F2(D, E, A, B, C, m_W[22]); F2(C, D, E, A, B, m_W[23]); 109 F2(B, C, D, E, A, m_W[24]); F2(A, B, C, D, E, m_W[25]); 110 F2(E, A, B, C, D, m_W[26]); F2(D, E, A, B, C, m_W[27]); 111 F2(C, D, E, A, B, m_W[28]); F2(B, C, D, E, A, m_W[29]); 112 F2(A, B, C, D, E, m_W[30]); F2(E, A, B, C, D, m_W[31]); 113 F2(D, E, A, B, C, m_W[32]); F2(C, D, E, A, B, m_W[33]); 114 F2(B, C, D, E, A, m_W[34]); F2(A, B, C, D, E, m_W[35]); 115 F2(E, A, B, C, D, m_W[36]); F2(D, E, A, B, C, m_W[37]); 116 F2(C, D, E, A, B, m_W[38]); F2(B, C, D, E, A, m_W[39]); 117 118 F3(A, B, C, D, E, m_W[40]); F3(E, A, B, C, D, m_W[41]); 119 F3(D, E, A, B, C, m_W[42]); F3(C, D, E, A, B, m_W[43]); 120 F3(B, C, D, E, A, m_W[44]); F3(A, B, C, D, E, m_W[45]); 121 F3(E, A, B, C, D, m_W[46]); F3(D, E, A, B, C, m_W[47]); 122 F3(C, D, E, A, B, m_W[48]); F3(B, C, D, E, A, m_W[49]); 123 F3(A, B, C, D, E, m_W[50]); F3(E, A, B, C, D, m_W[51]); 124 F3(D, E, A, B, C, m_W[52]); F3(C, D, E, A, B, m_W[53]); 125 F3(B, C, D, E, A, m_W[54]); F3(A, B, C, D, E, m_W[55]); 126 F3(E, A, B, C, D, m_W[56]); F3(D, E, A, B, C, m_W[57]); 127 F3(C, D, E, A, B, m_W[58]); F3(B, C, D, E, A, m_W[59]); 128 129 F4(A, B, C, D, E, m_W[60]); F4(E, A, B, C, D, m_W[61]); 130 F4(D, E, A, B, C, m_W[62]); F4(C, D, E, A, B, m_W[63]); 131 F4(B, C, D, E, A, m_W[64]); F4(A, B, C, D, E, m_W[65]); 132 F4(E, A, B, C, D, m_W[66]); F4(D, E, A, B, C, m_W[67]); 133 F4(C, D, E, A, B, m_W[68]); F4(B, C, D, E, A, m_W[69]); 134 F4(A, B, C, D, E, m_W[70]); F4(E, A, B, C, D, m_W[71]); 135 F4(D, E, A, B, C, m_W[72]); F4(C, D, E, A, B, m_W[73]); 136 F4(B, C, D, E, A, m_W[74]); F4(A, B, C, D, E, m_W[75]); 137 F4(E, A, B, C, D, m_W[76]); F4(D, E, A, B, C, m_W[77]); 138 F4(C, D, E, A, B, m_W[78]); F4(B, C, D, E, A, m_W[79]); 139 140 A = (m_digest[0] += A); 141 B = (m_digest[1] += B); 142 C = (m_digest[2] += C); 143 D = (m_digest[3] += D); 144 E = (m_digest[4] += E); 145 146 input += hashBlockSize; 147 } 148 } 149 150 /* 151 * Copy out the digest 152 */ 153 override final void copyOut(ubyte* output) 154 { 155 for (size_t i = 0; i != outputLength(); i += 4) 156 storeBigEndian(m_digest[i/4], output + i); 157 } 158 159 /** 160 * The digest value, exposed for use by subclasses (asm, SSE2) 161 */ 162 SecureVector!uint m_digest; 163 164 /** 165 * The message buffer, exposed for use by subclasses (asm, SSE2) 166 */ 167 SecureVector!uint m_W; 168 } 169 170 private: 171 pure: 172 /* 173 * SHA-160 F1 Function 174 */ 175 void F1(uint A, ref uint B, uint C, uint D, ref uint E, uint msg) 176 { 177 E += (D ^ (B & (C ^ D))) + msg + 0x5A827999 + rotateLeft(A, 5); 178 B = rotateLeft(B, 30); 179 } 180 181 /* 182 * SHA-160 F2 Function 183 */ 184 void F2(uint A, ref uint B, uint C, uint D, ref uint E, uint msg) 185 { 186 E += (B ^ C ^ D) + msg + 0x6ED9EBA1 + rotateLeft(A, 5); 187 B = rotateLeft(B, 30); 188 } 189 190 /* 191 * SHA-160 F3 Function 192 */ 193 void F3(uint A, ref uint B, uint C, uint D, ref uint E, uint msg) 194 { 195 E += ((B & C) | ((B | C) & D)) + msg + 0x8F1BBCDC + rotateLeft(A, 5); 196 B = rotateLeft(B, 30); 197 } 198 199 /* 200 * SHA-160 F4 Function 201 */ 202 void F4(uint A, ref uint B, uint C, uint D, ref uint E, uint msg) 203 { 204 E += (B ^ C ^ D) + msg + 0xCA62C1D6 + rotateLeft(A, 5); 205 B = rotateLeft(B, 30); 206 }