1 /**
2 * RIPEMD-128
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.rmd128;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_RIPEMD_128):
15 
16 import botan.utils.loadstor;
17 import botan.utils.rotate;
18 import botan.hash.mdx_hash;
19 import botan.utils.types;
20 import botan.utils.mem_ops;
21 
22 /**
23 * RIPEMD-128
24 */
25 final class RIPEMD128 : MDxHashFunction, HashFunction
26 {
27 public:
28     
29     override @property size_t hashBlockSize() const { return super.hashBlockSize(); }
30     override @property string name() const { return "RIPEMD-128"; }
31     override @property size_t outputLength() const { return 16; }
32     override HashFunction clone() const { return new RIPEMD128; }
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     }
46 
47     this() 
48     { 
49         super(64, false, true);
50         m_M.length = 16;
51         m_digest.length = 4;
52         clear();
53     }
54 protected:
55     /*
56     * RIPEMD-128 Compression Function
57     */
58     override void compressN(const(ubyte)* input, size_t blocks)
59     {
60         
61         const uint MAGIC2 = 0x5A827999, MAGIC3 = 0x6ED9EBA1,
62             MAGIC4 = 0x8F1BBCDC, MAGIC5 = 0x50A28BE6,
63             MAGIC6 = 0x5C4DD124, MAGIC7 = 0x6D703EF3;
64         
65         foreach (size_t i; 0 .. blocks)
66         {
67             loadLittleEndian(m_M.ptr, input, m_M.length);
68             
69             uint A1 = m_digest[0], A2 = A1, B1 = m_digest[1], B2 = B1,
70                 C1 = m_digest[2], C2 = C1, D1 = m_digest[3], D2 = D1;
71             
72             F1(A1,B1,C1,D1,m_M[ 0],11         );    F4(A2,B2,C2,D2,m_M[ 5], 8,MAGIC5);
73             F1(D1,A1,B1,C1,m_M[ 1],14         );    F4(D2,A2,B2,C2,m_M[14], 9,MAGIC5);
74             F1(C1,D1,A1,B1,m_M[ 2],15         );    F4(C2,D2,A2,B2,m_M[ 7], 9,MAGIC5);
75             F1(B1,C1,D1,A1,m_M[ 3],12         );    F4(B2,C2,D2,A2,m_M[ 0],11,MAGIC5);
76             F1(A1,B1,C1,D1,m_M[ 4], 5         );    F4(A2,B2,C2,D2,m_M[ 9],13,MAGIC5);
77             F1(D1,A1,B1,C1,m_M[ 5], 8         );    F4(D2,A2,B2,C2,m_M[ 2],15,MAGIC5);
78             F1(C1,D1,A1,B1,m_M[ 6], 7         );    F4(C2,D2,A2,B2,m_M[11],15,MAGIC5);
79             F1(B1,C1,D1,A1,m_M[ 7], 9         );    F4(B2,C2,D2,A2,m_M[ 4], 5,MAGIC5);
80             F1(A1,B1,C1,D1,m_M[ 8],11         );    F4(A2,B2,C2,D2,m_M[13], 7,MAGIC5);
81             F1(D1,A1,B1,C1,m_M[ 9],13         );    F4(D2,A2,B2,C2,m_M[ 6], 7,MAGIC5);
82             F1(C1,D1,A1,B1,m_M[10],14         );    F4(C2,D2,A2,B2,m_M[15], 8,MAGIC5);
83             F1(B1,C1,D1,A1,m_M[11],15         );    F4(B2,C2,D2,A2,m_M[ 8],11,MAGIC5);
84             F1(A1,B1,C1,D1,m_M[12], 6         );    F4(A2,B2,C2,D2,m_M[ 1],14,MAGIC5);
85             F1(D1,A1,B1,C1,m_M[13], 7         );    F4(D2,A2,B2,C2,m_M[10],14,MAGIC5);
86             F1(C1,D1,A1,B1,m_M[14], 9         );    F4(C2,D2,A2,B2,m_M[ 3],12,MAGIC5);
87             F1(B1,C1,D1,A1,m_M[15], 8         );    F4(B2,C2,D2,A2,m_M[12], 6,MAGIC5);
88             
89             F2(A1,B1,C1,D1,m_M[ 7], 7,MAGIC2);    F3(A2,B2,C2,D2,m_M[ 6], 9,MAGIC6);
90             F2(D1,A1,B1,C1,m_M[ 4], 6,MAGIC2);    F3(D2,A2,B2,C2,m_M[11],13,MAGIC6);
91             F2(C1,D1,A1,B1,m_M[13], 8,MAGIC2);    F3(C2,D2,A2,B2,m_M[ 3],15,MAGIC6);
92             F2(B1,C1,D1,A1,m_M[ 1],13,MAGIC2);    F3(B2,C2,D2,A2,m_M[ 7], 7,MAGIC6);
93             F2(A1,B1,C1,D1,m_M[10],11,MAGIC2);    F3(A2,B2,C2,D2,m_M[ 0],12,MAGIC6);
94             F2(D1,A1,B1,C1,m_M[ 6], 9,MAGIC2);    F3(D2,A2,B2,C2,m_M[13], 8,MAGIC6);
95             F2(C1,D1,A1,B1,m_M[15], 7,MAGIC2);    F3(C2,D2,A2,B2,m_M[ 5], 9,MAGIC6);
96             F2(B1,C1,D1,A1,m_M[ 3],15,MAGIC2);    F3(B2,C2,D2,A2,m_M[10],11,MAGIC6);
97             F2(A1,B1,C1,D1,m_M[12], 7,MAGIC2);    F3(A2,B2,C2,D2,m_M[14], 7,MAGIC6);
98             F2(D1,A1,B1,C1,m_M[ 0],12,MAGIC2);    F3(D2,A2,B2,C2,m_M[15], 7,MAGIC6);
99             F2(C1,D1,A1,B1,m_M[ 9],15,MAGIC2);    F3(C2,D2,A2,B2,m_M[ 8],12,MAGIC6);
100             F2(B1,C1,D1,A1,m_M[ 5], 9,MAGIC2);    F3(B2,C2,D2,A2,m_M[12], 7,MAGIC6);
101             F2(A1,B1,C1,D1,m_M[ 2],11,MAGIC2);    F3(A2,B2,C2,D2,m_M[ 4], 6,MAGIC6);
102             F2(D1,A1,B1,C1,m_M[14], 7,MAGIC2);    F3(D2,A2,B2,C2,m_M[ 9],15,MAGIC6);
103             F2(C1,D1,A1,B1,m_M[11],13,MAGIC2);    F3(C2,D2,A2,B2,m_M[ 1],13,MAGIC6);
104             F2(B1,C1,D1,A1,m_M[ 8],12,MAGIC2);    F3(B2,C2,D2,A2,m_M[ 2],11,MAGIC6);
105             
106             F3(A1,B1,C1,D1,m_M[ 3],11,MAGIC3);    F2(A2,B2,C2,D2,m_M[15], 9,MAGIC7);
107             F3(D1,A1,B1,C1,m_M[10],13,MAGIC3);    F2(D2,A2,B2,C2,m_M[ 5], 7,MAGIC7);
108             F3(C1,D1,A1,B1,m_M[14], 6,MAGIC3);    F2(C2,D2,A2,B2,m_M[ 1],15,MAGIC7);
109             F3(B1,C1,D1,A1,m_M[ 4], 7,MAGIC3);    F2(B2,C2,D2,A2,m_M[ 3],11,MAGIC7);
110             F3(A1,B1,C1,D1,m_M[ 9],14,MAGIC3);    F2(A2,B2,C2,D2,m_M[ 7], 8,MAGIC7);
111             F3(D1,A1,B1,C1,m_M[15], 9,MAGIC3);    F2(D2,A2,B2,C2,m_M[14], 6,MAGIC7);
112             F3(C1,D1,A1,B1,m_M[ 8],13,MAGIC3);    F2(C2,D2,A2,B2,m_M[ 6], 6,MAGIC7);
113             F3(B1,C1,D1,A1,m_M[ 1],15,MAGIC3);    F2(B2,C2,D2,A2,m_M[ 9],14,MAGIC7);
114             F3(A1,B1,C1,D1,m_M[ 2],14,MAGIC3);    F2(A2,B2,C2,D2,m_M[11],12,MAGIC7);
115             F3(D1,A1,B1,C1,m_M[ 7], 8,MAGIC3);    F2(D2,A2,B2,C2,m_M[ 8],13,MAGIC7);
116             F3(C1,D1,A1,B1,m_M[ 0],13,MAGIC3);    F2(C2,D2,A2,B2,m_M[12], 5,MAGIC7);
117             F3(B1,C1,D1,A1,m_M[ 6], 6,MAGIC3);    F2(B2,C2,D2,A2,m_M[ 2],14,MAGIC7);
118             F3(A1,B1,C1,D1,m_M[13], 5,MAGIC3);    F2(A2,B2,C2,D2,m_M[10],13,MAGIC7);
119             F3(D1,A1,B1,C1,m_M[11],12,MAGIC3);    F2(D2,A2,B2,C2,m_M[ 0],13,MAGIC7);
120             F3(C1,D1,A1,B1,m_M[ 5], 7,MAGIC3);    F2(C2,D2,A2,B2,m_M[ 4], 7,MAGIC7);
121             F3(B1,C1,D1,A1,m_M[12], 5,MAGIC3);    F2(B2,C2,D2,A2,m_M[13], 5,MAGIC7);
122             
123             F4(A1,B1,C1,D1,m_M[ 1],11,MAGIC4);    F1(A2,B2,C2,D2,m_M[ 8],15         );
124             F4(D1,A1,B1,C1,m_M[ 9],12,MAGIC4);    F1(D2,A2,B2,C2,m_M[ 6], 5         );
125             F4(C1,D1,A1,B1,m_M[11],14,MAGIC4);    F1(C2,D2,A2,B2,m_M[ 4], 8         );
126             F4(B1,C1,D1,A1,m_M[10],15,MAGIC4);    F1(B2,C2,D2,A2,m_M[ 1],11         );
127             F4(A1,B1,C1,D1,m_M[ 0],14,MAGIC4);    F1(A2,B2,C2,D2,m_M[ 3],14         );
128             F4(D1,A1,B1,C1,m_M[ 8],15,MAGIC4);    F1(D2,A2,B2,C2,m_M[11],14         );
129             F4(C1,D1,A1,B1,m_M[12], 9,MAGIC4);    F1(C2,D2,A2,B2,m_M[15], 6         );
130             F4(B1,C1,D1,A1,m_M[ 4], 8,MAGIC4);    F1(B2,C2,D2,A2,m_M[ 0],14         );
131             F4(A1,B1,C1,D1,m_M[13], 9,MAGIC4);    F1(A2,B2,C2,D2,m_M[ 5], 6         );
132             F4(D1,A1,B1,C1,m_M[ 3],14,MAGIC4);    F1(D2,A2,B2,C2,m_M[12], 9         );
133             F4(C1,D1,A1,B1,m_M[ 7], 5,MAGIC4);    F1(C2,D2,A2,B2,m_M[ 2],12         );
134             F4(B1,C1,D1,A1,m_M[15], 6,MAGIC4);    F1(B2,C2,D2,A2,m_M[13], 9         );
135             F4(A1,B1,C1,D1,m_M[14], 8,MAGIC4);    F1(A2,B2,C2,D2,m_M[ 9],12         );
136             F4(D1,A1,B1,C1,m_M[ 5], 6,MAGIC4);    F1(D2,A2,B2,C2,m_M[ 7], 5         );
137             F4(C1,D1,A1,B1,m_M[ 6], 5,MAGIC4);    F1(C2,D2,A2,B2,m_M[10],15         );
138             F4(B1,C1,D1,A1,m_M[ 2],12,MAGIC4);    F1(B2,C2,D2,A2,m_M[14], 8         );
139             
140             D2          = m_digest[1] + C1 + D2;
141             m_digest[1] = m_digest[2] + D1 + A2;
142             m_digest[2] = m_digest[3] + A1 + B2;
143             m_digest[3] = m_digest[0] + B1 + C2;
144             m_digest[0] = D2;
145             
146             input += hashBlockSize;
147         }
148     }
149 
150     /*
151     * Copy out the m_digest
152     */
153     override void copyOut(ubyte* output)
154     {
155         for (size_t i = 0; i != outputLength(); i += 4)
156             storeLittleEndian(m_digest[i/4], output + i);
157     }
158 
159     SecureVector!uint m_M, m_digest;
160 }
161 
162 
163 
164 
165 
166 private:
167 
168 /*
169 * RIPEMD-128 F1 Function
170 */
171 void F1(ref uint A, uint B, uint C, uint D,
172         uint msg, uint shift) pure
173 {
174     A += (B ^ C ^ D) + msg;
175     A  = rotateLeft(A, shift);
176 }
177 
178 /*
179 * RIPEMD-128 F2 Function
180 */
181 void F2(ref uint A, uint B, uint C, uint D,
182         uint msg, uint shift, uint magic) pure
183 {
184     A += (D ^ (B & (C ^ D))) + msg + magic;
185     A  = rotateLeft(A, shift);
186 }
187 
188 /*
189 * RIPEMD-128 F3 Function
190 */
191 void F3(ref uint A, uint B, uint C, uint D,
192         uint msg, uint shift, uint magic) pure
193 {
194     A += (D ^ (B | ~C)) + msg + magic;
195     A  = rotateLeft(A, shift);
196 }
197 
198 /*
199 * RIPEMD-128 F4 Function
200 */
201 void F4(ref uint A, uint B, uint C, uint D,
202         uint msg, uint shift, uint magic) pure
203 {
204     A += (C ^ (D & (B ^ C))) + msg + magic;
205     A  = rotateLeft(A, shift);
206 }