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 }