1 /**
2 * SHA-160 (x86-64)
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.sha1_x86_64;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_SHA1 && BOTAN_HAS_SHA1_X86_64):
15 
16 import botan.utils.asm_x86_64.asm_x86_64;
17 import botan.hash.sha160;
18 import botan.hash.hash;
19 
20 /**
21 * SHA-160 in x86-64 assembly
22 */
23 class SHA160_X86_64 : SHA160
24 {
25 public:
26     override HashFunction clone() const { return new SHA160_X86_64; }
27 
28 protected:
29     /*
30     * SHA-160 Compression Function
31     */
32     override void compressN(const(ubyte)* input, size_t blocks)
33     {
34         foreach (size_t i; 0 .. blocks)
35         {
36             botan_sha160_x86_64_compress(m_digest.ptr, input, m_W.ptr);
37             input += hashBlockSize;
38         }
39     }
40 }
41 
42 private:
43 pure:
44 
45 enum DIGEST_ARR = "RDI";
46 enum INPUT = "RSI";
47 enum W = "RDX";
48 enum LOOP_CTR = "EAX";
49 
50 enum A = "R8D";
51 enum B = "R9D";
52 enum C = "R10D";
53 enum D = "R11D";
54 enum E = "ECX";
55 
56 /*
57 * Using negative values for SHA-1 constants > 2^31 to work around
58 * a bug in binutils not accepting large lea displacements.
59 *    -0x70E44324 == 0x8F1BBCDC
60 *    -0x359D3E2A == 0xCA62C1D6
61 */
62 enum MAGIC1 = 0x5A827999;
63 enum MAGIC2 = 0x6ED9EBA1;
64 enum MAGIC3 = -0x70E44324;
65 enum MAGIC4 = -0x359D3E2A;
66 
67 enum T = "ESI";
68 enum T2 = "EAX";
69 
70 extern(C)
71 void botan_sha160_x86_64_compress(uint* arg1, const(ubyte)* arg2, uint* arg3)
72 {
73     /* defined later
74          enum A = "R8D";
75         enum B = "R9D";
76         enum C = "R10D";
77         enum D = "R11D";
78         enum E = "ECX";
79     */
80     enum ASM = 
81             START_ASM ~
82             "mov " ~ DIGEST_ARR ~ ", arg1;" ~ 
83             "mov " ~ INPUT ~ ", arg2;" ~ 
84             "mov " ~ W ~ ", arg3;" ~
85             ZEROIZE(LOOP_CTR) ~
86             ALIGN ~ `;
87 LOOP_LOAD_INPUT:
88             add EAX, 8;
89 
90             mov ` ~ R8 ~ `, ` ~ ARRAY8(INPUT, 0) ~ `;
91             mov ` ~ R9 ~ `, ` ~ ARRAY8(INPUT, 1) ~ `;
92             mov ` ~ R10 ~ `, ` ~ ARRAY8(INPUT, 2) ~ `;
93             mov ` ~ R11 ~ `, ` ~ ARRAY8(INPUT, 3) ~ `;
94 
95             bswap ` ~ R8 ~ `;
96             bswap ` ~ R9 ~ `;
97             bswap ` ~ R10 ~ `;
98             bswap ` ~ R11 ~ `;
99 
100             rol ` ~ R8 ~ `, 32;
101             rol ` ~ R9 ~ `, 32;
102             rol ` ~ R10 ~ `, 32;
103             rol ` ~ R11 ~ `, 32;
104 
105             mov ` ~ ARRAY8(W, 0) ~ `, ` ~ R8 ~ `;
106             mov ` ~ ARRAY8(W, 1) ~ `, ` ~ R9 ~ `;
107             mov ` ~ ARRAY8(W, 2) ~ `, ` ~ R10 ~ `;
108             mov ` ~ ARRAY8(W, 3) ~ `, ` ~ R11 ~ `;
109 
110             add ` ~ W ~ `, 32;
111             add ` ~ INPUT ~ `, 32;
112 
113             cmp ` ~ LOOP_CTR ~ `, ` ~ IMM(16) ~ `;
114             jne LOOP_LOAD_INPUT;` ~
115 
116             ALIGN ~ `;
117             LOOP_EXPANSION:
118             add ` ~ LOOP_CTR ~ `, 4;
119             `  ~
120                 
121             ZEROIZE(A) ~
122             ASSIGN(B, ARRAY4(W, -1)) ~
123             ASSIGN(C, ARRAY4(W, -2)) ~
124             ASSIGN(D, ARRAY4(W, -3)) ~
125 
126             XOR(A, ARRAY4(W, -5)) ~
127             XOR(B, ARRAY4(W, -6)) ~
128             XOR(C, ARRAY4(W, -7)) ~
129             XOR(D, ARRAY4(W, -8)) ~
130 
131             XOR(A, ARRAY4(W, -11)) ~
132             XOR(B, ARRAY4(W, -12)) ~
133             XOR(C, ARRAY4(W, -13)) ~
134             XOR(D, ARRAY4(W, -14)) ~
135 
136             XOR(A, ARRAY4(W, -13)) ~
137             XOR(B, ARRAY4(W, -14)) ~
138             XOR(C, ARRAY4(W, -15)) ~
139             XOR(D, ARRAY4(W, -16)) ~
140 
141             ROTL_IMM(D, 1) ~
142             ROTL_IMM(C, 1) ~
143             ROTL_IMM(B, 1) ~
144             XOR(A, D) ~
145             ROTL_IMM(A, 1) ~
146 
147             ASSIGN(ARRAY4(W, 0), D) ~
148             ASSIGN(ARRAY4(W, 1), C) ~
149             ASSIGN(ARRAY4(W, 2), B) ~
150             ASSIGN(ARRAY4(W, 3), A) ~
151 
152             `add ` ~ W ~ `, 16;
153             cmp ` ~ LOOP_CTR ~ `, ` ~ IMM(80) ~ `;
154             jne LOOP_EXPANSION;
155 
156             sub ` ~ W ~ `, 320;` ~
157 
158 
159 
160             ASSIGN(T, ARRAY4(DIGEST_ARR, 0)) ~
161             ASSIGN(B, ARRAY4(DIGEST_ARR, 1)) ~
162             ASSIGN(C, ARRAY4(DIGEST_ARR, 2)) ~
163             ASSIGN(D, ARRAY4(DIGEST_ARR, 3)) ~
164             ASSIGN(E, ARRAY4(DIGEST_ARR, 4)) ~
165 
166             /* First Round */
167             F1(A, B, C, D, E, T, 0) ~
168             F1(T, A, B, C, D, E, 1) ~
169             F1(E, T, A, B, C, D, 2) ~
170             F1(D, E, T, A, B, C, 3) ~
171             F1(C, D, E, T, A, B, 4) ~
172             F1(B, C, D, E, T, A, 5) ~
173             F1(A, B, C, D, E, T, 6) ~
174             F1(T, A, B, C, D, E, 7) ~
175             F1(E, T, A, B, C, D, 8) ~
176             F1(D, E, T, A, B, C, 9) ~
177             F1(C, D, E, T, A, B, 10) ~
178             F1(B, C, D, E, T, A, 11) ~
179             F1(A, B, C, D, E, T, 12) ~
180             F1(T, A, B, C, D, E, 13) ~
181             F1(E, T, A, B, C, D, 14) ~
182             F1(D, E, T, A, B, C, 15) ~
183             F1(C, D, E, T, A, B, 16) ~
184             F1(B, C, D, E, T, A, 17) ~
185             F1(A, B, C, D, E, T, 18) ~
186             F1(T, A, B, C, D, E, 19) ~
187 
188             /* Second Round */
189             F2(E, T, A, B, C, D, 20) ~
190             F2(D, E, T, A, B, C, 21) ~
191             F2(C, D, E, T, A, B, 22) ~
192             F2(B, C, D, E, T, A, 23) ~
193             F2(A, B, C, D, E, T, 24) ~
194             F2(T, A, B, C, D, E, 25) ~
195             F2(E, T, A, B, C, D, 26) ~
196             F2(D, E, T, A, B, C, 27) ~
197             F2(C, D, E, T, A, B, 28) ~
198             F2(B, C, D, E, T, A, 29 ) ~
199             F2(A, B, C, D, E, T, 30 ) ~
200             F2(T, A, B, C, D, E, 31 ) ~
201             F2(E, T, A, B, C, D, 32 ) ~
202             F2(D, E, T, A, B, C, 33 ) ~
203             F2(C, D, E, T, A, B, 34 ) ~
204             F2(B, C, D, E, T, A, 35 ) ~
205             F2(A, B, C, D, E, T, 36 ) ~
206             F2(T, A, B, C, D, E, 37 ) ~
207             F2(E, T, A, B, C, D, 38 ) ~
208             F2(D, E, T, A, B, C, 39 ) ~
209 
210             /* Third Round */
211             F3(C, D, E, T, A, B, 40 ) ~
212             F3(B, C, D, E, T, A, 41 ) ~
213             F3(A, B, C, D, E, T, 42 ) ~
214             F3(T, A, B, C, D, E, 43 ) ~
215             F3(E, T, A, B, C, D, 44 ) ~
216             F3(D, E, T, A, B, C, 45 ) ~
217             F3(C, D, E, T, A, B, 46 ) ~
218             F3(B, C, D, E, T, A, 47 ) ~
219             F3(A, B, C, D, E, T, 48 ) ~
220             F3(T, A, B, C, D, E, 49 ) ~
221             F3(E, T, A, B, C, D, 50 ) ~
222             F3(D, E, T, A, B, C, 51 ) ~
223             F3(C, D, E, T, A, B, 52 ) ~
224             F3(B, C, D, E, T, A, 53 ) ~
225             F3(A, B, C, D, E, T, 54 ) ~
226             F3(T, A, B, C, D, E, 55 ) ~
227             F3(E, T, A, B, C, D, 56 ) ~
228             F3(D, E, T, A, B, C, 57 ) ~
229             F3(C, D, E, T, A, B, 58 ) ~
230             F3(B, C, D, E, T, A, 59 ) ~
231 
232             /* Fourth Round */
233             F4(A, B, C, D, E, T, 60 ) ~
234             F4(T, A, B, C, D, E, 61 ) ~
235             F4(E, T, A, B, C, D, 62 ) ~
236             F4(D, E, T, A, B, C, 63 ) ~
237             F4(C, D, E, T, A, B, 64 ) ~
238             F4(B, C, D, E, T, A, 65 ) ~
239             F4(A, B, C, D, E, T, 66 ) ~
240             F4(T, A, B, C, D, E, 67 ) ~
241             F4(E, T, A, B, C, D, 68 ) ~
242             F4(D, E, T, A, B, C, 69 ) ~
243             F4(C, D, E, T, A, B, 70 ) ~
244             F4(B, C, D, E, T, A, 71 ) ~
245             F4(A, B, C, D, E, T, 72 ) ~
246             F4(T, A, B, C, D, E, 73 ) ~
247             F4(E, T, A, B, C, D, 74 ) ~
248             F4(D, E, T, A, B, C, 75 ) ~
249             F4(C, D, E, T, A, B, 76 ) ~
250             F4(B, C, D, E, T, A, 77 ) ~
251             F4(A, B, C, D, E, T, 78 ) ~
252             F4(T, A, B, C, D, E, 79 ) ~
253 
254             ADD(ARRAY4(DIGEST_ARR, 0), D) ~
255             ADD(ARRAY4(DIGEST_ARR, 1), T) ~
256             ADD(ARRAY4(DIGEST_ARR, 2), A) ~
257             ADD(ARRAY4(DIGEST_ARR, 3), B) ~
258             ADD(ARRAY4(DIGEST_ARR, 4), C) ~
259       END_ASM;
260 
261 
262     mixin(ASM);
263 
264 
265 }
266 
267 
268 string F1(string A, string B, string C, string D, string E, string F, ubyte N)
269 {
270     return ASSIGN(T2, ARRAY4(W, N))    ~
271             ASSIGN(A, F) ~
272             ROTL_IMM(F, 5) ~
273             ADD(F, E) ~
274             ASSIGN(E, C) ~
275             XOR(E, D) ~
276             ADD3_IMM(F, T2, MAGIC1) ~
277             AND(E, B) ~
278             XOR(E, D) ~
279             ROTR_IMM(B, 2) ~
280             ADD(E, F);
281 }
282 
283 string F2_4(string A, string B, string C, string D, string E, string F, ubyte N, int MAGIC)
284 {
285     return ASSIGN(T2, ARRAY4(W, N)) ~
286             ASSIGN(A, F) ~
287             ROTL_IMM(F, 5) ~
288             ADD(F, E) ~
289             ASSIGN(E, B) ~
290             XOR(E, C) ~
291             ADD3_IMM(F, T2, MAGIC) ~
292             XOR(E, D) ~
293             ROTR_IMM(B, 2) ~
294             ADD(E, F);
295 }
296 
297 string F3(string A, string B, string C, string D, string E, string F, ubyte N)
298 {
299     return ASSIGN(T2, ARRAY4(W, N)) ~
300             ASSIGN(A, F) ~
301             ROTL_IMM(F, 5) ~
302             ADD(F, E) ~
303             ASSIGN(E, B) ~
304             OR(E, C) ~
305             AND(E, D) ~
306             ADD3_IMM(F, T2, MAGIC3) ~
307             ASSIGN(T2, B) ~
308             AND(T2, C) ~
309             OR(E, T2) ~
310             ROTR_IMM(B, 2) ~
311             ADD(E, F);
312 }
313 
314 string F2(string A, string B, string C, string D, string E, string F, ubyte W2)
315 {
316     return F2_4(A, B, C, D, E, F, W2, MAGIC2);
317 }
318 
319 string F4(string A, string B, string C, string D, string E, string F, ubyte W2)
320 {
321     return F2_4(A, B, C, D, E, F, W2, MAGIC4);
322 }