1 /**
2 * MD4 (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.md4_x86_32;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_MD4_X86_32):
15 
16 import botan.utils.asm_x86_32.asm_x86_32;
17 import botan.hash.md4;
18 import botan.hash.hash;
19 
20 /**
21 * MD4 using x86 assembly
22 */
23 class MD4_X86_32 : MD4
24 {
25 public:
26     override HashFunction clone() const { return new MD4_X86_32; }
27 
28 protected:
29     /*
30     * MD4 Compression Function
31     */
32     override void compressN(const(ubyte)* input, size_t blocks)
33     {
34         foreach (size_t i; 0 .. blocks)
35         {
36             botan_md4_x86_32_compress(m_digest.ptr, input, m_M.ptr);
37             input += hashBlockSize;
38         }
39     }
40 }
41 
42 private:
43 /**
44 * MD4 compression function in x86-32 asm
45 * Params:
46 *  digest = the current digest
47 *  input = the input block
48 *  M = the message buffer
49 */
50 extern(C)
51 void botan_md4_x86_32_compress(uint* digest, const(ubyte)* input, uint* M)
52 {
53     enum PUSHED = 4;
54     enum ASM = START_ASM ~ 
55             "naked;" ~
56             SPILL_REGS() ~ 
57             ASSIGN(EBP, ARG(PUSHED, 2)) ~/* input block */
58             ASSIGN(EDI, ARG(PUSHED, 3)) ~ /* expanded words */
59 
60             ZEROIZE(ESI) ~
61 
62             START_LOOP("LOAD_INPUT") ~
63             ADD_IMM(ESI, 4) ~
64 
65             ASSIGN(EAX, ARRAY4(EBP, 0)) ~
66             ASSIGN(EBX, ARRAY4(EBP, 1)) ~
67             ASSIGN(ECX, ARRAY4(EBP, 2)) ~
68             ASSIGN(EDX, ARRAY4(EBP, 3)) ~
69 
70             ADD_IMM(EBP, 16) ~
71 
72             ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-4), EAX) ~
73             ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-3), EBX) ~
74             ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-2), ECX) ~
75             ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-1), EDX) ~
76             LOOP_UNTIL_EQ(ESI, 16, "LOAD_INPUT") ~
77 
78             ASSIGN(EBP, ARG(PUSHED, 1)) ~
79             ASSIGN(EAX, ARRAY4(EBP, 0)) ~
80             ASSIGN(EBX, ARRAY4(EBP, 1)) ~
81             ASSIGN(ECX, ARRAY4(EBP, 2)) ~
82             ASSIGN(EDX, ARRAY4(EBP, 3)) ~
83 
84             FF(EAX,EBX,ECX,EDX, 0, 3) ~
85             FF(EDX,EAX,EBX,ECX, 1, 7) ~
86             FF(ECX,EDX,EAX,EBX, 2,11) ~
87             FF(EBX,ECX,EDX,EAX, 3,19) ~
88             FF(EAX,EBX,ECX,EDX, 4, 3) ~
89             FF(EDX,EAX,EBX,ECX, 5, 7) ~
90             FF(ECX,EDX,EAX,EBX, 6,11) ~
91             FF(EBX,ECX,EDX,EAX, 7,19) ~
92             FF(EAX,EBX,ECX,EDX, 8, 3) ~
93             FF(EDX,EAX,EBX,ECX, 9, 7) ~
94             FF(ECX,EDX,EAX,EBX,10,11) ~
95             FF(EBX,ECX,EDX,EAX,11,19) ~
96             FF(EAX,EBX,ECX,EDX,12, 3) ~
97             FF(EDX,EAX,EBX,ECX,13, 7) ~
98             FF(ECX,EDX,EAX,EBX,14,11) ~
99             FF(EBX,ECX,EDX,EAX,15,19) ~
100 
101             GG(EAX,EBX,ECX,EDX, 0, 3) ~
102             GG(EDX,EAX,EBX,ECX, 4, 5) ~
103             GG(ECX,EDX,EAX,EBX, 8, 9) ~
104             GG(EBX,ECX,EDX,EAX,12,13) ~
105             GG(EAX,EBX,ECX,EDX, 1, 3) ~
106             GG(EDX,EAX,EBX,ECX, 5, 5) ~
107             GG(ECX,EDX,EAX,EBX, 9, 9) ~
108             GG(EBX,ECX,EDX,EAX,13,13) ~
109             GG(EAX,EBX,ECX,EDX, 2, 3) ~
110             GG(EDX,EAX,EBX,ECX, 6, 5) ~
111             GG(ECX,EDX,EAX,EBX,10, 9) ~
112             GG(EBX,ECX,EDX,EAX,14,13) ~
113             GG(EAX,EBX,ECX,EDX, 3, 3) ~
114             GG(EDX,EAX,EBX,ECX, 7, 5) ~
115             GG(ECX,EDX,EAX,EBX,11, 9) ~
116             GG(EBX,ECX,EDX,EAX,15,13) ~
117 
118             HH(EAX,EBX,ECX,EDX, 0, 3) ~
119             HH(EDX,EAX,EBX,ECX, 8, 9) ~
120             HH(ECX,EDX,EAX,EBX, 4,11) ~
121             HH(EBX,ECX,EDX,EAX,12,15) ~
122             HH(EAX,EBX,ECX,EDX, 2, 3) ~
123             HH(EDX,EAX,EBX,ECX,10, 9) ~
124             HH(ECX,EDX,EAX,EBX, 6,11) ~
125             HH(EBX,ECX,EDX,EAX,14,15) ~
126             HH(EAX,EBX,ECX,EDX, 1, 3) ~
127             HH(EDX,EAX,EBX,ECX, 9, 9) ~
128             HH(ECX,EDX,EAX,EBX, 5,11) ~
129             HH(EBX,ECX,EDX,EAX,13,15) ~
130             HH(EAX,EBX,ECX,EDX, 3, 3) ~
131             HH(EDX,EAX,EBX,ECX,11, 9) ~
132             HH(ECX,EDX,EAX,EBX, 7,11) ~
133             HH(EBX,ECX,EDX,EAX,15,15) ~
134 
135             ASSIGN(EBP, ARG(PUSHED, 1)) ~
136             ADD(ARRAY4(EBP, 0), EAX) ~
137             ADD(ARRAY4(EBP, 1), EBX) ~
138             ADD(ARRAY4(EBP, 2), ECX) ~
139             ADD(ARRAY4(EBP, 3), EDX) ~
140             RESTORE_REGS() ~
141             "ret;" ~
142             END_ASM;
143     mixin(ASM);
144 }
145 
146 
147 enum MSG = EDI;
148 enum T1 = ESI;
149 enum T2 = EBP;
150         
151 string FF(string A, string B, string C, string D, ubyte N, ubyte S) {
152     return  ASSIGN(T1, ARRAY4(MSG, N))~
153             ASSIGN(T2, C)~
154             XOR(T2, D)    ~
155             AND(T2, B)    ~
156             XOR(T2, D)    ~
157             ADD(A, T1)    ~
158             ADD(A, T2)    ~
159             ROTL_IMM(A, S);
160 }
161 
162 string GG(string A, string B, string C, string D, ubyte N, ubyte S) {
163     return  ASSIGN(T1, ARRAY4(MSG, N)) ~
164             ASSIGN(T2, B) ~
165             OR(T2, C)         ~
166             AND(T2, D)     ~
167             ADD3_IMM(A, T1, 0x5A827999) ~
168             ASSIGN(T1, B) ~
169             AND(T1, C)     ~
170             OR(T2, T1)     ~
171             ADD(A, T2)     ~
172             ROTL_IMM(A, S);
173 }
174 string HH(string A, string B, string C, string D, ubyte N, ubyte S) {
175     return  ASSIGN(T1, ARRAY4(MSG, N)) ~
176             ASSIGN(T2, B) ~
177             XOR(T2, C)     ~
178             XOR(T2, D)     ~
179             ADD3_IMM(A, T1, 0x6ED9EBA1) ~
180             ADD(A, T2)     ~
181             ROTL_IMM(A, S);
182 }