aarch64: Enable building the aarch64 cipher assembly for windows
[libgcrypt.git] / cipher / cipher-gcm-armv8-aarch64-ce.S
1 /* cipher-gcm-armv8-aarch64-ce.S - ARM/CE accelerated GHASH
2  * Copyright (C) 2016 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "asm-common-aarch64.h"
21
22 #if defined(__AARCH64EL__) && \
23     defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
24     defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO)
25
26 .cpu generic+simd+crypto
27
28 .text
29
30 #define GET_DATA_POINTER(reg, name) \
31                 adrp    reg, :got:name ; \
32                 ldr     reg, [reg, #:got_lo12:name] ;
33
34
35 /* Constants */
36
37 .align 4
38 gcry_gcm_reduction_constant:
39 .Lrconst:
40   .quad 0x87
41
42
43 /* Register macros */
44
45 #define rhash   v0
46 #define rr0     v1
47 #define rr1     v2
48 #define rbuf    v3
49 #define rbuf1   v4
50 #define rbuf2   v5
51 #define rbuf3   v6
52 #define rbuf4   v7
53 #define rbuf5   v8
54 #define rr2     v9
55 #define rr3     v10
56 #define rr4     v11
57 #define rr5     v12
58 #define rr6     v13
59 #define rr7     v14
60 #define rr8     v15
61 #define rr9     v16
62
63 #define rrconst v18
64 #define rh1     v19
65 #define rh2     v20
66 #define rh3     v21
67 #define rh4     v22
68 #define rh5     v23
69 #define rh6     v24
70 #define t0      v25
71 #define t1      v26
72 #define t2      v27
73 #define t3      v28
74 #define t4      v29
75 #define t5      v30
76 #define vZZ     v31
77
78 /* GHASH macros */
79
80 /* See "Gouvêa, C. P. L. & López, J. Implementing GCM on ARMv8. Topics in
81  * Cryptology — CT-RSA 2015" for details.
82  */
83
84 /* Input: 'a' and 'b', Output: 'r0:r1' (low 128-bits in r0, high in r1) */
85 #define PMUL_128x128(r0, r1, a, b, T0, T1, interleave_op) \
86         ext T0.16b, b.16b, b.16b, #8; \
87         pmull r0.1q, a.1d, b.1d; \
88         pmull2 r1.1q, a.2d, b.2d; \
89         pmull T1.1q, a.1d, T0.1d; \
90         pmull2 T0.1q, a.2d, T0.2d; \
91         interleave_op; \
92         eor T0.16b, T0.16b, T1.16b; \
93         ext T1.16b, vZZ.16b, T0.16b, #8; \
94         ext T0.16b, T0.16b, vZZ.16b, #8; \
95         eor r0.16b, r0.16b, T1.16b; \
96         eor r1.16b, r1.16b, T0.16b;
97
98 /* Input: 'aA' and 'bA', Output: 'r0A:r1A' (low 128-bits in r0A, high in r1A)
99  * Input: 'aB' and 'bB', Output: 'r0B:r1B' (low 128-bits in r0B, high in r1B)
100  * Input: 'aC' and 'bC', Output: 'r0C:r1C' (low 128-bits in r0C, high in r1C)
101  */
102 #define PMUL_128x128_3(r0A, r1A, aA, bA, t0A, t1A, \
103                        r0B, r1B, aB, bB, t0B, t1B, \
104                        r0C, r1C, aC, bC, t0C, t1C,  interleave_op) \
105         ext t0A.16b, bA.16b, bA.16b, #8; \
106         pmull r0A.1q, aA.1d, bA.1d; \
107         pmull2 r1A.1q, aA.2d, bA.2d; \
108           ext t0B.16b, bB.16b, bB.16b, #8; \
109           pmull r0B.1q, aB.1d, bB.1d; \
110           pmull2 r1B.1q, aB.2d, bB.2d; \
111             ext t0C.16b, bC.16b, bC.16b, #8; \
112             pmull r0C.1q, aC.1d, bC.1d; \
113             pmull2 r1C.1q, aC.2d, bC.2d; \
114         pmull t1A.1q, aA.1d, t0A.1d; \
115         pmull2 t0A.1q, aA.2d, t0A.2d; \
116           pmull t1B.1q, aB.1d, t0B.1d; \
117           pmull2 t0B.1q, aB.2d, t0B.2d; \
118             pmull t1C.1q, aC.1d, t0C.1d; \
119             pmull2 t0C.1q, aC.2d, t0C.2d; \
120         eor t0A.16b, t0A.16b, t1A.16b; \
121           eor t0B.16b, t0B.16b, t1B.16b; \
122             eor t0C.16b, t0C.16b, t1C.16b; \
123               interleave_op; \
124         ext t1A.16b, vZZ.16b, t0A.16b, #8; \
125         ext t0A.16b, t0A.16b, vZZ.16b, #8; \
126           ext t1B.16b, vZZ.16b, t0B.16b, #8; \
127           ext t0B.16b, t0B.16b, vZZ.16b, #8; \
128             ext t1C.16b, vZZ.16b, t0C.16b, #8; \
129             ext t0C.16b, t0C.16b, vZZ.16b, #8; \
130         eor r0A.16b, r0A.16b, t1A.16b; \
131         eor r1A.16b, r1A.16b, t0A.16b; \
132           eor r0B.16b, r0B.16b, t1B.16b; \
133           eor r1B.16b, r1B.16b, t0B.16b; \
134             eor r0C.16b, r0C.16b, t1C.16b; \
135             eor r1C.16b, r1C.16b, t0C.16b; \
136
137 /* Input: 'r0:r1', Output: 'a' */
138 #define REDUCTION(a, r0, r1, rconst, T0, T1, interleave_op1, interleave_op2, \
139                   interleave_op3) \
140         pmull2 T0.1q, r1.2d, rconst.2d; \
141         interleave_op1; \
142         ext T1.16b, T0.16b, vZZ.16b, #8; \
143         ext T0.16b, vZZ.16b, T0.16b, #8; \
144         interleave_op2; \
145         eor r1.16b, r1.16b, T1.16b; \
146         eor r0.16b, r0.16b, T0.16b; \
147         pmull T0.1q, r1.1d, rconst.1d; \
148         interleave_op3; \
149         eor a.16b, r0.16b, T0.16b;
150
151 /* Other functional macros */
152
153 #define _(...) __VA_ARGS__
154 #define __ _()
155
156 #define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
157
158 #define VPUSH_ABI \
159         stp d8, d9, [sp, #-16]!; \
160         stp d10, d11, [sp, #-16]!; \
161         stp d12, d13, [sp, #-16]!; \
162         stp d14, d15, [sp, #-16]!;
163
164 #define VPOP_ABI \
165         ldp d14, d15, [sp], #16; \
166         ldp d12, d13, [sp], #16; \
167         ldp d10, d11, [sp], #16; \
168         ldp d8, d9, [sp], #16;
169
170 /*
171  * unsigned int _gcry_ghash_armv8_ce_pmull (void *gcm_key, byte *result,
172  *                                          const byte *buf, size_t nblocks,
173  *                                          void *gcm_table);
174  */
175 .align 3
176 .globl _gcry_ghash_armv8_ce_pmull
177 ELF(.type  _gcry_ghash_armv8_ce_pmull,%function;)
178 _gcry_ghash_armv8_ce_pmull:
179   /* input:
180    *    x0: gcm_key
181    *    x1: result/hash
182    *    x2: buf
183    *    x3: nblocks
184    *    x4: gcm_table
185    */
186   cbz x3, .Ldo_nothing;
187
188   GET_DATA_POINTER(x5, .Lrconst)
189
190   eor vZZ.16b, vZZ.16b, vZZ.16b
191   ld1 {rhash.16b}, [x1]
192   ld1 {rh1.16b}, [x0]
193
194   rbit rhash.16b, rhash.16b /* bit-swap */
195   ld1r {rrconst.2d}, [x5]
196
197   cmp x3, #6
198   b.lo .Less_than_6
199
200   add x6, x4, #64
201   VPUSH_ABI
202
203   ld1 {rh2.16b-rh5.16b}, [x4]
204   ld1 {rh6.16b}, [x6]
205
206   sub x3, x3, #6
207
208   ld1 {rbuf.16b-rbuf2.16b}, [x2], #(3*16)
209   ld1 {rbuf3.16b-rbuf5.16b}, [x2], #(3*16)
210
211   rbit rbuf.16b, rbuf.16b /* bit-swap */
212   rbit rbuf1.16b, rbuf1.16b /* bit-swap */
213   rbit rbuf2.16b, rbuf2.16b /* bit-swap */
214   rbit rbuf3.16b, rbuf3.16b /* bit-swap */
215   rbit rbuf4.16b, rbuf4.16b /* bit-swap */
216   rbit rbuf5.16b, rbuf5.16b /* bit-swap */
217   eor rhash.16b, rhash.16b, rbuf.16b
218
219   cmp x3, #6
220   b.lo .Lend_6
221
222 .Loop_6:
223
224   /* (in1) * H⁵ => rr0:rr1 */
225   /* (in2) * H⁴ => rr2:rr3 */
226   /* (in0 ^ hash) * H⁶ => rr4:rr5 */
227   PMUL_128x128_3(rr0, rr1, rbuf1, rh5, t0, t1,
228                  rr2, rr3, rbuf2, rh4, t2, t3,
229                  rr4, rr5, rhash, rh6, t4, t5,
230                  _(sub x3, x3, #6))
231
232   ld1 {rbuf.16b-rbuf2.16b}, [x2], #(3*16)
233   cmp x3, #6
234
235   eor rr0.16b, rr0.16b, rr2.16b
236   eor rr1.16b, rr1.16b, rr3.16b
237
238   /* (in3) * H³ => rr2:rr3 */
239   /* (in4) * H² => rr6:rr7 */
240   /* (in5) * H¹ => rr8:rr9 */
241   PMUL_128x128_3(rr2, rr3, rbuf3, rh3, t0, t1,
242                  rr6, rr7, rbuf4, rh2, t2, t3,
243                  rr8, rr9, rbuf5, rh1, t4, t5,
244                  _(eor rr0.16b, rr0.16b, rr4.16b;
245                    eor rr1.16b, rr1.16b, rr5.16b))
246
247   eor rr0.16b, rr0.16b, rr2.16b
248   eor rr1.16b, rr1.16b, rr3.16b
249   rbit rbuf.16b, rbuf.16b
250   eor rr0.16b, rr0.16b, rr6.16b
251   eor rr1.16b, rr1.16b, rr7.16b
252   rbit rbuf1.16b, rbuf1.16b
253   eor rr0.16b, rr0.16b, rr8.16b
254   eor rr1.16b, rr1.16b, rr9.16b
255   ld1 {rbuf3.16b-rbuf5.16b}, [x2], #(3*16)
256
257   REDUCTION(rhash, rr0, rr1, rrconst, t0, t1,
258             _(rbit rbuf2.16b, rbuf2.16b),
259             _(rbit rbuf3.16b, rbuf3.16b),
260             _(rbit rbuf4.16b, rbuf4.16b))
261
262   rbit rbuf5.16b, rbuf5.16b
263   eor rhash.16b, rhash.16b, rbuf.16b
264
265   b.hs .Loop_6
266
267 .Lend_6:
268
269   /* (in1) * H⁵ => rr0:rr1 */
270   /* (in0 ^ hash) * H⁶ => rr2:rr3 */
271   /* (in2) * H⁴ => rr4:rr5 */
272   PMUL_128x128_3(rr0, rr1, rbuf1, rh5, t0, t1,
273                  rr2, rr3, rhash, rh6, t2, t3,
274                  rr4, rr5, rbuf2, rh4, t4, t5,
275                  __)
276   eor rr0.16b, rr0.16b, rr2.16b
277   eor rr1.16b, rr1.16b, rr3.16b
278   eor rr0.16b, rr0.16b, rr4.16b
279   eor rr1.16b, rr1.16b, rr5.16b
280
281   /* (in3) * H³ => rhash:rbuf */
282   /* (in4) * H² => rr6:rr7 */
283   /* (in5) * H¹ => rr8:rr9 */
284   PMUL_128x128_3(rhash, rbuf, rbuf3, rh3, t0, t1,
285                  rr6, rr7, rbuf4, rh2, t2, t3,
286                  rr8, rr9, rbuf5, rh1, t4, t5,
287                  _(CLEAR_REG(rh4);
288                    CLEAR_REG(rh5);
289                    CLEAR_REG(rh6)))
290   eor rr0.16b, rr0.16b, rhash.16b
291   eor rr1.16b, rr1.16b, rbuf.16b
292   eor rr0.16b, rr0.16b, rr6.16b
293   eor rr1.16b, rr1.16b, rr7.16b
294   eor rr0.16b, rr0.16b, rr8.16b
295   eor rr1.16b, rr1.16b, rr9.16b
296
297   REDUCTION(rhash, rr0, rr1, rrconst, t0, t1,
298             _(CLEAR_REG(rh2);
299               CLEAR_REG(rh3);
300               CLEAR_REG(rr2);
301               CLEAR_REG(rbuf2);
302               CLEAR_REG(rbuf3)),
303             _(CLEAR_REG(rr3);
304               CLEAR_REG(rr4);
305               CLEAR_REG(rr5);
306               CLEAR_REG(rr6);
307               CLEAR_REG(rr7)),
308             _(CLEAR_REG(rr8);
309               CLEAR_REG(rr9);
310               CLEAR_REG(rbuf1);
311               CLEAR_REG(rbuf2)))
312
313   CLEAR_REG(rbuf4)
314   CLEAR_REG(rbuf5)
315   CLEAR_REG(t2)
316   CLEAR_REG(t3)
317   CLEAR_REG(t4)
318   CLEAR_REG(t5)
319
320   VPOP_ABI
321
322   cbz x3, .Ldone
323
324 .Less_than_6:
325   /* Handle remaining blocks. */
326
327   ld1 {rbuf.16b}, [x2], #16
328   sub x3, x3, #1
329
330   rbit rbuf.16b, rbuf.16b /* bit-swap */
331
332   eor rhash.16b, rhash.16b, rbuf.16b
333
334   cbz x3, .Lend
335
336 .Loop:
337   PMUL_128x128(rr0, rr1, rh1, rhash, t0, t1, _(ld1 {rbuf.16b}, [x2], #16))
338   REDUCTION(rhash, rr0, rr1, rrconst, t0, t1,
339             _(sub x3, x3, #1),
340             _(rbit rbuf.16b, rbuf.16b),
341             __)
342   eor rhash.16b, rhash.16b, rbuf.16b
343
344   cbnz x3, .Loop
345
346 .Lend:
347   PMUL_128x128(rr0, rr1, rh1, rhash, t0, t1, _(CLEAR_REG(rbuf)))
348   REDUCTION(rhash, rr0, rr1, rrconst, t0, t1, __, _(CLEAR_REG(rh1)), __)
349
350 .Ldone:
351   CLEAR_REG(rr1)
352   CLEAR_REG(rr0)
353   rbit rhash.16b, rhash.16b /* bit-swap */
354   CLEAR_REG(t0)
355   CLEAR_REG(t1)
356
357   st1 {rhash.2d}, [x1]
358   CLEAR_REG(rhash)
359
360 .Ldo_nothing:
361   mov x0, #0
362   ret
363 ELF(.size _gcry_ghash_armv8_ce_pmull,.-_gcry_ghash_armv8_ce_pmull;)
364
365
366 /*
367  * void _gcry_ghash_setup_armv8_ce_pmull (void *gcm_key, void *gcm_table);
368  */
369 .align 3
370 .globl _gcry_ghash_setup_armv8_ce_pmull
371 ELF(.type  _gcry_ghash_setup_armv8_ce_pmull,%function;)
372 _gcry_ghash_setup_armv8_ce_pmull:
373   /* input:
374    *    x0: gcm_key
375    *    x1: gcm_table
376    */
377
378   GET_DATA_POINTER(x2, .Lrconst)
379
380   /* H¹ */
381   ld1 {rh1.16b}, [x0]
382   rbit rh1.16b, rh1.16b
383   st1 {rh1.16b}, [x0]
384
385   ld1r {rrconst.2d}, [x2]
386
387   /* H² */
388   PMUL_128x128(rr0, rr1, rh1, rh1, t0, t1, __)
389   REDUCTION(rh2, rr0, rr1, rrconst, t0, t1, __, __, __)
390
391   /* H³ */
392   PMUL_128x128(rr0, rr1, rh2, rh1, t0, t1, __)
393   REDUCTION(rh3, rr0, rr1, rrconst, t0, t1, __, __, __)
394
395   /* H⁴ */
396   PMUL_128x128(rr0, rr1, rh2, rh2, t0, t1, __)
397   REDUCTION(rh4, rr0, rr1, rrconst, t0, t1, __, __, __)
398
399   /* H⁵ */
400   PMUL_128x128(rr0, rr1, rh2, rh3, t0, t1, __)
401   REDUCTION(rh5, rr0, rr1, rrconst, t0, t1, __, __, __)
402
403   /* H⁶ */
404   PMUL_128x128(rr0, rr1, rh3, rh3, t0, t1, __)
405   REDUCTION(rh6, rr0, rr1, rrconst, t0, t1, __, __, __)
406
407   st1 {rh2.16b-rh4.16b}, [x1], #(3*16)
408   st1 {rh5.16b-rh6.16b}, [x1]
409
410   ret
411 ELF(.size _gcry_ghash_setup_armv8_ce_pmull,.-_gcry_ghash_setup_armv8_ce_pmull;)
412
413 #endif