1 /**
2 * RIPEMD-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.rmd160;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_RIPEMD_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 * RIPEMD-160
24 */
25 final class RIPEMD160 : MDxHashFunction, HashFunction
26 {
27 public:
28     
29     override @property size_t hashBlockSize() const { return super.hashBlockSize(); }
30     override @property string name() const { return "RIPEMD-160"; }
31     override @property size_t outputLength() const { return 20; }
32     override HashFunction clone() const { return new RIPEMD160; }
33 
34     /*
35     * Clear memory of sensitive data
36     */
37     override void clear()
38     {
39         super.clear();
40         zeroise(m_M);
41         m_digest[0] = 0x67452301;
42         m_digest[1] = 0xEFCDAB89;
43         m_digest[2] = 0x98BADCFE;
44         m_digest[3] = 0x10325476;
45         m_digest[4] = 0xC3D2E1F0;
46     }
47 
48     this()
49     { 
50         super(64, false, true);
51         m_M.length = 16;
52         m_digest.length = 5;
53 
54         clear(); 
55     }
56 protected:
57     /*
58     * RIPEMD-160 Compression Function
59     */
60     override void compressN(const(ubyte)* input, size_t blocks)
61     {
62         const uint MAGIC2 = 0x5A827999, MAGIC3 = 0x6ED9EBA1,
63             MAGIC4 = 0x8F1BBCDC, MAGIC5 = 0xA953FD4E,
64             MAGIC6 = 0x50A28BE6, MAGIC7 = 0x5C4DD124,
65             MAGIC8 = 0x6D703EF3, MAGIC9 = 0x7A6D76E9;
66         
67         foreach (size_t i; 0 .. blocks)
68         {
69             loadLittleEndian(m_M.ptr, input, m_M.length);
70             
71             uint A1 = m_digest[0], A2 = A1, B1 = m_digest[1], B2 = B1,
72                 C1 = m_digest[2], C2 = C1, D1 = m_digest[3], D2 = D1,
73                 E1 = m_digest[4], E2 = E1;
74             
75             F1(A1,B1,C1,D1,E1,m_M[ 0],11         );  F5(A2,B2,C2,D2,E2,m_M[ 5], 8,MAGIC6);
76             F1(E1,A1,B1,C1,D1,m_M[ 1],14         );  F5(E2,A2,B2,C2,D2,m_M[14], 9,MAGIC6);
77             F1(D1,E1,A1,B1,C1,m_M[ 2],15         );  F5(D2,E2,A2,B2,C2,m_M[ 7], 9,MAGIC6);
78             F1(C1,D1,E1,A1,B1,m_M[ 3],12         );  F5(C2,D2,E2,A2,B2,m_M[ 0],11,MAGIC6);
79             F1(B1,C1,D1,E1,A1,m_M[ 4], 5         );  F5(B2,C2,D2,E2,A2,m_M[ 9],13,MAGIC6);
80             F1(A1,B1,C1,D1,E1,m_M[ 5], 8         );  F5(A2,B2,C2,D2,E2,m_M[ 2],15,MAGIC6);
81             F1(E1,A1,B1,C1,D1,m_M[ 6], 7         );  F5(E2,A2,B2,C2,D2,m_M[11],15,MAGIC6);
82             F1(D1,E1,A1,B1,C1,m_M[ 7], 9         );  F5(D2,E2,A2,B2,C2,m_M[ 4], 5,MAGIC6);
83             F1(C1,D1,E1,A1,B1,m_M[ 8],11         );  F5(C2,D2,E2,A2,B2,m_M[13], 7,MAGIC6);
84             F1(B1,C1,D1,E1,A1,m_M[ 9],13         );  F5(B2,C2,D2,E2,A2,m_M[ 6], 7,MAGIC6);
85             F1(A1,B1,C1,D1,E1,m_M[10],14         );  F5(A2,B2,C2,D2,E2,m_M[15], 8,MAGIC6);
86             F1(E1,A1,B1,C1,D1,m_M[11],15         );  F5(E2,A2,B2,C2,D2,m_M[ 8],11,MAGIC6);
87             F1(D1,E1,A1,B1,C1,m_M[12], 6         );  F5(D2,E2,A2,B2,C2,m_M[ 1],14,MAGIC6);
88             F1(C1,D1,E1,A1,B1,m_M[13], 7         );  F5(C2,D2,E2,A2,B2,m_M[10],14,MAGIC6);
89             F1(B1,C1,D1,E1,A1,m_M[14], 9         );  F5(B2,C2,D2,E2,A2,m_M[ 3],12,MAGIC6);
90             F1(A1,B1,C1,D1,E1,m_M[15], 8         );  F5(A2,B2,C2,D2,E2,m_M[12], 6,MAGIC6);
91             
92             F2(E1,A1,B1,C1,D1,m_M[ 7], 7,MAGIC2);  F4(E2,A2,B2,C2,D2,m_M[ 6], 9,MAGIC7);
93             F2(D1,E1,A1,B1,C1,m_M[ 4], 6,MAGIC2);  F4(D2,E2,A2,B2,C2,m_M[11],13,MAGIC7);
94             F2(C1,D1,E1,A1,B1,m_M[13], 8,MAGIC2);  F4(C2,D2,E2,A2,B2,m_M[ 3],15,MAGIC7);
95             F2(B1,C1,D1,E1,A1,m_M[ 1],13,MAGIC2);  F4(B2,C2,D2,E2,A2,m_M[ 7], 7,MAGIC7);
96             F2(A1,B1,C1,D1,E1,m_M[10],11,MAGIC2);  F4(A2,B2,C2,D2,E2,m_M[ 0],12,MAGIC7);
97             F2(E1,A1,B1,C1,D1,m_M[ 6], 9,MAGIC2);  F4(E2,A2,B2,C2,D2,m_M[13], 8,MAGIC7);
98             F2(D1,E1,A1,B1,C1,m_M[15], 7,MAGIC2);  F4(D2,E2,A2,B2,C2,m_M[ 5], 9,MAGIC7);
99             F2(C1,D1,E1,A1,B1,m_M[ 3],15,MAGIC2);  F4(C2,D2,E2,A2,B2,m_M[10],11,MAGIC7);
100             F2(B1,C1,D1,E1,A1,m_M[12], 7,MAGIC2);  F4(B2,C2,D2,E2,A2,m_M[14], 7,MAGIC7);
101             F2(A1,B1,C1,D1,E1,m_M[ 0],12,MAGIC2);  F4(A2,B2,C2,D2,E2,m_M[15], 7,MAGIC7);
102             F2(E1,A1,B1,C1,D1,m_M[ 9],15,MAGIC2);  F4(E2,A2,B2,C2,D2,m_M[ 8],12,MAGIC7);
103             F2(D1,E1,A1,B1,C1,m_M[ 5], 9,MAGIC2);  F4(D2,E2,A2,B2,C2,m_M[12], 7,MAGIC7);
104             F2(C1,D1,E1,A1,B1,m_M[ 2],11,MAGIC2);  F4(C2,D2,E2,A2,B2,m_M[ 4], 6,MAGIC7);
105             F2(B1,C1,D1,E1,A1,m_M[14], 7,MAGIC2);  F4(B2,C2,D2,E2,A2,m_M[ 9],15,MAGIC7);
106             F2(A1,B1,C1,D1,E1,m_M[11],13,MAGIC2);  F4(A2,B2,C2,D2,E2,m_M[ 1],13,MAGIC7);
107             F2(E1,A1,B1,C1,D1,m_M[ 8],12,MAGIC2);  F4(E2,A2,B2,C2,D2,m_M[ 2],11,MAGIC7);
108             
109             F3(D1,E1,A1,B1,C1,m_M[ 3],11,MAGIC3);  F3(D2,E2,A2,B2,C2,m_M[15], 9,MAGIC8);
110             F3(C1,D1,E1,A1,B1,m_M[10],13,MAGIC3);  F3(C2,D2,E2,A2,B2,m_M[ 5], 7,MAGIC8);
111             F3(B1,C1,D1,E1,A1,m_M[14], 6,MAGIC3);  F3(B2,C2,D2,E2,A2,m_M[ 1],15,MAGIC8);
112             F3(A1,B1,C1,D1,E1,m_M[ 4], 7,MAGIC3);  F3(A2,B2,C2,D2,E2,m_M[ 3],11,MAGIC8);
113             F3(E1,A1,B1,C1,D1,m_M[ 9],14,MAGIC3);  F3(E2,A2,B2,C2,D2,m_M[ 7], 8,MAGIC8);
114             F3(D1,E1,A1,B1,C1,m_M[15], 9,MAGIC3);  F3(D2,E2,A2,B2,C2,m_M[14], 6,MAGIC8);
115             F3(C1,D1,E1,A1,B1,m_M[ 8],13,MAGIC3);  F3(C2,D2,E2,A2,B2,m_M[ 6], 6,MAGIC8);
116             F3(B1,C1,D1,E1,A1,m_M[ 1],15,MAGIC3);  F3(B2,C2,D2,E2,A2,m_M[ 9],14,MAGIC8);
117             F3(A1,B1,C1,D1,E1,m_M[ 2],14,MAGIC3);  F3(A2,B2,C2,D2,E2,m_M[11],12,MAGIC8);
118             F3(E1,A1,B1,C1,D1,m_M[ 7], 8,MAGIC3);  F3(E2,A2,B2,C2,D2,m_M[ 8],13,MAGIC8);
119             F3(D1,E1,A1,B1,C1,m_M[ 0],13,MAGIC3);  F3(D2,E2,A2,B2,C2,m_M[12], 5,MAGIC8);
120             F3(C1,D1,E1,A1,B1,m_M[ 6], 6,MAGIC3);  F3(C2,D2,E2,A2,B2,m_M[ 2],14,MAGIC8);
121             F3(B1,C1,D1,E1,A1,m_M[13], 5,MAGIC3);  F3(B2,C2,D2,E2,A2,m_M[10],13,MAGIC8);
122             F3(A1,B1,C1,D1,E1,m_M[11],12,MAGIC3);  F3(A2,B2,C2,D2,E2,m_M[ 0],13,MAGIC8);
123             F3(E1,A1,B1,C1,D1,m_M[ 5], 7,MAGIC3);  F3(E2,A2,B2,C2,D2,m_M[ 4], 7,MAGIC8);
124             F3(D1,E1,A1,B1,C1,m_M[12], 5,MAGIC3);  F3(D2,E2,A2,B2,C2,m_M[13], 5,MAGIC8);
125             
126             F4(C1,D1,E1,A1,B1,m_M[ 1],11,MAGIC4);  F2(C2,D2,E2,A2,B2,m_M[ 8],15,MAGIC9);
127             F4(B1,C1,D1,E1,A1,m_M[ 9],12,MAGIC4);  F2(B2,C2,D2,E2,A2,m_M[ 6], 5,MAGIC9);
128             F4(A1,B1,C1,D1,E1,m_M[11],14,MAGIC4);  F2(A2,B2,C2,D2,E2,m_M[ 4], 8,MAGIC9);
129             F4(E1,A1,B1,C1,D1,m_M[10],15,MAGIC4);  F2(E2,A2,B2,C2,D2,m_M[ 1],11,MAGIC9);
130             F4(D1,E1,A1,B1,C1,m_M[ 0],14,MAGIC4);  F2(D2,E2,A2,B2,C2,m_M[ 3],14,MAGIC9);
131             F4(C1,D1,E1,A1,B1,m_M[ 8],15,MAGIC4);  F2(C2,D2,E2,A2,B2,m_M[11],14,MAGIC9);
132             F4(B1,C1,D1,E1,A1,m_M[12], 9,MAGIC4);  F2(B2,C2,D2,E2,A2,m_M[15], 6,MAGIC9);
133             F4(A1,B1,C1,D1,E1,m_M[ 4], 8,MAGIC4);  F2(A2,B2,C2,D2,E2,m_M[ 0],14,MAGIC9);
134             F4(E1,A1,B1,C1,D1,m_M[13], 9,MAGIC4);  F2(E2,A2,B2,C2,D2,m_M[ 5], 6,MAGIC9);
135             F4(D1,E1,A1,B1,C1,m_M[ 3],14,MAGIC4);  F2(D2,E2,A2,B2,C2,m_M[12], 9,MAGIC9);
136             F4(C1,D1,E1,A1,B1,m_M[ 7], 5,MAGIC4);  F2(C2,D2,E2,A2,B2,m_M[ 2],12,MAGIC9);
137             F4(B1,C1,D1,E1,A1,m_M[15], 6,MAGIC4);  F2(B2,C2,D2,E2,A2,m_M[13], 9,MAGIC9);
138             F4(A1,B1,C1,D1,E1,m_M[14], 8,MAGIC4);  F2(A2,B2,C2,D2,E2,m_M[ 9],12,MAGIC9);
139             F4(E1,A1,B1,C1,D1,m_M[ 5], 6,MAGIC4);  F2(E2,A2,B2,C2,D2,m_M[ 7], 5,MAGIC9);
140             F4(D1,E1,A1,B1,C1,m_M[ 6], 5,MAGIC4);  F2(D2,E2,A2,B2,C2,m_M[10],15,MAGIC9);
141             F4(C1,D1,E1,A1,B1,m_M[ 2],12,MAGIC4);  F2(C2,D2,E2,A2,B2,m_M[14], 8,MAGIC9);
142             
143             F5(B1,C1,D1,E1,A1,m_M[ 4], 9,MAGIC5);  F1(B2,C2,D2,E2,A2,m_M[12], 8         );
144             F5(A1,B1,C1,D1,E1,m_M[ 0],15,MAGIC5);  F1(A2,B2,C2,D2,E2,m_M[15], 5         );
145             F5(E1,A1,B1,C1,D1,m_M[ 5], 5,MAGIC5);  F1(E2,A2,B2,C2,D2,m_M[10],12         );
146             F5(D1,E1,A1,B1,C1,m_M[ 9],11,MAGIC5);  F1(D2,E2,A2,B2,C2,m_M[ 4], 9         );
147             F5(C1,D1,E1,A1,B1,m_M[ 7], 6,MAGIC5);  F1(C2,D2,E2,A2,B2,m_M[ 1],12         );
148             F5(B1,C1,D1,E1,A1,m_M[12], 8,MAGIC5);  F1(B2,C2,D2,E2,A2,m_M[ 5], 5         );
149             F5(A1,B1,C1,D1,E1,m_M[ 2],13,MAGIC5);  F1(A2,B2,C2,D2,E2,m_M[ 8],14         );
150             F5(E1,A1,B1,C1,D1,m_M[10],12,MAGIC5);  F1(E2,A2,B2,C2,D2,m_M[ 7], 6         );
151             F5(D1,E1,A1,B1,C1,m_M[14], 5,MAGIC5);  F1(D2,E2,A2,B2,C2,m_M[ 6], 8         );
152             F5(C1,D1,E1,A1,B1,m_M[ 1],12,MAGIC5);  F1(C2,D2,E2,A2,B2,m_M[ 2],13         );
153             F5(B1,C1,D1,E1,A1,m_M[ 3],13,MAGIC5);  F1(B2,C2,D2,E2,A2,m_M[13], 6         );
154             F5(A1,B1,C1,D1,E1,m_M[ 8],14,MAGIC5);  F1(A2,B2,C2,D2,E2,m_M[14], 5         );
155             F5(E1,A1,B1,C1,D1,m_M[11],11,MAGIC5);  F1(E2,A2,B2,C2,D2,m_M[ 0],15         );
156             F5(D1,E1,A1,B1,C1,m_M[ 6], 8,MAGIC5);  F1(D2,E2,A2,B2,C2,m_M[ 3],13         );
157             F5(C1,D1,E1,A1,B1,m_M[15], 5,MAGIC5);  F1(C2,D2,E2,A2,B2,m_M[ 9],11         );
158             F5(B1,C1,D1,E1,A1,m_M[13], 6,MAGIC5);  F1(B2,C2,D2,E2,A2,m_M[11],11         );
159             
160             C1          = m_digest[1] + C1 + D2;
161             m_digest[1] = m_digest[2] + D1 + E2;
162             m_digest[2] = m_digest[3] + E1 + A2;
163             m_digest[3] = m_digest[4] + A1 + B2;
164             m_digest[4] = m_digest[0] + B1 + C2;
165             m_digest[0] = C1;
166             
167             input += hashBlockSize;
168         }
169     }
170 
171     /*
172     * Copy out the m_digest
173     */
174     override void copyOut(ubyte* output)
175     {
176         for (size_t i = 0; i != outputLength(); i += 4)
177             storeLittleEndian(m_digest[i/4], output + i);
178     }
179 
180     SecureVector!uint m_M, m_digest;
181 }
182 
183 private:
184 
185 /*
186 * RIPEMD-160 F1 Function
187 */
188 void F1(ref uint A, uint B, ref uint C, uint D, uint E,
189         uint msg, uint shift) pure
190 {
191     A += (B ^ C ^ D) + msg;
192     A  = rotateLeft(A, shift) + E;
193     C  = rotateLeft(C, 10);
194 }
195 
196 /*
197 * RIPEMD-160 F2 Function
198 */
199 void F2(ref uint A, uint B, ref uint C, uint D, uint E,
200         uint msg, uint shift, uint magic) pure
201 {
202     A += (D ^ (B & (C ^ D))) + msg + magic;
203     A  = rotateLeft(A, shift) + E;
204     C  = rotateLeft(C, 10);
205 }
206 
207 /*
208 * RIPEMD-160 F3 Function
209 */
210 void F3(ref uint A, uint B, ref uint C, uint D, uint E,
211         uint msg, uint shift, uint magic) pure
212 {
213     A += (D ^ (B | ~C)) + msg + magic;
214     A  = rotateLeft(A, shift) + E;
215     C  = rotateLeft(C, 10);
216 }
217 
218 /*
219 * RIPEMD-160 F4 Function
220 */
221 void F4(ref uint A, uint B, ref uint C, uint D, uint E,
222         uint msg, uint shift, uint magic) pure
223 {
224     A += (C ^ (D & (B ^ C))) + msg + magic;
225     A  = rotateLeft(A, shift) + E;
226     C  = rotateLeft(C, 10);
227 }
228 
229 /*
230 * RIPEMD-160 F5 Function
231 */
232 void F5(ref uint A, uint B, ref uint C, uint D, uint E,
233         uint msg, uint shift, uint magic) pure
234 {
235     A += (B ^ (C | ~D)) + msg + magic;
236     A  = rotateLeft(A, shift) + E;
237     C  = rotateLeft(C, 10);
238 }