1 /**
2 * MD5 (x86-32)
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.md5_x86_32;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_MD5_X86_32):
15 
16 import botan.hash.md5;
17 import botan.hash.hash;
18 import botan.utils.asm_x86_32.asm_x86_32;
19 
20 /**
21 * MD5 in x86 assembly
22 */
23 final class MD5_X86_32 : MD5
24 {
25 public:
26     override HashFunction clone() const { return new MD5_X86_32; }
27 
28 protected:
29     override void compressN(const(ubyte)* input, size_t blocks)
30     {
31         foreach (size_t i; 0 .. blocks)
32         {
33             botan_md5_x86_32_compress(m_digest.ptr, input, m_M.ptr);
34             input += hashBlockSize;
35         }
36     }
37 
38 }
39 
40 extern(C)
41 void botan_md5_x86_32_compress(uint* digest, const(ubyte)* input, uint* M) pure
42 {
43     enum PUSHED = 4;
44     mixin(START_ASM ~ 
45         "naked;\n" ~
46         SPILL_REGS() ~ 
47         ASSIGN(EBP, ARG(PUSHED, 2)) ~ /* input block */
48         ASSIGN(EDI, ARG(PUSHED, 3)) ~ /* expanded words */
49 
50         ZEROIZE(ESI) ~
51 
52         START_LOOP("LOAD_INPUT") ~
53         ADD_IMM(ESI, 4) ~
54 
55         ASSIGN(EAX, ARRAY4(EBP, 0)) ~
56         ASSIGN(EBX, ARRAY4(EBP, 1)) ~
57         ASSIGN(ECX, ARRAY4(EBP, 2)) ~
58         ASSIGN(EDX, ARRAY4(EBP, 3)) ~
59 
60         ADD_IMM(EBP, 16) ~
61 
62         ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-4), EAX) ~
63         ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-3), EBX) ~
64         ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-2), ECX) ~
65         ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-1), EDX) ~
66         LOOP_UNTIL_EQ(ESI, 16, "LOAD_INPUT") ~
67 
68         ASSIGN(EBP, ARG(PUSHED, 1)) ~
69         ASSIGN(EAX, ARRAY4(EBP, 0)) ~
70         ASSIGN(EBX, ARRAY4(EBP, 1)) ~
71         ASSIGN(ECX, ARRAY4(EBP, 2)) ~
72         ASSIGN(EDX, ARRAY4(EBP, 3)) ~
73 
74         FF(EAX,EBX,ECX,EDX, 0, 7,0xD76AA478) ~
75         FF(EDX,EAX,EBX,ECX, 1,12,0xE8C7B756) ~
76         FF(ECX,EDX,EAX,EBX, 2,17,0x242070DB) ~
77         FF(EBX,ECX,EDX,EAX, 3,22,0xC1BDCEEE) ~
78         FF(EAX,EBX,ECX,EDX, 4, 7,0xF57C0FAF) ~
79         FF(EDX,EAX,EBX,ECX, 5,12,0x4787C62A) ~
80         FF(ECX,EDX,EAX,EBX, 6,17,0xA8304613) ~
81         FF(EBX,ECX,EDX,EAX, 7,22,0xFD469501) ~
82         FF(EAX,EBX,ECX,EDX, 8, 7,0x698098D8) ~
83         FF(EDX,EAX,EBX,ECX, 9,12,0x8B44F7AF) ~
84         FF(ECX,EDX,EAX,EBX,10,17,0xFFFF5BB1) ~
85         FF(EBX,ECX,EDX,EAX,11,22,0x895CD7BE) ~
86         FF(EAX,EBX,ECX,EDX,12, 7,0x6B901122) ~
87         FF(EDX,EAX,EBX,ECX,13,12,0xFD987193) ~
88         FF(ECX,EDX,EAX,EBX,14,17,0xA679438E) ~
89         FF(EBX,ECX,EDX,EAX,15,22,0x49B40821) ~
90 
91         GG(EAX,EBX,ECX,EDX, 1, 5,0xF61E2562) ~
92         GG(EDX,EAX,EBX,ECX, 6, 9,0xC040B340) ~
93         GG(ECX,EDX,EAX,EBX,11,14,0x265E5A51) ~
94         GG(EBX,ECX,EDX,EAX, 0,20,0xE9B6C7AA) ~
95         GG(EAX,EBX,ECX,EDX, 5, 5,0xD62F105D) ~
96         GG(EDX,EAX,EBX,ECX,10, 9,0x02441453) ~
97         GG(ECX,EDX,EAX,EBX,15,14,0xD8A1E681) ~
98         GG(EBX,ECX,EDX,EAX, 4,20,0xE7D3FBC8) ~
99         GG(EAX,EBX,ECX,EDX, 9, 5,0x21E1CDE6) ~
100         GG(EDX,EAX,EBX,ECX,14, 9,0xC33707D6) ~
101         GG(ECX,EDX,EAX,EBX, 3,14,0xF4D50D87) ~
102         GG(EBX,ECX,EDX,EAX, 8,20,0x455A14ED) ~
103         GG(EAX,EBX,ECX,EDX,13, 5,0xA9E3E905) ~
104         GG(EDX,EAX,EBX,ECX, 2, 9,0xFCEFA3F8) ~
105         GG(ECX,EDX,EAX,EBX, 7,14,0x676F02D9) ~
106         GG(EBX,ECX,EDX,EAX,12,20,0x8D2A4C8A) ~
107 
108         HH(EAX,EBX,ECX,EDX, 5, 4,0xFFFA3942) ~
109         HH(EDX,EAX,EBX,ECX, 8,11,0x8771F681) ~
110         HH(ECX,EDX,EAX,EBX,11,16,0x6D9D6122) ~
111         HH(EBX,ECX,EDX,EAX,14,23,0xFDE5380C) ~
112         HH(EAX,EBX,ECX,EDX, 1, 4,0xA4BEEA44) ~
113         HH(EDX,EAX,EBX,ECX, 4,11,0x4BDECFA9) ~
114         HH(ECX,EDX,EAX,EBX, 7,16,0xF6BB4B60) ~
115         HH(EBX,ECX,EDX,EAX,10,23,0xBEBFBC70) ~
116         HH(EAX,EBX,ECX,EDX,13, 4,0x289B7EC6) ~
117         HH(EDX,EAX,EBX,ECX, 0,11,0xEAA127FA) ~
118         HH(ECX,EDX,EAX,EBX, 3,16,0xD4EF3085) ~
119         HH(EBX,ECX,EDX,EAX, 6,23,0x04881D05) ~
120         HH(EAX,EBX,ECX,EDX, 9, 4,0xD9D4D039) ~
121         HH(EDX,EAX,EBX,ECX,12,11,0xE6DB99E5) ~
122         HH(ECX,EDX,EAX,EBX,15,16,0x1FA27CF8) ~
123         HH(EBX,ECX,EDX,EAX, 2,23,0xC4AC5665) ~
124 
125         II(EAX,EBX,ECX,EDX, 0, 6,0xF4292244) ~
126         II(EDX,EAX,EBX,ECX, 7,10,0x432AFF97) ~
127         II(ECX,EDX,EAX,EBX,14,15,0xAB9423A7) ~
128         II(EBX,ECX,EDX,EAX, 5,21,0xFC93A039) ~
129         II(EAX,EBX,ECX,EDX,12, 6,0x655B59C3) ~
130         II(EDX,EAX,EBX,ECX, 3,10,0x8F0CCC92) ~
131         II(ECX,EDX,EAX,EBX,10,15,0xFFEFF47D) ~
132         II(EBX,ECX,EDX,EAX, 1,21,0x85845DD1) ~
133         II(EAX,EBX,ECX,EDX, 8, 6,0x6FA87E4F) ~
134         II(EDX,EAX,EBX,ECX,15,10,0xFE2CE6E0) ~
135         II(ECX,EDX,EAX,EBX, 6,15,0xA3014314) ~
136         II(EBX,ECX,EDX,EAX,13,21,0x4E0811A1) ~
137         II(EAX,EBX,ECX,EDX, 4, 6,0xF7537E82) ~
138         II(EDX,EAX,EBX,ECX,11,10,0xBD3AF235) ~
139         II(ECX,EDX,EAX,EBX, 2,15,0x2AD7D2BB) ~
140         II(EBX,ECX,EDX,EAX, 9,21,0xEB86D391) ~
141 
142         ASSIGN(EBP, ARG(PUSHED, 1)) ~
143         ADD(ARRAY4(EBP, 0), EAX) ~
144         ADD(ARRAY4(EBP, 1), EBX) ~
145         ADD(ARRAY4(EBP, 2), ECX) ~
146         ADD(ARRAY4(EBP, 3), EDX) ~
147 
148         RESTORE_REGS() ~ 
149         "ret;\n" ~
150         END_ASM);
151         
152 }
153 
154 enum MSG = EDI;
155 enum T1 = ESI;
156 enum T2 = EBP;
157 
158 string FF(string A, string B, string C, string D, ubyte N, ubyte S, int MAGIC) {
159     return  ASSIGN(T1, ARRAY4(MSG, N)) ~
160             ASSIGN(T2, C) ~
161             XOR(T2, D)     ~
162             AND(T2, B)     ~
163             XOR(T2, D)     ~
164             ADD3_IMM(A, T1, MAGIC)     ~
165             ADD(A, T2)     ~
166             ROTL_IMM(A, S) ~
167             ADD(A, B);
168 }
169 
170 string GG(string A, string B, string C, string D, ubyte N, ubyte S, int MAGIC)
171 {
172     return  ASSIGN(T1, ARRAY4(MSG, N)) ~
173             ASSIGN(T2, B) ~
174             XOR(T2, C)     ~
175             AND(T2, D)     ~
176             XOR(T2, C)     ~
177             ADD3_IMM(A, T1, MAGIC)     ~
178             ADD(A, T2)     ~
179             ROTL_IMM(A, S) ~
180             ADD(A, B);
181 }
182 
183 string HH(string A, string B, string C, string D, ubyte N, ubyte S, int MAGIC)
184 {
185     return  ASSIGN(T1, ARRAY4(MSG, N)) ~
186             ASSIGN(T2, B) ~
187             XOR(T2, C)     ~
188             XOR(T2, D)     ~
189             ADD3_IMM(A, T1, MAGIC)     ~
190             ADD(A, T2)     ~
191             ROTL_IMM(A, S) ~
192             ADD(A, B);
193 }
194 
195 string II(string A, string B, string C, string D, ubyte N, ubyte S, int MAGIC) 
196 {
197     return  ASSIGN(T1, ARRAY4(MSG, N)) ~
198             ASSIGN(T2, D) ~
199             NOT(T2) ~
200             OR(T2, B)         ~
201             XOR(T2, C)     ~
202             ADD3_IMM(A, T1, MAGIC)     ~
203             ADD(A, T2)     ~
204             ROTL_IMM(A, S) ~
205             ADD(A, B);
206 }