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