40097a7107003fde9cec77687b35d34cc8a0dd70
[libgcrypt.git] / cipher / rijndael-armv8-aarch64-ce.S
1 /* rijndael-armv8-aarch64-ce.S - ARMv8/CE accelerated AES
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 <config.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
31 #define GET_DATA_POINTER(reg, name) \
32         adrp    reg, :got:name ; \
33         ldr     reg, [reg, #:got_lo12:name] ;
34
35
36 /* Register macros */
37
38 #define vk0 v17
39 #define vk1 v18
40 #define vk2 v19
41 #define vk3 v20
42 #define vk4 v21
43 #define vk5 v22
44 #define vk6 v23
45 #define vk7 v24
46 #define vk8 v25
47 #define vk9 v26
48 #define vk10 v27
49 #define vk11 v28
50 #define vk12 v29
51 #define vk13 v30
52 #define vk14 v31
53
54
55 /* AES macros */
56
57 #define aes_preload_keys(keysched, nrounds) \
58         cmp nrounds, #12; \
59         ld1 {vk0.16b-vk3.16b}, [keysched], #64; \
60         ld1 {vk4.16b-vk7.16b}, [keysched], #64; \
61         ld1 {vk8.16b-vk10.16b}, [keysched], #48; \
62         b.lo 1f; \
63         ld1 {vk11.16b-vk12.16b}, [keysched], #32; \
64         b.eq 1f; \
65         ld1 {vk13.16b-vk14.16b}, [keysched]; \
66 1:      ;
67
68 #define do_aes_one128(ed, mcimc, vo, vb) \
69         aes##ed    vb.16b, vk0.16b; \
70         aes##mcimc vb.16b, vb.16b; \
71         aes##ed    vb.16b, vk1.16b; \
72         aes##mcimc vb.16b, vb.16b; \
73         aes##ed    vb.16b, vk2.16b; \
74         aes##mcimc vb.16b, vb.16b; \
75         aes##ed    vb.16b, vk3.16b; \
76         aes##mcimc vb.16b, vb.16b; \
77         aes##ed    vb.16b, vk4.16b; \
78         aes##mcimc vb.16b, vb.16b; \
79         aes##ed    vb.16b, vk5.16b; \
80         aes##mcimc vb.16b, vb.16b; \
81         aes##ed    vb.16b, vk6.16b; \
82         aes##mcimc vb.16b, vb.16b; \
83         aes##ed    vb.16b, vk7.16b; \
84         aes##mcimc vb.16b, vb.16b; \
85         aes##ed    vb.16b, vk8.16b; \
86         aes##mcimc vb.16b, vb.16b; \
87         aes##ed    vb.16b, vk9.16b; \
88         eor        vo.16b, vb.16b, vk10.16b;
89
90 #define do_aes_one192(ed, mcimc, vo, vb) \
91         aes##ed    vb.16b, vk0.16b; \
92         aes##mcimc vb.16b, vb.16b; \
93         aes##ed    vb.16b, vk1.16b; \
94         aes##mcimc vb.16b, vb.16b; \
95         aes##ed    vb.16b, vk2.16b; \
96         aes##mcimc vb.16b, vb.16b; \
97         aes##ed    vb.16b, vk3.16b; \
98         aes##mcimc vb.16b, vb.16b; \
99         aes##ed    vb.16b, vk4.16b; \
100         aes##mcimc vb.16b, vb.16b; \
101         aes##ed    vb.16b, vk5.16b; \
102         aes##mcimc vb.16b, vb.16b; \
103         aes##ed    vb.16b, vk6.16b; \
104         aes##mcimc vb.16b, vb.16b; \
105         aes##ed    vb.16b, vk7.16b; \
106         aes##mcimc vb.16b, vb.16b; \
107         aes##ed    vb.16b, vk8.16b; \
108         aes##mcimc vb.16b, vb.16b; \
109         aes##ed    vb.16b, vk9.16b; \
110         aes##mcimc vb.16b, vb.16b; \
111         aes##ed    vb.16b, vk10.16b; \
112         aes##mcimc vb.16b, vb.16b; \
113         aes##ed    vb.16b, vk11.16b; \
114         eor        vo.16b, vb.16b, vk12.16b;
115
116 #define do_aes_one256(ed, mcimc, vo, vb) \
117         aes##ed    vb.16b, vk0.16b; \
118         aes##mcimc vb.16b, vb.16b; \
119         aes##ed    vb.16b, vk1.16b; \
120         aes##mcimc vb.16b, vb.16b; \
121         aes##ed    vb.16b, vk2.16b; \
122         aes##mcimc vb.16b, vb.16b; \
123         aes##ed    vb.16b, vk3.16b; \
124         aes##mcimc vb.16b, vb.16b; \
125         aes##ed    vb.16b, vk4.16b; \
126         aes##mcimc vb.16b, vb.16b; \
127         aes##ed    vb.16b, vk5.16b; \
128         aes##mcimc vb.16b, vb.16b; \
129         aes##ed    vb.16b, vk6.16b; \
130         aes##mcimc vb.16b, vb.16b; \
131         aes##ed    vb.16b, vk7.16b; \
132         aes##mcimc vb.16b, vb.16b; \
133         aes##ed    vb.16b, vk8.16b; \
134         aes##mcimc vb.16b, vb.16b; \
135         aes##ed    vb.16b, vk9.16b; \
136         aes##mcimc vb.16b, vb.16b; \
137         aes##ed    vb.16b, vk10.16b; \
138         aes##mcimc vb.16b, vb.16b; \
139         aes##ed    vb.16b, vk11.16b; \
140         aes##mcimc vb.16b, vb.16b; \
141         aes##ed    vb.16b, vk12.16b; \
142         aes##mcimc vb.16b, vb.16b; \
143         aes##ed    vb.16b, vk13.16b; \
144         eor        vo.16b, vb.16b, vk14.16b;
145
146 #define aes_round_4(ed, mcimc, b0, b1, b2, b3, key) \
147         aes##ed    b0.16b, key.16b; \
148         aes##mcimc b0.16b, b0.16b; \
149           aes##ed    b1.16b, key.16b; \
150           aes##mcimc b1.16b, b1.16b; \
151             aes##ed    b2.16b, key.16b; \
152             aes##mcimc b2.16b, b2.16b; \
153               aes##ed    b3.16b, key.16b; \
154               aes##mcimc b3.16b, b3.16b;
155
156 #define aes_lastround_4(ed, b0, b1, b2, b3, key1, key2) \
157         aes##ed    b0.16b, key1.16b; \
158         eor        b0.16b, b0.16b, key2.16b; \
159           aes##ed    b1.16b, key1.16b; \
160           eor        b1.16b, b1.16b, key2.16b; \
161             aes##ed    b2.16b, key1.16b; \
162             eor        b2.16b, b2.16b, key2.16b; \
163               aes##ed    b3.16b, key1.16b; \
164               eor        b3.16b, b3.16b, key2.16b;
165
166 #define do_aes_4_128(ed, mcimc, b0, b1, b2, b3) \
167         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk0); \
168         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk1); \
169         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk2); \
170         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk3); \
171         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk4); \
172         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk5); \
173         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk6); \
174         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk7); \
175         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk8); \
176         aes_lastround_4(ed, b0, b1, b2, b3, vk9, vk10);
177
178 #define do_aes_4_192(ed, mcimc, b0, b1, b2, b3) \
179         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk0); \
180         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk1); \
181         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk2); \
182         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk3); \
183         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk4); \
184         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk5); \
185         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk6); \
186         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk7); \
187         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk8); \
188         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk9); \
189         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk10); \
190         aes_lastround_4(ed, b0, b1, b2, b3, vk11, vk12);
191
192 #define do_aes_4_256(ed, mcimc, b0, b1, b2, b3) \
193         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk0); \
194         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk1); \
195         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk2); \
196         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk3); \
197         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk4); \
198         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk5); \
199         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk6); \
200         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk7); \
201         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk8); \
202         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk9); \
203         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk10); \
204         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk11); \
205         aes_round_4(ed, mcimc, b0, b1, b2, b3, vk12); \
206         aes_lastround_4(ed, b0, b1, b2, b3, vk13, vk14);
207
208
209 /* Other functional macros */
210
211 #define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
212
213 #define aes_clear_keys(nrounds) \
214         cmp nrounds, #12; \
215         CLEAR_REG(vk0); \
216         CLEAR_REG(vk1); \
217         CLEAR_REG(vk2); \
218         CLEAR_REG(vk3); \
219         CLEAR_REG(vk4); \
220         CLEAR_REG(vk5); \
221         CLEAR_REG(vk6); \
222         CLEAR_REG(vk7); \
223         CLEAR_REG(vk9); \
224         CLEAR_REG(vk8); \
225         CLEAR_REG(vk10); \
226         b.lo 1f; \
227         CLEAR_REG(vk11); \
228         CLEAR_REG(vk12); \
229         b.eq 1f; \
230         CLEAR_REG(vk13); \
231         CLEAR_REG(vk14); \
232 1:      ;
233
234
235 /*
236  * unsigned int _gcry_aes_enc_armv8_ce(void *keysched, byte *dst,
237  *                                     const byte *src,
238  *                                     unsigned int nrounds);
239  */
240 .align 3
241 .globl _gcry_aes_enc_armv8_ce
242 .type  _gcry_aes_enc_armv8_ce,%function;
243 _gcry_aes_enc_armv8_ce:
244   /* input:
245    *    x0: keysched
246    *    x1: dst
247    *    x2: src
248    *    w3: nrounds
249    */
250
251   aes_preload_keys(x0, w3);
252
253   ld1 {v0.16b}, [x2]
254
255   b.hi .Lenc1_256
256   b.eq .Lenc1_192
257
258 .Lenc1_128:
259   do_aes_one128(e, mc, v0, v0);
260
261 .Lenc1_tail:
262   CLEAR_REG(vk0)
263   CLEAR_REG(vk1)
264   CLEAR_REG(vk2)
265   CLEAR_REG(vk3)
266   CLEAR_REG(vk4)
267   CLEAR_REG(vk5)
268   CLEAR_REG(vk6)
269   CLEAR_REG(vk7)
270   CLEAR_REG(vk8)
271   CLEAR_REG(vk9)
272   CLEAR_REG(vk10)
273   st1 {v0.16b}, [x1]
274   CLEAR_REG(v0)
275
276   mov x0, #0
277   ret
278
279 .Lenc1_192:
280   do_aes_one192(e, mc, v0, v0);
281
282   CLEAR_REG(vk11)
283   CLEAR_REG(vk12)
284   b .Lenc1_tail
285
286 .Lenc1_256:
287   do_aes_one256(e, mc, v0, v0);
288
289   CLEAR_REG(vk11)
290   CLEAR_REG(vk12)
291   CLEAR_REG(vk13)
292   CLEAR_REG(vk14)
293   b .Lenc1_tail
294 .size _gcry_aes_enc_armv8_ce,.-_gcry_aes_enc_armv8_ce;
295
296
297 /*
298  * unsigned int _gcry_aes_dec_armv8_ce(void *keysched, byte *dst,
299  *                                     const byte *src,
300  *                                     unsigned int nrounds);
301  */
302 .align 3
303 .globl _gcry_aes_dec_armv8_ce
304 .type  _gcry_aes_dec_armv8_ce,%function;
305 _gcry_aes_dec_armv8_ce:
306   /* input:
307    *    x0: keysched
308    *    x1: dst
309    *    x2: src
310    *    w3: nrounds
311    */
312
313   aes_preload_keys(x0, w3);
314
315   ld1 {v0.16b}, [x2]
316
317   b.hi .Ldec1_256
318   b.eq .Ldec1_192
319
320 .Ldec1_128:
321   do_aes_one128(d, imc, v0, v0);
322
323 .Ldec1_tail:
324   CLEAR_REG(vk0)
325   CLEAR_REG(vk1)
326   CLEAR_REG(vk2)
327   CLEAR_REG(vk3)
328   CLEAR_REG(vk4)
329   CLEAR_REG(vk5)
330   CLEAR_REG(vk6)
331   CLEAR_REG(vk7)
332   CLEAR_REG(vk8)
333   CLEAR_REG(vk9)
334   CLEAR_REG(vk10)
335   st1 {v0.16b}, [x1]
336   CLEAR_REG(v0)
337
338   mov x0, #0
339   ret
340
341 .Ldec1_192:
342   do_aes_one192(d, imc, v0, v0);
343
344   CLEAR_REG(vk11)
345   CLEAR_REG(vk12)
346   b .Ldec1_tail
347
348 .Ldec1_256:
349   do_aes_one256(d, imc, v0, v0);
350
351   CLEAR_REG(vk11)
352   CLEAR_REG(vk12)
353   CLEAR_REG(vk13)
354   CLEAR_REG(vk14)
355   b .Ldec1_tail
356 .size _gcry_aes_dec_armv8_ce,.-_gcry_aes_dec_armv8_ce;
357
358
359 /*
360  * void _gcry_aes_cbc_enc_armv8_ce (const void *keysched,
361  *                                  unsigned char *outbuf,
362  *                                  const unsigned char *inbuf,
363  *                                  unsigned char *iv, size_t nblocks,
364  *                                  int cbc_mac, unsigned int nrounds);
365  */
366
367 .align 3
368 .globl _gcry_aes_cbc_enc_armv8_ce
369 .type  _gcry_aes_cbc_enc_armv8_ce,%function;
370 _gcry_aes_cbc_enc_armv8_ce:
371   /* input:
372    *    x0: keysched
373    *    x1: outbuf
374    *    x2: inbuf
375    *    x3: iv
376    *    x4: nblocks
377    *    w5: cbc_mac
378    *    w6: nrounds
379    */
380
381   cbz x4, .Lcbc_enc_skip
382
383   cmp w5, #0
384   ld1 {v1.16b}, [x3] /* load IV */
385   cset x5, eq
386
387   aes_preload_keys(x0, w6);
388   lsl x5, x5, #4
389
390   b.eq .Lcbc_enc_loop192
391   b.hi .Lcbc_enc_loop256
392
393 #define CBC_ENC(bits) \
394   .Lcbc_enc_loop##bits: \
395     ld1 {v0.16b}, [x2], #16; /* load plaintext */ \
396     eor v1.16b, v0.16b, v1.16b; \
397     sub x4, x4, #1; \
398     \
399     do_aes_one##bits(e, mc, v1, v1); \
400     \
401     st1 {v1.16b}, [x1], x5; /* store ciphertext */ \
402     \
403     cbnz x4, .Lcbc_enc_loop##bits; \
404     b .Lcbc_enc_done;
405
406   CBC_ENC(128)
407   CBC_ENC(192)
408   CBC_ENC(256)
409
410 #undef CBC_ENC
411
412 .Lcbc_enc_done:
413   aes_clear_keys(w6)
414
415   st1 {v1.16b}, [x3] /* store IV */
416
417   CLEAR_REG(v1)
418   CLEAR_REG(v0)
419
420 .Lcbc_enc_skip:
421   ret
422 .size _gcry_aes_cbc_enc_armv8_ce,.-_gcry_aes_cbc_enc_armv8_ce;
423
424 /*
425  * void _gcry_aes_cbc_dec_armv8_ce (const void *keysched,
426  *                                  unsigned char *outbuf,
427  *                                  const unsigned char *inbuf,
428  *                                  unsigned char *iv, unsigned int nrounds);
429  */
430
431 .align 3
432 .globl _gcry_aes_cbc_dec_armv8_ce
433 .type  _gcry_aes_cbc_dec_armv8_ce,%function;
434 _gcry_aes_cbc_dec_armv8_ce:
435   /* input:
436    *    x0: keysched
437    *    x1: outbuf
438    *    x2: inbuf
439    *    x3: iv
440    *    x4: nblocks
441    *    w5: nrounds
442    */
443
444   cbz x4, .Lcbc_dec_skip
445
446   ld1 {v0.16b}, [x3] /* load IV */
447
448   aes_preload_keys(x0, w5);
449
450   b.eq .Lcbc_dec_entry_192
451   b.hi .Lcbc_dec_entry_256
452
453 #define CBC_DEC(bits) \
454   .Lcbc_dec_entry_##bits: \
455     cmp x4, #4; \
456     b.lo .Lcbc_dec_loop_##bits; \
457     \
458   .Lcbc_dec_loop4_##bits: \
459     \
460     ld1 {v1.16b-v4.16b}, [x2], #64; /* load ciphertext */ \
461     sub x4, x4, #4; \
462     mov v5.16b, v1.16b; \
463     mov v6.16b, v2.16b; \
464     mov v7.16b, v3.16b; \
465     mov v16.16b, v4.16b; \
466     cmp x4, #4; \
467     \
468     do_aes_4_##bits(d, imc, v1, v2, v3, v4); \
469     \
470     eor v1.16b, v1.16b, v0.16b; \
471     eor v2.16b, v2.16b, v5.16b; \
472     st1 {v1.16b-v2.16b}, [x1], #32; /* store plaintext */ \
473     eor v3.16b, v3.16b, v6.16b; \
474     eor v4.16b, v4.16b, v7.16b; \
475     mov v0.16b, v16.16b; /* next IV */ \
476     st1 {v3.16b-v4.16b}, [x1], #32; /* store plaintext */ \
477     \
478     b.hs .Lcbc_dec_loop4_##bits; \
479     CLEAR_REG(v3); \
480     CLEAR_REG(v4); \
481     CLEAR_REG(v5); \
482     CLEAR_REG(v6); \
483     CLEAR_REG(v7); \
484     CLEAR_REG(v16); \
485     cbz x4, .Lcbc_dec_done; \
486     \
487   .Lcbc_dec_loop_##bits: \
488     ld1 {v1.16b}, [x2], #16; /* load ciphertext */ \
489     sub x4, x4, #1; \
490     mov v2.16b, v1.16b; \
491     \
492     do_aes_one##bits(d, imc, v1, v1); \
493     \
494     eor v1.16b, v1.16b, v0.16b; \
495     mov v0.16b, v2.16b; \
496     st1 {v1.16b}, [x1], #16; /* store plaintext */ \
497     \
498     cbnz x4, .Lcbc_dec_loop_##bits; \
499     b .Lcbc_dec_done;
500
501   CBC_DEC(128)
502   CBC_DEC(192)
503   CBC_DEC(256)
504
505 #undef CBC_DEC
506
507 .Lcbc_dec_done:
508   aes_clear_keys(w5)
509
510   st1 {v0.16b}, [x3] /* store IV */
511
512   CLEAR_REG(v0)
513   CLEAR_REG(v1)
514   CLEAR_REG(v2)
515
516 .Lcbc_dec_skip:
517   ret
518 .size _gcry_aes_cbc_dec_armv8_ce,.-_gcry_aes_cbc_dec_armv8_ce;
519
520
521 /*
522  * void _gcry_aes_ctr_enc_armv8_ce (const void *keysched,
523  *                                  unsigned char *outbuf,
524  *                                  const unsigned char *inbuf,
525  *                                  unsigned char *iv, unsigned int nrounds);
526  */
527
528 .align 3
529 .globl _gcry_aes_ctr_enc_armv8_ce
530 .type  _gcry_aes_ctr_enc_armv8_ce,%function;
531 _gcry_aes_ctr_enc_armv8_ce:
532   /* input:
533    *    r0: keysched
534    *    r1: outbuf
535    *    r2: inbuf
536    *    r3: iv
537    *    x4: nblocks
538    *    w5: nrounds
539    */
540
541   cbz x4, .Lctr_enc_skip
542
543   mov x6, #1
544   movi v16.16b, #0
545   mov v16.D[1], x6
546
547   /* load IV */
548   ldp x9, x10, [x3]
549   ld1 {v0.16b}, [x3]
550   rev x9, x9
551   rev x10, x10
552
553   aes_preload_keys(x0, w5);
554
555   b.eq .Lctr_enc_entry_192
556   b.hi .Lctr_enc_entry_256
557
558 #define CTR_ENC(bits) \
559   .Lctr_enc_entry_##bits: \
560     cmp x4, #4; \
561     b.lo .Lctr_enc_loop_##bits; \
562     \
563   .Lctr_enc_loop4_##bits: \
564     cmp x10, #0xfffffffffffffffc; \
565     sub x4, x4, #4; \
566     b.lo .Lctr_enc_loop4_##bits##_nocarry; \
567     \
568     adds x10, x10, #1; \
569     mov v1.16b, v0.16b; \
570     adc x9, x9, xzr; \
571     mov v2.D[1], x10; \
572     mov v2.D[0], x9; \
573     \
574     adds x10, x10, #1; \
575     rev64 v2.16b, v2.16b; \
576     adc x9, x9, xzr; \
577     mov v3.D[1], x10; \
578     mov v3.D[0], x9; \
579     \
580     adds x10, x10, #1; \
581     rev64 v3.16b, v3.16b; \
582     adc x9, x9, xzr; \
583     mov v4.D[1], x10; \
584     mov v4.D[0], x9; \
585     \
586     adds x10, x10, #1; \
587     rev64 v4.16b, v4.16b; \
588     adc x9, x9, xzr; \
589     mov v0.D[1], x10; \
590     mov v0.D[0], x9; \
591     rev64 v0.16b, v0.16b; \
592     \
593     b .Lctr_enc_loop4_##bits##_store_ctr; \
594     \
595   .Lctr_enc_loop4_##bits##_nocarry: \
596     \
597     add v3.2d, v16.2d, v16.2d; /* 2 */ \
598     rev64 v6.16b, v0.16b; \
599     add x10, x10, #4; \
600     add v4.2d, v3.2d, v16.2d;  /* 3 */ \
601     add v0.2d, v3.2d, v3.2d;   /* 4 */ \
602     rev64 v1.16b, v6.16b; \
603     add v2.2d, v6.2d, v16.2d; \
604     add v3.2d, v6.2d, v3.2d; \
605     add v4.2d, v6.2d, v4.2d; \
606     add v0.2d, v6.2d, v0.2d; \
607     rev64 v2.16b, v2.16b; \
608     rev64 v3.16b, v3.16b; \
609     rev64 v0.16b, v0.16b; \
610     rev64 v4.16b, v4.16b; \
611     \
612   .Lctr_enc_loop4_##bits##_store_ctr: \
613     \
614     st1 {v0.16b}, [x3]; \
615     cmp x4, #4; \
616     ld1 {v5.16b-v7.16b}, [x2], #48; /* preload ciphertext */ \
617     \
618     do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
619     \
620     eor v1.16b, v1.16b, v5.16b; \
621     ld1 {v5.16b}, [x2], #16; /* load ciphertext */ \
622     eor v2.16b, v2.16b, v6.16b; \
623     eor v3.16b, v3.16b, v7.16b; \
624     eor v4.16b, v4.16b, v5.16b; \
625     st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
626     \
627     b.hs .Lctr_enc_loop4_##bits; \
628     CLEAR_REG(v3); \
629     CLEAR_REG(v4); \
630     CLEAR_REG(v5); \
631     CLEAR_REG(v6); \
632     CLEAR_REG(v7); \
633     cbz x4, .Lctr_enc_done; \
634     \
635   .Lctr_enc_loop_##bits: \
636     \
637     adds x10, x10, #1; \
638     mov v1.16b, v0.16b; \
639     adc x9, x9, xzr; \
640     mov v0.D[1], x10; \
641     mov v0.D[0], x9; \
642     sub x4, x4, #1; \
643     ld1 {v2.16b}, [x2], #16; /* load ciphertext */ \
644     rev64 v0.16b, v0.16b; \
645     \
646     do_aes_one##bits(e, mc, v1, v1); \
647     \
648     eor v1.16b, v2.16b, v1.16b; \
649     st1 {v1.16b}, [x1], #16; /* store plaintext */ \
650     \
651     cbnz x4, .Lctr_enc_loop_##bits; \
652     b .Lctr_enc_done;
653
654   CTR_ENC(128)
655   CTR_ENC(192)
656   CTR_ENC(256)
657
658 #undef CTR_ENC
659
660 .Lctr_enc_done:
661   aes_clear_keys(w5)
662
663   st1 {v0.16b}, [x3] /* store IV */
664
665   CLEAR_REG(v0)
666   CLEAR_REG(v1)
667   CLEAR_REG(v2)
668
669 .Lctr_enc_skip:
670   ret
671
672 .size _gcry_aes_ctr_enc_armv8_ce,.-_gcry_aes_ctr_enc_armv8_ce;
673
674
675 /*
676  * void _gcry_aes_cfb_enc_armv8_ce (const void *keysched,
677  *                                  unsigned char *outbuf,
678  *                                  const unsigned char *inbuf,
679  *                                  unsigned char *iv, unsigned int nrounds);
680  */
681
682 .align 3
683 .globl _gcry_aes_cfb_enc_armv8_ce
684 .type  _gcry_aes_cfb_enc_armv8_ce,%function;
685 _gcry_aes_cfb_enc_armv8_ce:
686   /* input:
687    *    r0: keysched
688    *    r1: outbuf
689    *    r2: inbuf
690    *    r3: iv
691    *    x4: nblocks
692    *    w5: nrounds
693    */
694
695   cbz x4, .Lcfb_enc_skip
696
697   /* load IV */
698   ld1 {v0.16b}, [x3]
699
700   aes_preload_keys(x0, w5);
701
702   b.eq .Lcfb_enc_entry_192
703   b.hi .Lcfb_enc_entry_256
704
705 #define CFB_ENC(bits) \
706   .Lcfb_enc_entry_##bits: \
707   .Lcfb_enc_loop_##bits: \
708     ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
709     sub x4, x4, #1; \
710     \
711     do_aes_one##bits(e, mc, v0, v0); \
712     \
713     eor v0.16b, v1.16b, v0.16b; \
714     st1 {v0.16b}, [x1], #16; /* store ciphertext */ \
715     \
716     cbnz x4, .Lcfb_enc_loop_##bits; \
717     b .Lcfb_enc_done;
718
719   CFB_ENC(128)
720   CFB_ENC(192)
721   CFB_ENC(256)
722
723 #undef CFB_ENC
724
725 .Lcfb_enc_done:
726   aes_clear_keys(w5)
727
728   st1 {v0.16b}, [x3] /* store IV */
729
730   CLEAR_REG(v0)
731   CLEAR_REG(v1)
732
733 .Lcfb_enc_skip:
734   ret
735 .size _gcry_aes_cfb_enc_armv8_ce,.-_gcry_aes_cfb_enc_armv8_ce;
736
737
738 /*
739  * void _gcry_aes_cfb_dec_armv8_ce (const void *keysched,
740  *                                  unsigned char *outbuf,
741  *                                  const unsigned char *inbuf,
742  *                                  unsigned char *iv, unsigned int nrounds);
743  */
744
745 .align 3
746 .globl _gcry_aes_cfb_dec_armv8_ce
747 .type  _gcry_aes_cfb_dec_armv8_ce,%function;
748 _gcry_aes_cfb_dec_armv8_ce:
749   /* input:
750    *    r0: keysched
751    *    r1: outbuf
752    *    r2: inbuf
753    *    r3: iv
754    *    x4: nblocks
755    *    w5: nrounds
756    */
757
758   cbz x4, .Lcfb_dec_skip
759
760   /* load IV */
761   ld1 {v0.16b}, [x3]
762
763   aes_preload_keys(x0, w5);
764
765   b.eq .Lcfb_dec_entry_192
766   b.hi .Lcfb_dec_entry_256
767
768 #define CFB_DEC(bits) \
769   .Lcfb_dec_entry_##bits: \
770     cmp x4, #4; \
771     b.lo .Lcfb_dec_loop_##bits; \
772     \
773   .Lcfb_dec_loop4_##bits: \
774     \
775     ld1 {v2.16b-v4.16b}, [x2], #48; /* load ciphertext */ \
776     mov v1.16b, v0.16b; \
777     sub x4, x4, #4; \
778     cmp x4, #4; \
779     mov v5.16b, v2.16b; \
780     mov v6.16b, v3.16b; \
781     mov v7.16b, v4.16b; \
782     ld1 {v0.16b}, [x2], #16; /* load next IV / ciphertext */ \
783     \
784     do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
785     \
786     eor v1.16b, v1.16b, v5.16b; \
787     eor v2.16b, v2.16b, v6.16b; \
788     eor v3.16b, v3.16b, v7.16b; \
789     eor v4.16b, v4.16b, v0.16b; \
790     st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
791     \
792     b.hs .Lcfb_dec_loop4_##bits; \
793     CLEAR_REG(v3); \
794     CLEAR_REG(v4); \
795     CLEAR_REG(v5); \
796     CLEAR_REG(v6); \
797     CLEAR_REG(v7); \
798     cbz x4, .Lcfb_dec_done; \
799     \
800   .Lcfb_dec_loop_##bits: \
801     \
802     ld1 {v1.16b}, [x2], #16; /* load ciphertext */ \
803     \
804     sub x4, x4, #1; \
805     \
806     do_aes_one##bits(e, mc, v0, v0); \
807     \
808     eor v2.16b, v1.16b, v0.16b; \
809     mov v0.16b, v1.16b; \
810     st1 {v2.16b}, [x1], #16; /* store plaintext */ \
811     \
812     cbnz x4, .Lcfb_dec_loop_##bits; \
813     b .Lcfb_dec_done;
814
815   CFB_DEC(128)
816   CFB_DEC(192)
817   CFB_DEC(256)
818
819 #undef CFB_DEC
820
821 .Lcfb_dec_done:
822   aes_clear_keys(w5)
823
824   st1 {v0.16b}, [x3] /* store IV */
825
826   CLEAR_REG(v0)
827   CLEAR_REG(v1)
828   CLEAR_REG(v2)
829
830 .Lcfb_dec_skip:
831   ret
832 .size _gcry_aes_cfb_dec_armv8_ce,.-_gcry_aes_cfb_dec_armv8_ce;
833
834
835 /*
836  * void _gcry_aes_ocb_enc_armv8_ce (const void *keysched,
837  *                                  unsigned char *outbuf,
838  *                                  const unsigned char *inbuf,
839  *                                  unsigned char *offset,
840  *                                  unsigned char *checksum,
841  *                                  unsigned char *L_table,
842  *                                  size_t nblocks,
843  *                                  unsigned int nrounds,
844  *                                  unsigned int blkn);
845  */
846
847 .align 3
848 .globl _gcry_aes_ocb_enc_armv8_ce
849 .type  _gcry_aes_ocb_enc_armv8_ce,%function;
850 _gcry_aes_ocb_enc_armv8_ce:
851   /* input:
852    *    x0: keysched
853    *    x1: outbuf
854    *    x2: inbuf
855    *    x3: offset
856    *    x4: checksum
857    *    x5: Ltable
858    *    x6: nblocks (0 < nblocks <= 32)
859    *    w7: nrounds
860    *    %st+0: blkn => w12
861    */
862
863   ldr w12, [sp]
864   ld1 {v0.16b}, [x3] /* load offset */
865   ld1 {v16.16b}, [x4] /* load checksum */
866
867   aes_preload_keys(x0, w7);
868
869   b.eq .Locb_enc_entry_192
870   b.hi .Locb_enc_entry_256
871
872 #define OCB_ENC(bits, ...) \
873   .Locb_enc_entry_##bits: \
874     cmp x6, #4; \
875     add x12, x12, #1; \
876     b.lo .Locb_enc_loop_##bits; \
877     \
878   .Locb_enc_loop4_##bits: \
879     \
880     /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
881     /* Checksum_i = Checksum_{i-1} xor P_i  */ \
882     /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */ \
883     \
884     add w9, w12, #1; \
885     add w10, w12, #2; \
886     add w11, w12, #3; \
887     rbit w8, w12; \
888     add w12, w12, #4; \
889     rbit w9, w9; \
890     rbit w10, w10; \
891     rbit w11, w11; \
892     clz w8, w8; /* ntz(i+0) */ \
893     clz w9, w9; /* ntz(i+1) */ \
894     clz w10, w10; /* ntz(i+2) */ \
895     clz w11, w11; /* ntz(i+3) */ \
896     add x8, x5, x8, lsl #4; \
897     ld1 {v1.16b-v4.16b}, [x2], #64;   /* load P_i+<0-3> */ \
898     add x9, x5, x9, lsl #4; \
899     add x10, x5, x10, lsl #4; \
900     add x11, x5, x11, lsl #4; \
901     \
902     sub x6, x6, #4; \
903     \
904     ld1 {v5.16b}, [x8];               /* load L_{ntz(i+0)} */ \
905     eor v16.16b, v16.16b, v1.16b;     /* Checksum_i+0 */ \
906     ld1 {v6.16b}, [x9];               /* load L_{ntz(i+1)} */ \
907     eor v16.16b, v16.16b, v2.16b;     /* Checksum_i+1 */ \
908     ld1 {v7.16b}, [x10];              /* load L_{ntz(i+2)} */ \
909     eor v16.16b, v16.16b, v3.16b;     /* Checksum_i+2 */ \
910     eor v5.16b, v5.16b, v0.16b;       /* Offset_i+0 */ \
911     ld1 {v0.16b}, [x11];              /* load L_{ntz(i+3)} */ \
912     eor v16.16b, v16.16b, v4.16b;     /* Checksum_i+3 */ \
913     eor v6.16b, v6.16b, v5.16b;       /* Offset_i+1 */ \
914     eor v1.16b, v1.16b, v5.16b;       /* P_i+0 xor Offset_i+0 */ \
915     eor v7.16b, v7.16b, v6.16b;       /* Offset_i+2 */ \
916     eor v2.16b, v2.16b, v6.16b;       /* P_i+1 xor Offset_i+1 */ \
917     eor v0.16b, v0.16b, v7.16b;       /* Offset_i+3 */ \
918     cmp x6, #4; \
919     eor v3.16b, v3.16b, v7.16b;       /* P_i+2 xor Offset_i+2 */ \
920     eor v4.16b, v4.16b, v0.16b;       /* P_i+3 xor Offset_i+3 */ \
921     \
922     do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
923     \
924     eor v1.16b, v1.16b, v5.16b;       /* xor Offset_i+0 */ \
925     eor v2.16b, v2.16b, v6.16b;       /* xor Offset_i+1 */ \
926     eor v3.16b, v3.16b, v7.16b;       /* xor Offset_i+2 */ \
927     eor v4.16b, v4.16b, v0.16b;       /* xor Offset_i+3 */ \
928     st1 {v1.16b-v4.16b}, [x1], #64; \
929     \
930     b.hs .Locb_enc_loop4_##bits; \
931     CLEAR_REG(v3); \
932     CLEAR_REG(v4); \
933     CLEAR_REG(v5); \
934     CLEAR_REG(v6); \
935     CLEAR_REG(v7); \
936     cbz x6, .Locb_enc_done; \
937     \
938   .Locb_enc_loop_##bits: \
939     \
940     /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
941     /* Checksum_i = Checksum_{i-1} xor P_i  */ \
942     /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */ \
943     \
944     rbit x8, x12; \
945     add x12, x12, #1; \
946     clz x8, x8; /* ntz(i) */ \
947     add x8, x5, x8, lsl #4; \
948     \
949     ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
950     ld1 {v2.16b}, [x8]; /* load L_{ntz(i)} */ \
951     sub x6, x6, #1; \
952     eor v0.16b, v0.16b, v2.16b; \
953     eor v16.16b, v16.16b, v1.16b; \
954     eor v1.16b, v1.16b, v0.16b; \
955     \
956     do_aes_one##bits(e, mc, v1, v1); \
957     \
958     eor v1.16b, v1.16b, v0.16b; \
959     st1 {v1.16b}, [x1], #16; /* store ciphertext */ \
960     \
961     cbnz x6, .Locb_enc_loop_##bits; \
962     b .Locb_enc_done;
963
964   OCB_ENC(128)
965   OCB_ENC(192)
966   OCB_ENC(256)
967
968 #undef OCB_ENC
969
970 .Locb_enc_done:
971   aes_clear_keys(w7)
972
973   st1 {v16.16b}, [x4] /* store checksum */
974   st1 {v0.16b}, [x3] /* store offset */
975
976   CLEAR_REG(v0)
977   CLEAR_REG(v1)
978   CLEAR_REG(v2)
979   CLEAR_REG(v16)
980
981   ret
982 .size _gcry_aes_ocb_enc_armv8_ce,.-_gcry_aes_ocb_enc_armv8_ce;
983
984
985 /*
986  * void _gcry_aes_ocb_dec_armv8_ce (const void *keysched,
987  *                                  unsigned char *outbuf,
988  *                                  const unsigned char *inbuf,
989  *                                  unsigned char *offset,
990  *                                  unsigned char *checksum,
991  *                                  unsigned char *L_table,
992  *                                  size_t nblocks,
993  *                                  unsigned int nrounds,
994  *                                  unsigned int blkn);
995  */
996
997 .align 3
998 .globl _gcry_aes_ocb_dec_armv8_ce
999 .type  _gcry_aes_ocb_dec_armv8_ce,%function;
1000 _gcry_aes_ocb_dec_armv8_ce:
1001   /* input:
1002    *    x0: keysched
1003    *    x1: outbuf
1004    *    x2: inbuf
1005    *    x3: offset
1006    *    x4: checksum
1007    *    x5: Ltable
1008    *    x6: nblocks (0 < nblocks <= 32)
1009    *    w7: nrounds
1010    *    %st+0: blkn => w12
1011    */
1012
1013   ldr w12, [sp]
1014   ld1 {v0.16b}, [x3] /* load offset */
1015   ld1 {v16.16b}, [x4] /* load checksum */
1016
1017   aes_preload_keys(x0, w7);
1018
1019   b.eq .Locb_dec_entry_192
1020   b.hi .Locb_dec_entry_256
1021
1022 #define OCB_DEC(bits) \
1023   .Locb_dec_entry_##bits: \
1024     cmp x6, #4; \
1025     add w12, w12, #1; \
1026     b.lo .Locb_dec_loop_##bits; \
1027     \
1028   .Locb_dec_loop4_##bits: \
1029     \
1030     /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
1031     /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */ \
1032     /* Checksum_i = Checksum_{i-1} xor P_i  */ \
1033     \
1034     add w9, w12, #1; \
1035     add w10, w12, #2; \
1036     add w11, w12, #3; \
1037     rbit w8, w12; \
1038     add w12, w12, #4; \
1039     rbit w9, w9; \
1040     rbit w10, w10; \
1041     rbit w11, w11; \
1042     clz w8, w8; /* ntz(i+0) */ \
1043     clz w9, w9; /* ntz(i+1) */ \
1044     clz w10, w10; /* ntz(i+2) */ \
1045     clz w11, w11; /* ntz(i+3) */ \
1046     add x8, x5, x8, lsl #4; \
1047     ld1 {v1.16b-v4.16b}, [x2], #64;   /* load C_i+<0-3> */ \
1048     add x9, x5, x9, lsl #4; \
1049     add x10, x5, x10, lsl #4; \
1050     add x11, x5, x11, lsl #4; \
1051     \
1052     sub x6, x6, #4; \
1053     \
1054     ld1 {v5.16b}, [x8];               /* load L_{ntz(i+0)} */ \
1055     ld1 {v6.16b}, [x9];               /* load L_{ntz(i+1)} */ \
1056     ld1 {v7.16b}, [x10];              /* load L_{ntz(i+2)} */ \
1057     eor v5.16b, v5.16b, v0.16b;       /* Offset_i+0 */ \
1058     ld1 {v0.16b}, [x11];              /* load L_{ntz(i+3)} */ \
1059     eor v6.16b, v6.16b, v5.16b;       /* Offset_i+1 */ \
1060     eor v1.16b, v1.16b, v5.16b;       /* C_i+0 xor Offset_i+0 */ \
1061     eor v7.16b, v7.16b, v6.16b;       /* Offset_i+2 */ \
1062     eor v2.16b, v2.16b, v6.16b;       /* C_i+1 xor Offset_i+1 */ \
1063     eor v0.16b, v0.16b, v7.16b;       /* Offset_i+3 */ \
1064     cmp x6, #4; \
1065     eor v3.16b, v3.16b, v7.16b;       /* C_i+2 xor Offset_i+2 */ \
1066     eor v4.16b, v4.16b, v0.16b;       /* C_i+3 xor Offset_i+3 */ \
1067     \
1068     do_aes_4_##bits(d, imc, v1, v2, v3, v4); \
1069     \
1070     eor v1.16b, v1.16b, v5.16b;       /* xor Offset_i+0 */ \
1071     eor v2.16b, v2.16b, v6.16b;       /* xor Offset_i+1 */ \
1072     eor v16.16b, v16.16b, v1.16b;     /* Checksum_i+0 */ \
1073     eor v3.16b, v3.16b, v7.16b;       /* xor Offset_i+2 */ \
1074     eor v16.16b, v16.16b, v2.16b;     /* Checksum_i+1 */ \
1075     eor v4.16b, v4.16b, v0.16b;       /* xor Offset_i+3 */ \
1076     eor v16.16b, v16.16b, v3.16b;     /* Checksum_i+2 */ \
1077     eor v16.16b, v16.16b, v4.16b;     /* Checksum_i+3 */ \
1078     st1 {v1.16b-v4.16b}, [x1], #64; \
1079     \
1080     b.hs .Locb_dec_loop4_##bits; \
1081     CLEAR_REG(v3); \
1082     CLEAR_REG(v4); \
1083     CLEAR_REG(v5); \
1084     CLEAR_REG(v6); \
1085     CLEAR_REG(v7); \
1086     cbz x6, .Locb_dec_done; \
1087     \
1088   .Locb_dec_loop_##bits: \
1089     \
1090     /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
1091     /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */ \
1092     /* Checksum_i = Checksum_{i-1} xor P_i  */ \
1093     \
1094     rbit w8, w12; \
1095     add w12, w12, #1; \
1096     clz w8, w8; /* ntz(i) */ \
1097     add x8, x5, x8, lsl #4; \
1098     \
1099     ld1 {v1.16b}, [x2], #16; /* load ciphertext */ \
1100     ld1 {v2.16b}, [x8]; /* load L_{ntz(i)} */ \
1101     sub x6, x6, #1; \
1102     eor v0.16b, v0.16b, v2.16b; \
1103     eor v1.16b, v1.16b, v0.16b; \
1104     \
1105     do_aes_one##bits(d, imc, v1, v1) \
1106     \
1107     eor v1.16b, v1.16b, v0.16b; \
1108     st1 {v1.16b}, [x1], #16; /* store plaintext */ \
1109     eor v16.16b, v16.16b, v1.16b; \
1110     \
1111     cbnz x6, .Locb_dec_loop_##bits; \
1112     b .Locb_dec_done;
1113
1114   OCB_DEC(128)
1115   OCB_DEC(192)
1116   OCB_DEC(256)
1117
1118 #undef OCB_DEC
1119
1120 .Locb_dec_done:
1121   aes_clear_keys(w7)
1122
1123   st1 {v16.16b}, [x4] /* store checksum */
1124   st1 {v0.16b}, [x3] /* store offset */
1125
1126   CLEAR_REG(v0)
1127   CLEAR_REG(v1)
1128   CLEAR_REG(v2)
1129   CLEAR_REG(v16)
1130
1131   ret
1132 .size _gcry_aes_ocb_dec_armv8_ce,.-_gcry_aes_ocb_dec_armv8_ce;
1133
1134
1135 /*
1136  * void _gcry_aes_ocb_auth_armv8_ce (const void *keysched,
1137  *                                   const unsigned char *abuf,
1138  *                                   unsigned char *offset,
1139  *                                   unsigned char *checksum,
1140  *                                   unsigned char *L_table,
1141  *                                   size_t nblocks,
1142  *                                   unsigned int nrounds,
1143  *                                   unsigned int blkn);
1144  */
1145
1146 .align 3
1147 .globl _gcry_aes_ocb_auth_armv8_ce
1148 .type  _gcry_aes_ocb_auth_armv8_ce,%function;
1149 _gcry_aes_ocb_auth_armv8_ce:
1150   /* input:
1151    *    x0: keysched
1152    *    x1: abuf
1153    *    x2: offset => x3
1154    *    x3: checksum => x4
1155    *    x4: Ltable => x5
1156    *    x5: nblocks => x6  (0 < nblocks <= 32)
1157    *    w6: nrounds => w7
1158    *    w7: blkn => w12
1159    */
1160   mov x12, x7
1161   mov x7, x6
1162   mov x6, x5
1163   mov x5, x4
1164   mov x4, x3
1165   mov x3, x2
1166
1167   aes_preload_keys(x0, w7);
1168
1169   ld1 {v0.16b}, [x3] /* load offset */
1170   ld1 {v16.16b}, [x4] /* load checksum */
1171
1172   beq .Locb_auth_entry_192
1173   bhi .Locb_auth_entry_256
1174
1175 #define OCB_AUTH(bits) \
1176   .Locb_auth_entry_##bits: \
1177     cmp x6, #4; \
1178     add w12, w12, #1; \
1179     b.lo .Locb_auth_loop_##bits; \
1180     \
1181   .Locb_auth_loop4_##bits: \
1182     \
1183     /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
1184     /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */ \
1185     \
1186     add w9, w12, #1; \
1187     add w10, w12, #2; \
1188     add w11, w12, #3; \
1189     rbit w8, w12; \
1190     add w12, w12, #4; \
1191     rbit w9, w9; \
1192     rbit w10, w10; \
1193     rbit w11, w11; \
1194     clz w8, w8; /* ntz(i+0) */ \
1195     clz w9, w9; /* ntz(i+1) */ \
1196     clz w10, w10; /* ntz(i+2) */ \
1197     clz w11, w11; /* ntz(i+3) */ \
1198     add x8, x5, x8, lsl #4; \
1199     ld1 {v1.16b-v4.16b}, [x1], #64;   /* load A_i+<0-3> */ \
1200     add x9, x5, x9, lsl #4; \
1201     add x10, x5, x10, lsl #4; \
1202     add x11, x5, x11, lsl #4; \
1203     \
1204     sub x6, x6, #4; \
1205     \
1206     ld1 {v5.16b}, [x8];               /* load L_{ntz(i+0)} */ \
1207     ld1 {v6.16b}, [x9];               /* load L_{ntz(i+1)} */ \
1208     ld1 {v7.16b}, [x10];              /* load L_{ntz(i+2)} */ \
1209     eor v5.16b, v5.16b, v0.16b;       /* Offset_i+0 */ \
1210     ld1 {v0.16b}, [x11];              /* load L_{ntz(i+3)} */ \
1211     eor v6.16b, v6.16b, v5.16b;       /* Offset_i+1 */ \
1212     eor v1.16b, v1.16b, v5.16b;       /* A_i+0 xor Offset_i+0 */ \
1213     eor v7.16b, v7.16b, v6.16b;       /* Offset_i+2 */ \
1214     eor v2.16b, v2.16b, v6.16b;       /* A_i+1 xor Offset_i+1 */ \
1215     eor v0.16b, v0.16b, v7.16b;       /* Offset_i+3 */ \
1216     cmp x6, #4; \
1217     eor v3.16b, v3.16b, v7.16b;       /* A_i+2 xor Offset_i+2 */ \
1218     eor v4.16b, v4.16b, v0.16b;       /* A_i+3 xor Offset_i+3 */ \
1219     \
1220     do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
1221     \
1222     eor v1.16b, v1.16b, v2.16b; \
1223     eor v16.16b, v16.16b, v3.16b; \
1224     eor v1.16b, v1.16b, v4.16b; \
1225     eor v16.16b, v16.16b, v1.16b; \
1226     \
1227     b.hs .Locb_auth_loop4_##bits; \
1228     CLEAR_REG(v3); \
1229     CLEAR_REG(v4); \
1230     CLEAR_REG(v5); \
1231     CLEAR_REG(v6); \
1232     CLEAR_REG(v7); \
1233     cbz x6, .Locb_auth_done; \
1234     \
1235   .Locb_auth_loop_##bits: \
1236     \
1237     /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
1238     /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */ \
1239     \
1240     rbit w8, w12; \
1241     add w12, w12, #1; \
1242     clz w8, w8; /* ntz(i) */ \
1243     add x8, x5, x8, lsl #4; \
1244     \
1245     ld1 {v1.16b}, [x1], #16; /* load aadtext */ \
1246     ld1 {v2.16b}, [x8]; /* load L_{ntz(i)} */ \
1247     sub x6, x6, #1; \
1248     eor v0.16b, v0.16b, v2.16b; \
1249     eor v1.16b, v1.16b, v0.16b; \
1250     \
1251     do_aes_one##bits(e, mc, v1, v1) \
1252     \
1253     eor v16.16b, v16.16b, v1.16b; \
1254     \
1255     cbnz x6, .Locb_auth_loop_##bits; \
1256     b .Locb_auth_done;
1257
1258   OCB_AUTH(128)
1259   OCB_AUTH(192)
1260   OCB_AUTH(256)
1261
1262 #undef OCB_AUTH
1263
1264 .Locb_auth_done:
1265   aes_clear_keys(w7)
1266
1267   st1 {v16.16b}, [x4] /* store checksum */
1268   st1 {v0.16b}, [x3] /* store offset */
1269
1270   CLEAR_REG(v0)
1271   CLEAR_REG(v1)
1272   CLEAR_REG(v2)
1273   CLEAR_REG(v16)
1274
1275   ret
1276 .size _gcry_aes_ocb_auth_armv8_ce,.-_gcry_aes_ocb_auth_armv8_ce;
1277
1278
1279 /*
1280  * void _gcry_aes_xts_enc_armv8_ce (const void *keysched,
1281  *                                  unsigned char *outbuf,
1282  *                                  const unsigned char *inbuf,
1283  *                                  unsigned char *tweak, unsigned int nrounds);
1284  */
1285
1286 .align 3
1287 .globl _gcry_aes_xts_enc_armv8_ce
1288 .type  _gcry_aes_xts_enc_armv8_ce,%function;
1289 _gcry_aes_xts_enc_armv8_ce:
1290   /* input:
1291    *    r0: keysched
1292    *    r1: outbuf
1293    *    r2: inbuf
1294    *    r3: tweak
1295    *    x4: nblocks
1296    *    w5: nrounds
1297    */
1298
1299   cbz x4, .Lxts_enc_skip
1300
1301   /* load tweak */
1302   ld1 {v0.16b}, [x3]
1303
1304   /* load gfmul mask */
1305   mov x6, #0x87
1306   mov x7, #0x01
1307   mov v16.D[0], x6
1308   mov v16.D[1], x7
1309
1310   aes_preload_keys(x0, w5);
1311
1312   b.eq .Lxts_enc_entry_192
1313   b.hi .Lxts_enc_entry_256
1314
1315 #define XTS_ENC(bits) \
1316   .Lxts_enc_entry_##bits: \
1317     cmp x4, #4; \
1318     b.lo .Lxts_enc_loop_##bits; \
1319     \
1320   .Lxts_enc_loop4_##bits: \
1321     \
1322     ext v4.16b, v0.16b, v0.16b, #8; \
1323     \
1324     sshr v2.2d, v4.2d, #63; \
1325     add v5.2d, v0.2d, v0.2d; \
1326     and v2.16b, v2.16b, v16.16b; \
1327     add v4.2d, v4.2d, v4.2d; \
1328     eor v5.16b, v5.16b, v2.16b; \
1329     \
1330     sshr v2.2d, v4.2d, #63; \
1331     add v6.2d, v5.2d, v5.2d; \
1332     and v2.16b, v2.16b, v16.16b; \
1333     add v4.2d, v4.2d, v4.2d; \
1334     eor v6.16b, v6.16b, v2.16b; \
1335     \
1336     sshr v2.2d, v4.2d, #63; \
1337     add v7.2d, v6.2d, v6.2d; \
1338     and v2.16b, v2.16b, v16.16b; \
1339     add v4.2d, v4.2d, v4.2d; \
1340     eor v7.16b, v7.16b, v2.16b; \
1341     \
1342     sshr v2.2d, v4.2d, #63; \
1343     add v3.2d, v7.2d, v7.2d; \
1344     and v2.16b, v2.16b, v16.16b; \
1345     add v4.2d, v4.2d, v4.2d; \
1346     eor v3.16b, v3.16b, v2.16b; \
1347     ld1 {v1.16b-v2.16b}, [x2], #32; /* load plaintext */ \
1348     st1 {v3.16b}, [x3]; \
1349     sub x4, x4, #4; \
1350     eor v1.16b, v1.16b, v0.16b; \
1351     \
1352     ld1 {v3.16b-v4.16b}, [x2], #32; /* load plaintext */ \
1353     cmp x4, #4; \
1354     eor v2.16b, v2.16b, v5.16b; \
1355     eor v3.16b, v3.16b, v6.16b; \
1356     eor v4.16b, v4.16b, v7.16b; \
1357     \
1358     do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
1359     \
1360     eor v1.16b, v1.16b, v0.16b; \
1361     ld1 {v0.16b}, [x3]; \
1362     eor v2.16b, v2.16b, v5.16b; \
1363     eor v3.16b, v3.16b, v6.16b; \
1364     eor v4.16b, v4.16b, v7.16b; \
1365     st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
1366     \
1367     b.hs .Lxts_enc_loop4_##bits; \
1368     CLEAR_REG(v3); \
1369     CLEAR_REG(v4); \
1370     CLEAR_REG(v5); \
1371     CLEAR_REG(v6); \
1372     CLEAR_REG(v7); \
1373     cbz x4, .Lxts_enc_done; \
1374     \
1375   .Lxts_enc_loop_##bits: \
1376     \
1377     ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
1378     ext v3.16b, v0.16b, v0.16b, #8; \
1379     mov v2.16b, v0.16b; \
1380     sshr v3.2d, v3.2d, #63; \
1381     add v0.2d, v0.2d, v0.2d; \
1382     and v3.16b, v3.16b, v16.16b; \
1383     eor v1.16b, v1.16b, v2.16b; \
1384     eor v0.16b, v0.16b, v3.16b; \
1385     sub x4, x4, #1; \
1386     \
1387     do_aes_one##bits(e, mc, v1, v1); \
1388     \
1389     eor v1.16b, v1.16b, v2.16b; \
1390     st1 {v1.16b}, [x1], #16; /* store ciphertext */ \
1391     \
1392     cbnz x4, .Lxts_enc_loop_##bits; \
1393     b .Lxts_enc_done;
1394
1395   XTS_ENC(128)
1396   XTS_ENC(192)
1397   XTS_ENC(256)
1398
1399 #undef XTS_ENC
1400
1401 .Lxts_enc_done:
1402   aes_clear_keys(w5)
1403
1404   st1 {v0.16b}, [x3] /* store tweak */
1405
1406   CLEAR_REG(v0)
1407   CLEAR_REG(v1)
1408   CLEAR_REG(v2)
1409
1410 .Lxts_enc_skip:
1411   ret
1412
1413 .size _gcry_aes_xts_enc_armv8_ce,.-_gcry_aes_xts_enc_armv8_ce;
1414
1415
1416 /*
1417  * void _gcry_aes_xts_dec_armv8_ce (const void *keysched,
1418  *                                  unsigned char *outbuf,
1419  *                                  const unsigned char *inbuf,
1420  *                                  unsigned char *tweak, unsigned int nrounds);
1421  */
1422
1423 .align 3
1424 .globl _gcry_aes_xts_dec_armv8_ce
1425 .type  _gcry_aes_xts_dec_armv8_ce,%function;
1426 _gcry_aes_xts_dec_armv8_ce:
1427   /* input:
1428    *    r0: keysched
1429    *    r1: outbuf
1430    *    r2: inbuf
1431    *    r3: tweak
1432    *    x4: nblocks
1433    *    w5: nrounds
1434    */
1435
1436   cbz x4, .Lxts_dec_skip
1437
1438   /* load tweak */
1439   ld1 {v0.16b}, [x3]
1440
1441   /* load gfmul mask */
1442   mov x6, #0x87
1443   mov x7, #0x01
1444   mov v16.D[0], x6
1445   mov v16.D[1], x7
1446
1447   aes_preload_keys(x0, w5);
1448
1449   b.eq .Lxts_dec_entry_192
1450   b.hi .Lxts_dec_entry_256
1451
1452 #define XTS_DEC(bits) \
1453   .Lxts_dec_entry_##bits: \
1454     cmp x4, #4; \
1455     b.lo .Lxts_dec_loop_##bits; \
1456     \
1457   .Lxts_dec_loop4_##bits: \
1458     \
1459     ext v4.16b, v0.16b, v0.16b, #8; \
1460     \
1461     sshr v2.2d, v4.2d, #63; \
1462     add v5.2d, v0.2d, v0.2d; \
1463     and v2.16b, v2.16b, v16.16b; \
1464     add v4.2d, v4.2d, v4.2d; \
1465     eor v5.16b, v5.16b, v2.16b; \
1466     \
1467     sshr v2.2d, v4.2d, #63; \
1468     add v6.2d, v5.2d, v5.2d; \
1469     and v2.16b, v2.16b, v16.16b; \
1470     add v4.2d, v4.2d, v4.2d; \
1471     eor v6.16b, v6.16b, v2.16b; \
1472     \
1473     sshr v2.2d, v4.2d, #63; \
1474     add v7.2d, v6.2d, v6.2d; \
1475     and v2.16b, v2.16b, v16.16b; \
1476     add v4.2d, v4.2d, v4.2d; \
1477     eor v7.16b, v7.16b, v2.16b; \
1478     \
1479     sshr v2.2d, v4.2d, #63; \
1480     add v3.2d, v7.2d, v7.2d; \
1481     and v2.16b, v2.16b, v16.16b; \
1482     add v4.2d, v4.2d, v4.2d; \
1483     eor v3.16b, v3.16b, v2.16b; \
1484     ld1 {v1.16b-v2.16b}, [x2], #32; /* load plaintext */ \
1485     st1 {v3.16b}, [x3]; \
1486     sub x4, x4, #4; \
1487     eor v1.16b, v1.16b, v0.16b; \
1488     \
1489     ld1 {v3.16b-v4.16b}, [x2], #32; /* load plaintext */ \
1490     cmp x4, #4; \
1491     eor v2.16b, v2.16b, v5.16b; \
1492     eor v3.16b, v3.16b, v6.16b; \
1493     eor v4.16b, v4.16b, v7.16b; \
1494     \
1495     do_aes_4_##bits(d, imc, v1, v2, v3, v4); \
1496     \
1497     eor v1.16b, v1.16b, v0.16b; \
1498     ld1 {v0.16b}, [x3]; \
1499     eor v2.16b, v2.16b, v5.16b; \
1500     eor v3.16b, v3.16b, v6.16b; \
1501     eor v4.16b, v4.16b, v7.16b; \
1502     st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
1503     \
1504     b.hs .Lxts_dec_loop4_##bits; \
1505     CLEAR_REG(v3); \
1506     CLEAR_REG(v4); \
1507     CLEAR_REG(v5); \
1508     CLEAR_REG(v6); \
1509     CLEAR_REG(v7); \
1510     cbz x4, .Lxts_dec_done; \
1511     \
1512   .Lxts_dec_loop_##bits: \
1513     \
1514     ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
1515     ext v3.16b, v0.16b, v0.16b, #8; \
1516     mov v2.16b, v0.16b; \
1517     sshr v3.2d, v3.2d, #63; \
1518     add v0.2d, v0.2d, v0.2d; \
1519     and v3.16b, v3.16b, v16.16b; \
1520     eor v1.16b, v1.16b, v2.16b; \
1521     eor v0.16b, v0.16b, v3.16b; \
1522     sub x4, x4, #1; \
1523     \
1524     do_aes_one##bits(d, imc, v1, v1); \
1525     \
1526     eor v1.16b, v1.16b, v2.16b; \
1527     st1 {v1.16b}, [x1], #16; /* store ciphertext */ \
1528     \
1529     cbnz x4, .Lxts_dec_loop_##bits; \
1530     b .Lxts_dec_done;
1531
1532   XTS_DEC(128)
1533   XTS_DEC(192)
1534   XTS_DEC(256)
1535
1536 #undef XTS_DEC
1537
1538 .Lxts_dec_done:
1539   aes_clear_keys(w5)
1540
1541   st1 {v0.16b}, [x3] /* store tweak */
1542
1543   CLEAR_REG(v0)
1544   CLEAR_REG(v1)
1545   CLEAR_REG(v2)
1546
1547 .Lxts_dec_skip:
1548   ret
1549
1550 .size _gcry_aes_xts_dec_armv8_ce,.-_gcry_aes_xts_dec_armv8_ce;
1551
1552
1553 /*
1554  * u32 _gcry_aes_sbox4_armv8_ce(u32 in4b);
1555  */
1556 .align 3
1557 .globl _gcry_aes_sbox4_armv8_ce
1558 .type  _gcry_aes_sbox4_armv8_ce,%function;
1559 _gcry_aes_sbox4_armv8_ce:
1560   /* See "Gouvêa, C. P. L. & López, J. Implementing GCM on ARMv8. Topics in
1561    * Cryptology — CT-RSA 2015" for details.
1562    */
1563   movi v0.16b, #0x52
1564   movi v1.16b, #0
1565   mov v0.S[0], w0
1566   aese v0.16b, v1.16b
1567   addv s0, v0.4s
1568   mov w0, v0.S[0]
1569   CLEAR_REG(v0)
1570   ret
1571 .size _gcry_aes_sbox4_armv8_ce,.-_gcry_aes_sbox4_armv8_ce;
1572
1573
1574 /*
1575  * void _gcry_aes_invmixcol_armv8_ce(void *dst, const void *src);
1576  */
1577 .align 3
1578 .globl _gcry_aes_invmixcol_armv8_ce
1579 .type  _gcry_aes_invmixcol_armv8_ce,%function;
1580 _gcry_aes_invmixcol_armv8_ce:
1581   ld1 {v0.16b}, [x1]
1582   aesimc v0.16b, v0.16b
1583   st1 {v0.16b}, [x0]
1584   CLEAR_REG(v0)
1585   ret
1586 .size _gcry_aes_invmixcol_armv8_ce,.-_gcry_aes_invmixcol_armv8_ce;
1587
1588 #endif