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 }