pkgconfig: Fix libgcrypt.pc.
[libgcrypt.git] / cipher / rijndael-aarch64.S
1 /* rijndael-aarch64.S  -  ARMv8/AArch64 assembly implementation of AES cipher
2  *
3  * Copyright (C) 2016 Jussi Kivilinna <jussi.kivilinna@iki.fi>
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "asm-common-aarch64.h"
22
23 #if defined(__AARCH64EL__)
24 #ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS
25
26 .text
27
28 /* register macros */
29 #define CTX     x0
30 #define RDST    x1
31 #define RSRC    x2
32 #define NROUNDS w3
33 #define RTAB    x4
34 #define RMASK   w5
35
36 #define RA      w8
37 #define RB      w9
38 #define RC      w10
39 #define RD      w11
40
41 #define RNA     w12
42 #define RNB     w13
43 #define RNC     w14
44 #define RND     w15
45
46 #define RT0     w6
47 #define RT1     w7
48 #define RT2     w16
49 #define xRT0    x6
50 #define xRT1    x7
51 #define xRT2    x16
52
53 #define xw8     x8
54 #define xw9     x9
55 #define xw10    x10
56 #define xw11    x11
57
58 #define xw12    x12
59 #define xw13    x13
60 #define xw14    x14
61 #define xw15    x15
62
63 /***********************************************************************
64  * ARMv8/AArch64 assembly implementation of the AES cipher
65  ***********************************************************************/
66 #define preload_first_key(round, ra) \
67         ldr ra, [CTX, #(((round) * 16) + 0 * 4)];
68
69 #define dummy(round, ra) /* nothing */
70
71 #define addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
72         ldp rna, rnb, [CTX]; \
73         ldp rnc, rnd, [CTX, #8]; \
74         eor ra, ra, rna; \
75         eor rb, rb, rnb; \
76         eor rc, rc, rnc; \
77         preload_key(1, rna); \
78         eor rd, rd, rnd;
79
80 #define do_encround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
81         ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
82         \
83         and RT0, RMASK, ra, lsl#2; \
84         ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
85         and RT1, RMASK, ra, lsr#(8 - 2); \
86         ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
87         and RT2, RMASK, ra, lsr#(16 - 2); \
88         ldr RT0, [RTAB, xRT0]; \
89         and ra,  RMASK, ra, lsr#(24 - 2); \
90         \
91         ldr RT1, [RTAB, xRT1]; \
92         eor rna, rna, RT0; \
93         ldr RT2, [RTAB, xRT2]; \
94         and RT0, RMASK, rd, lsl#2; \
95         ldr ra,  [RTAB, x##ra]; \
96         \
97         eor rnd, rnd, RT1, ror #24; \
98         and RT1, RMASK, rd, lsr#(8 - 2); \
99         eor rnc, rnc, RT2, ror #16; \
100         and RT2, RMASK, rd, lsr#(16 - 2); \
101         eor rnb, rnb, ra, ror #8; \
102         ldr RT0, [RTAB, xRT0]; \
103         and rd,  RMASK, rd, lsr#(24 - 2); \
104         \
105         ldr RT1, [RTAB, xRT1]; \
106         eor rnd, rnd, RT0; \
107         ldr RT2, [RTAB, xRT2]; \
108         and RT0, RMASK, rc, lsl#2; \
109         ldr rd,  [RTAB, x##rd]; \
110         \
111         eor rnc, rnc, RT1, ror #24; \
112         and RT1, RMASK, rc, lsr#(8 - 2); \
113         eor rnb, rnb, RT2, ror #16; \
114         and RT2, RMASK, rc, lsr#(16 - 2); \
115         eor rna, rna, rd, ror #8; \
116         ldr RT0, [RTAB, xRT0]; \
117         and rc,  RMASK, rc, lsr#(24 - 2); \
118         \
119         ldr RT1, [RTAB, xRT1]; \
120         eor rnc, rnc, RT0; \
121         ldr RT2, [RTAB, xRT2]; \
122         and RT0, RMASK, rb, lsl#2; \
123         ldr rc,  [RTAB, x##rc]; \
124         \
125         eor rnb, rnb, RT1, ror #24; \
126         and RT1, RMASK, rb, lsr#(8 - 2); \
127         eor rna, rna, RT2, ror #16; \
128         and RT2, RMASK, rb, lsr#(16 - 2); \
129         eor rnd, rnd, rc, ror #8; \
130         ldr RT0, [RTAB, xRT0]; \
131         and rb,  RMASK, rb, lsr#(24 - 2); \
132         \
133         ldr RT1, [RTAB, xRT1]; \
134         eor rnb, rnb, RT0; \
135         ldr RT2, [RTAB, xRT2]; \
136         eor rna, rna, RT1, ror #24; \
137         ldr rb,  [RTAB, x##rb]; \
138         \
139         eor rnd, rnd, RT2, ror #16; \
140         preload_key((next_r) + 1, ra); \
141         eor rnc, rnc, rb, ror #8;
142
143 #define do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
144         and RT0, RMASK, ra, lsl#2; \
145         and RT1, RMASK, ra, lsr#(8 - 2); \
146         and RT2, RMASK, ra, lsr#(16 - 2); \
147         ldrb rna, [RTAB, xRT0]; \
148         and ra,  RMASK, ra, lsr#(24 - 2); \
149         ldrb rnd, [RTAB, xRT1]; \
150         and RT0, RMASK, rd, lsl#2; \
151         ldrb rnc, [RTAB, xRT2]; \
152         ror rnd, rnd, #24; \
153         ldrb rnb, [RTAB, x##ra]; \
154         and RT1, RMASK, rd, lsr#(8 - 2); \
155         ror rnc, rnc, #16; \
156         and RT2, RMASK, rd, lsr#(16 - 2); \
157         ror rnb, rnb, #8; \
158         ldrb RT0, [RTAB, xRT0]; \
159         and rd,  RMASK, rd, lsr#(24 - 2); \
160         ldrb RT1, [RTAB, xRT1]; \
161         \
162         orr rnd, rnd, RT0; \
163         ldrb RT2, [RTAB, xRT2]; \
164         and RT0, RMASK, rc, lsl#2; \
165         ldrb rd,  [RTAB, x##rd]; \
166         orr rnc, rnc, RT1, ror #24; \
167         and RT1, RMASK, rc, lsr#(8 - 2); \
168         orr rnb, rnb, RT2, ror #16; \
169         and RT2, RMASK, rc, lsr#(16 - 2); \
170         orr rna, rna, rd, ror #8; \
171         ldrb RT0, [RTAB, xRT0]; \
172         and rc,  RMASK, rc, lsr#(24 - 2); \
173         ldrb RT1, [RTAB, xRT1]; \
174         \
175         orr rnc, rnc, RT0; \
176         ldrb RT2, [RTAB, xRT2]; \
177         and RT0, RMASK, rb, lsl#2; \
178         ldrb rc,  [RTAB, x##rc]; \
179         orr rnb, rnb, RT1, ror #24; \
180         and RT1, RMASK, rb, lsr#(8 - 2); \
181         orr rna, rna, RT2, ror #16; \
182         ldrb RT0, [RTAB, xRT0]; \
183         and RT2, RMASK, rb, lsr#(16 - 2); \
184         ldrb RT1, [RTAB, xRT1]; \
185         orr rnd, rnd, rc, ror #8; \
186         ldrb RT2, [RTAB, xRT2]; \
187         and rb,  RMASK, rb, lsr#(24 - 2); \
188         ldrb rb,  [RTAB, x##rb]; \
189         \
190         orr rnb, rnb, RT0; \
191         orr rna, rna, RT1, ror #24; \
192         orr rnd, rnd, RT2, ror #16; \
193         orr rnc, rnc, rb, ror #8;
194
195 #define firstencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
196         addroundkey(ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key); \
197         do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
198
199 #define encround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
200         do_encround((round) + 1, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
201
202 #define lastencround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
203         add CTX, CTX, #(((round) + 1) * 16); \
204         add RTAB, RTAB, #1; \
205         do_lastencround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
206         addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
207
208 .globl _gcry_aes_arm_encrypt_block
209 ELF(.type   _gcry_aes_arm_encrypt_block,%function;)
210
211 _gcry_aes_arm_encrypt_block:
212         /* input:
213          *      %x0: keysched, CTX
214          *      %x1: dst
215          *      %x2: src
216          *      %w3: number of rounds.. 10, 12 or 14
217          *      %x4: encryption table
218          */
219         CFI_STARTPROC();
220
221         /* read input block */
222
223         /* aligned load */
224         ldp     RA, RB, [RSRC];
225         ldp     RC, RD, [RSRC, #8];
226 #ifndef __AARCH64EL__
227         rev     RA, RA;
228         rev     RB, RB;
229         rev     RC, RC;
230         rev     RD, RD;
231 #endif
232
233         mov     RMASK, #(0xff<<2);
234
235         firstencround(0, RA, RB, RC, RD, RNA, RNB, RNC, RND);
236         encround(1, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
237         encround(2, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
238         encround(3, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
239         encround(4, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
240         encround(5, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
241         encround(6, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
242         encround(7, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
243
244         cmp     NROUNDS, #12;
245         bge     .Lenc_not_128;
246
247         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
248         lastencround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD);
249
250 .Lenc_done:
251
252         /* store output block */
253
254         /* aligned store */
255 #ifndef __AARCH64EL__
256         rev     RA, RA;
257         rev     RB, RB;
258         rev     RC, RC;
259         rev     RD, RD;
260 #endif
261         /* write output block */
262         stp     RA, RB, [RDST];
263         stp     RC, RD, [RDST, #8];
264
265         mov     x0, #(0);
266         ret;
267
268 .ltorg
269 .Lenc_not_128:
270         beq .Lenc_192
271
272         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
273         encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
274         encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
275         encround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
276         encround(12, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
277         lastencround(13, RNA, RNB, RNC, RND, RA, RB, RC, RD);
278
279         b .Lenc_done;
280
281 .ltorg
282 .Lenc_192:
283         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
284         encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
285         encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
286         lastencround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD);
287
288         b .Lenc_done;
289         CFI_ENDPROC();
290 ELF(.size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block;)
291
292 #define addroundkey_dec(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
293         ldr rna, [CTX, #(((round) * 16) + 0 * 4)]; \
294         ldr rnb, [CTX, #(((round) * 16) + 1 * 4)]; \
295         eor ra, ra, rna; \
296         ldr rnc, [CTX, #(((round) * 16) + 2 * 4)]; \
297         eor rb, rb, rnb; \
298         ldr rnd, [CTX, #(((round) * 16) + 3 * 4)]; \
299         eor rc, rc, rnc; \
300         preload_first_key((round) - 1, rna); \
301         eor rd, rd, rnd;
302
303 #define do_decround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
304         ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
305         \
306         and RT0, RMASK, ra, lsl#2; \
307         ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
308         and RT1, RMASK, ra, lsr#(8 - 2); \
309         ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
310         and RT2, RMASK, ra, lsr#(16 - 2); \
311         ldr RT0, [RTAB, xRT0]; \
312         and ra,  RMASK, ra, lsr#(24 - 2); \
313         \
314         ldr RT1, [RTAB, xRT1]; \
315         eor rna, rna, RT0; \
316         ldr RT2, [RTAB, xRT2]; \
317         and RT0, RMASK, rb, lsl#2; \
318         ldr ra,  [RTAB, x##ra]; \
319         \
320         eor rnb, rnb, RT1, ror #24; \
321         and RT1, RMASK, rb, lsr#(8 - 2); \
322         eor rnc, rnc, RT2, ror #16; \
323         and RT2, RMASK, rb, lsr#(16 - 2); \
324         eor rnd, rnd, ra, ror #8; \
325         ldr RT0, [RTAB, xRT0]; \
326         and rb,  RMASK, rb, lsr#(24 - 2); \
327         \
328         ldr RT1, [RTAB, xRT1]; \
329         eor rnb, rnb, RT0; \
330         ldr RT2, [RTAB, xRT2]; \
331         and RT0, RMASK, rc, lsl#2; \
332         ldr rb,  [RTAB, x##rb]; \
333         \
334         eor rnc, rnc, RT1, ror #24; \
335         and RT1, RMASK, rc, lsr#(8 - 2); \
336         eor rnd, rnd, RT2, ror #16; \
337         and RT2, RMASK, rc, lsr#(16 - 2); \
338         eor rna, rna, rb, ror #8; \
339         ldr RT0, [RTAB, xRT0]; \
340         and rc,  RMASK, rc, lsr#(24 - 2); \
341         \
342         ldr RT1, [RTAB, xRT1]; \
343         eor rnc, rnc, RT0; \
344         ldr RT2, [RTAB, xRT2]; \
345         and RT0, RMASK, rd, lsl#2; \
346         ldr rc,  [RTAB, x##rc]; \
347         \
348         eor rnd, rnd, RT1, ror #24; \
349         and RT1, RMASK, rd, lsr#(8 - 2); \
350         eor rna, rna, RT2, ror #16; \
351         and RT2, RMASK, rd, lsr#(16 - 2); \
352         eor rnb, rnb, rc, ror #8; \
353         ldr RT0, [RTAB, xRT0]; \
354         and rd,  RMASK, rd, lsr#(24 - 2); \
355         \
356         ldr RT1, [RTAB, xRT1]; \
357         eor rnd, rnd, RT0; \
358         ldr RT2, [RTAB, xRT2]; \
359         eor rna, rna, RT1, ror #24; \
360         ldr rd,  [RTAB, x##rd]; \
361         \
362         eor rnb, rnb, RT2, ror #16; \
363         preload_key((next_r) - 1, ra); \
364         eor rnc, rnc, rd, ror #8;
365
366 #define do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
367         and RT0, RMASK, ra; \
368         and RT1, RMASK, ra, lsr#8; \
369         and RT2, RMASK, ra, lsr#16; \
370         ldrb rna, [RTAB, xRT0]; \
371         lsr ra,  ra, #24; \
372         ldrb rnb, [RTAB, xRT1]; \
373         and RT0, RMASK, rb; \
374         ldrb rnc, [RTAB, xRT2]; \
375         ror rnb, rnb, #24; \
376         ldrb rnd, [RTAB, x##ra]; \
377         and RT1, RMASK, rb, lsr#8; \
378         ror rnc, rnc, #16; \
379         and RT2, RMASK, rb, lsr#16; \
380         ror rnd, rnd, #8; \
381         ldrb RT0, [RTAB, xRT0]; \
382         lsr rb,  rb, #24; \
383         ldrb RT1, [RTAB, xRT1]; \
384         \
385         orr rnb, rnb, RT0; \
386         ldrb RT2, [RTAB, xRT2]; \
387         and RT0, RMASK, rc; \
388         ldrb rb,  [RTAB, x##rb]; \
389         orr rnc, rnc, RT1, ror #24; \
390         and RT1, RMASK, rc, lsr#8; \
391         orr rnd, rnd, RT2, ror #16; \
392         and RT2, RMASK, rc, lsr#16; \
393         orr rna, rna, rb, ror #8; \
394         ldrb RT0, [RTAB, xRT0]; \
395         lsr rc,  rc, #24; \
396         ldrb RT1, [RTAB, xRT1]; \
397         \
398         orr rnc, rnc, RT0; \
399         ldrb RT2, [RTAB, xRT2]; \
400         and RT0, RMASK, rd; \
401         ldrb rc,  [RTAB, x##rc]; \
402         orr rnd, rnd, RT1, ror #24; \
403         and RT1, RMASK, rd, lsr#8; \
404         orr rna, rna, RT2, ror #16; \
405         ldrb RT0, [RTAB, xRT0]; \
406         and RT2, RMASK, rd, lsr#16; \
407         ldrb RT1, [RTAB, xRT1]; \
408         orr rnb, rnb, rc, ror #8; \
409         ldrb RT2, [RTAB, xRT2]; \
410         lsr rd,  rd, #24; \
411         ldrb rd,  [RTAB, x##rd]; \
412         \
413         orr rnd, rnd, RT0; \
414         orr rna, rna, RT1, ror #24; \
415         orr rnb, rnb, RT2, ror #16; \
416         orr rnc, rnc, rd, ror #8;
417
418 #define firstdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
419         addroundkey_dec(((round) + 1), ra, rb, rc, rd, rna, rnb, rnc, rnd); \
420         do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
421
422 #define decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
423         do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
424
425 #define set_last_round_rmask(_, __) \
426         mov RMASK, #0xff;
427
428 #define lastdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
429         add RTAB, RTAB, #(4 * 256); \
430         do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
431         addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
432
433 .globl _gcry_aes_arm_decrypt_block
434 ELF(.type   _gcry_aes_arm_decrypt_block,%function;)
435
436 _gcry_aes_arm_decrypt_block:
437         /* input:
438          *      %x0: keysched, CTX
439          *      %x1: dst
440          *      %x2: src
441          *      %w3: number of rounds.. 10, 12 or 14
442          *      %x4: decryption table
443          */
444         CFI_STARTPROC();
445
446         /* read input block */
447
448         /* aligned load */
449         ldp     RA, RB, [RSRC];
450         ldp     RC, RD, [RSRC, #8];
451 #ifndef __AARCH64EL__
452         rev     RA, RA;
453         rev     RB, RB;
454         rev     RC, RC;
455         rev     RD, RD;
456 #endif
457
458         mov     RMASK, #(0xff << 2);
459
460         cmp     NROUNDS, #12;
461         bge     .Ldec_256;
462
463         firstdecround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND);
464 .Ldec_tail:
465         decround(8, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
466         decround(7, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
467         decround(6, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
468         decround(5, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
469         decround(4, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
470         decround(3, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
471         decround(2, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
472         decround(1, RA, RB, RC, RD, RNA, RNB, RNC, RND, set_last_round_rmask);
473         lastdecround(0, RNA, RNB, RNC, RND, RA, RB, RC, RD);
474
475         /* store output block */
476
477         /* aligned store */
478 #ifndef __AARCH64EL__
479         rev     RA, RA;
480         rev     RB, RB;
481         rev     RC, RC;
482         rev     RD, RD;
483 #endif
484         /* write output block */
485         stp     RA, RB, [RDST];
486         stp     RC, RD, [RDST, #8];
487
488         mov     x0, #(0);
489         ret;
490
491 .ltorg
492 .Ldec_256:
493         beq .Ldec_192;
494
495         firstdecround(13, RA, RB, RC, RD, RNA, RNB, RNC, RND);
496         decround(12, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
497         decround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
498         decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
499         decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
500
501         b .Ldec_tail;
502
503 .ltorg
504 .Ldec_192:
505         firstdecround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND);
506         decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
507         decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
508
509         b .Ldec_tail;
510         CFI_ENDPROC();
511 ELF(.size _gcry_aes_arm_decrypt_block,.-_gcry_aes_arm_decrypt_block;)
512
513 #endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/
514 #endif /*__AARCH64EL__ */