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