1 /** 2 * HAS-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.has160; 12 13 import botan.constants; 14 static if (BOTAN_HAS_HAS_160): 15 16 import botan.hash.mdx_hash; 17 import botan.utils.loadstor; 18 import botan.utils.rotate; 19 import botan.utils.types; 20 import botan.utils.mem_ops; 21 22 /** 23 * HAS-160, a Korean hash function standardized in 24 * TTAS.KO-12.0011/R1. Used in conjuction with KCDSA 25 */ 26 class HAS160 : MDxHashFunction, HashFunction 27 { 28 public: 29 30 override @property size_t hashBlockSize() const { return super.hashBlockSize(); } 31 override @property string name() const { return "HAS-160"; } 32 override @property size_t outputLength() const { return 20; } 33 override HashFunction clone() const { return new HAS160; } 34 35 /* 36 * Clear memory of sensitive data 37 */ 38 override void clear() 39 { 40 super.clear(); 41 zeroise(m_X); 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, false, true); 52 m_X = 20; 53 m_digest.length = 5; 54 clear(); 55 } 56 57 protected: 58 /* 59 * HAS-160 Compression Function 60 */ 61 override void compressN(const(ubyte)* input, size_t blocks) 62 { 63 64 uint A = m_digest[0], B = m_digest[1], C = m_digest[2], 65 D = m_digest[3], E = m_digest[4]; 66 67 foreach (size_t i; 0 .. blocks) 68 { 69 loadLittleEndian(m_X.ptr, input, 16); 70 71 m_X[16] = m_X[ 0] ^ m_X[ 1] ^ m_X[ 2] ^ m_X[ 3]; 72 m_X[17] = m_X[ 4] ^ m_X[ 5] ^ m_X[ 6] ^ m_X[ 7]; 73 m_X[18] = m_X[ 8] ^ m_X[ 9] ^ m_X[10] ^ m_X[11]; 74 m_X[19] = m_X[12] ^ m_X[13] ^ m_X[14] ^ m_X[15]; 75 F1(A,B,C,D,E,m_X[18], 5); F1(E,A,B,C,D,m_X[ 0],11); 76 F1(D,E,A,B,C,m_X[ 1], 7); F1(C,D,E,A,B,m_X[ 2],15); 77 F1(B,C,D,E,A,m_X[ 3], 6); F1(A,B,C,D,E,m_X[19],13); 78 F1(E,A,B,C,D,m_X[ 4], 8); F1(D,E,A,B,C,m_X[ 5],14); 79 F1(C,D,E,A,B,m_X[ 6], 7); F1(B,C,D,E,A,m_X[ 7],12); 80 F1(A,B,C,D,E,m_X[16], 9); F1(E,A,B,C,D,m_X[ 8],11); 81 F1(D,E,A,B,C,m_X[ 9], 8); F1(C,D,E,A,B,m_X[10],15); 82 F1(B,C,D,E,A,m_X[11], 6); F1(A,B,C,D,E,m_X[17],12); 83 F1(E,A,B,C,D,m_X[12], 9); F1(D,E,A,B,C,m_X[13],14); 84 F1(C,D,E,A,B,m_X[14], 5); F1(B,C,D,E,A,m_X[15],13); 85 86 m_X[16] = m_X[ 3] ^ m_X[ 6] ^ m_X[ 9] ^ m_X[12]; 87 m_X[17] = m_X[ 2] ^ m_X[ 5] ^ m_X[ 8] ^ m_X[15]; 88 m_X[18] = m_X[ 1] ^ m_X[ 4] ^ m_X[11] ^ m_X[14]; 89 m_X[19] = m_X[ 0] ^ m_X[ 7] ^ m_X[10] ^ m_X[13]; 90 F2(A,B,C,D,E,m_X[18], 5); F2(E,A,B,C,D,m_X[ 3],11); 91 F2(D,E,A,B,C,m_X[ 6], 7); F2(C,D,E,A,B,m_X[ 9],15); 92 F2(B,C,D,E,A,m_X[12], 6); F2(A,B,C,D,E,m_X[19],13); 93 F2(E,A,B,C,D,m_X[15], 8); F2(D,E,A,B,C,m_X[ 2],14); 94 F2(C,D,E,A,B,m_X[ 5], 7); F2(B,C,D,E,A,m_X[ 8],12); 95 F2(A,B,C,D,E,m_X[16], 9); F2(E,A,B,C,D,m_X[11],11); 96 F2(D,E,A,B,C,m_X[14], 8); F2(C,D,E,A,B,m_X[ 1],15); 97 F2(B,C,D,E,A,m_X[ 4], 6); F2(A,B,C,D,E,m_X[17],12); 98 F2(E,A,B,C,D,m_X[ 7], 9); F2(D,E,A,B,C,m_X[10],14); 99 F2(C,D,E,A,B,m_X[13], 5); F2(B,C,D,E,A,m_X[ 0],13); 100 101 m_X[16] = m_X[ 5] ^ m_X[ 7] ^ m_X[12] ^ m_X[14]; 102 m_X[17] = m_X[ 0] ^ m_X[ 2] ^ m_X[ 9] ^ m_X[11]; 103 m_X[18] = m_X[ 4] ^ m_X[ 6] ^ m_X[13] ^ m_X[15]; 104 m_X[19] = m_X[ 1] ^ m_X[ 3] ^ m_X[ 8] ^ m_X[10]; 105 F3(A,B,C,D,E,m_X[18], 5); F3(E,A,B,C,D,m_X[12],11); 106 F3(D,E,A,B,C,m_X[ 5], 7); F3(C,D,E,A,B,m_X[14],15); 107 F3(B,C,D,E,A,m_X[ 7], 6); F3(A,B,C,D,E,m_X[19],13); 108 F3(E,A,B,C,D,m_X[ 0], 8); F3(D,E,A,B,C,m_X[ 9],14); 109 F3(C,D,E,A,B,m_X[ 2], 7); F3(B,C,D,E,A,m_X[11],12); 110 F3(A,B,C,D,E,m_X[16], 9); F3(E,A,B,C,D,m_X[ 4],11); 111 F3(D,E,A,B,C,m_X[13], 8); F3(C,D,E,A,B,m_X[ 6],15); 112 F3(B,C,D,E,A,m_X[15], 6); F3(A,B,C,D,E,m_X[17],12); 113 F3(E,A,B,C,D,m_X[ 8], 9); F3(D,E,A,B,C,m_X[ 1],14); 114 F3(C,D,E,A,B,m_X[10], 5); F3(B,C,D,E,A,m_X[ 3],13); 115 116 m_X[16] = m_X[ 2] ^ m_X[ 7] ^ m_X[ 8] ^ m_X[13]; 117 m_X[17] = m_X[ 3] ^ m_X[ 4] ^ m_X[ 9] ^ m_X[14]; 118 m_X[18] = m_X[ 0] ^ m_X[ 5] ^ m_X[10] ^ m_X[15]; 119 m_X[19] = m_X[ 1] ^ m_X[ 6] ^ m_X[11] ^ m_X[12]; 120 F4(A,B,C,D,E,m_X[18], 5); F4(E,A,B,C,D,m_X[ 7],11); 121 F4(D,E,A,B,C,m_X[ 2], 7); F4(C,D,E,A,B,m_X[13],15); 122 F4(B,C,D,E,A,m_X[ 8], 6); F4(A,B,C,D,E,m_X[19],13); 123 F4(E,A,B,C,D,m_X[ 3], 8); F4(D,E,A,B,C,m_X[14],14); 124 F4(C,D,E,A,B,m_X[ 9], 7); F4(B,C,D,E,A,m_X[ 4],12); 125 F4(A,B,C,D,E,m_X[16], 9); F4(E,A,B,C,D,m_X[15],11); 126 F4(D,E,A,B,C,m_X[10], 8); F4(C,D,E,A,B,m_X[ 5],15); 127 F4(B,C,D,E,A,m_X[ 0], 6); F4(A,B,C,D,E,m_X[17],12); 128 F4(E,A,B,C,D,m_X[11], 9); F4(D,E,A,B,C,m_X[ 6],14); 129 F4(C,D,E,A,B,m_X[ 1], 5); F4(B,C,D,E,A,m_X[12],13); 130 131 A = (m_digest[0] += A); 132 B = (m_digest[1] += B); 133 C = (m_digest[2] += C); 134 D = (m_digest[3] += D); 135 E = (m_digest[4] += E); 136 137 input += hashBlockSize; 138 } 139 } 140 141 /* 142 * Copy out the digest 143 */ 144 override void copyOut(ubyte* output) 145 { 146 for (size_t i = 0; i != outputLength(); i += 4) 147 storeLittleEndian(m_digest[i/4], output + i); 148 } 149 150 151 SecureVector!uint m_X, m_digest; 152 } 153 154 private: 155 156 /* 157 * HAS-160 F1 Function 158 */ 159 void F1(uint A, ref uint B, uint C, uint D, ref uint E, 160 uint msg, uint rot) 161 { 162 E += rotateLeft(A, rot) + (D ^ (B & (C ^ D))) + msg; 163 B = rotateLeft(B, 10); 164 } 165 166 /* 167 * HAS-160 F2 Function 168 */ 169 void F2(uint A, ref uint B, uint C, uint D, ref uint E, 170 uint msg, uint rot) 171 { 172 E += rotateLeft(A, rot) + (B ^ C ^ D) + msg + 0x5A827999; 173 B = rotateLeft(B, 17); 174 } 175 176 /* 177 * HAS-160 F3 Function 178 */ 179 void F3(uint A, ref uint B, uint C, uint D, ref uint E, 180 uint msg, uint rot) 181 { 182 E += rotateLeft(A, rot) + (C ^ (B | ~D)) + msg + 0x6ED9EBA1; 183 B = rotateLeft(B, 25); 184 } 185 186 /* 187 * HAS-160 F4 Function 188 */ 189 void F4(uint A, ref uint B, uint C, uint D, ref uint E, 190 uint msg, uint rot) 191 { 192 E += rotateLeft(A, rot) + (B ^ C ^ D) + msg + 0x8F1BBCDC; 193 B = rotateLeft(B, 30); 194 }