aarch64: Enable building the aarch64 cipher assembly for windows
[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
220         /* read input block */
221
222         /* aligned load */
223         ldp     RA, RB, [RSRC];
224         ldp     RC, RD, [RSRC, #8];
225 #ifndef __AARCH64EL__
226         rev     RA, RA;
227         rev     RB, RB;
228         rev     RC, RC;
229         rev     RD, RD;
230 #endif
231
232         mov     RMASK, #(0xff<<2);
233
234         firstencround(0, RA, RB, RC, RD, RNA, RNB, RNC, RND);
235         encround(1, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
236         encround(2, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
237         encround(3, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
238         encround(4, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
239         encround(5, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
240         encround(6, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
241         encround(7, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
242
243         cmp     NROUNDS, #12;
244         bge     .Lenc_not_128;
245
246         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
247         lastencround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD);
248
249 .Lenc_done:
250
251         /* store output block */
252
253         /* aligned store */
254 #ifndef __AARCH64EL__
255         rev     RA, RA;
256         rev     RB, RB;
257         rev     RC, RC;
258         rev     RD, RD;
259 #endif
260         /* write output block */
261         stp     RA, RB, [RDST];
262         stp     RC, RD, [RDST, #8];
263
264         mov     x0, #(0);
265         ret;
266
267 .ltorg
268 .Lenc_not_128:
269         beq .Lenc_192
270
271         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
272         encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
273         encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
274         encround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
275         encround(12, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
276         lastencround(13, RNA, RNB, RNC, RND, RA, RB, RC, RD);
277
278         b .Lenc_done;
279
280 .ltorg
281 .Lenc_192:
282         encround(8, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
283         encround(9, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
284         encround(10, RA, RB, RC, RD, RNA, RNB, RNC, RND, dummy);
285         lastencround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD);
286
287         b .Lenc_done;
288 ELF(.size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block;)
289
290 #define addroundkey_dec(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
291         ldr rna, [CTX, #(((round) * 16) + 0 * 4)]; \
292         ldr rnb, [CTX, #(((round) * 16) + 1 * 4)]; \
293         eor ra, ra, rna; \
294         ldr rnc, [CTX, #(((round) * 16) + 2 * 4)]; \
295         eor rb, rb, rnb; \
296         ldr rnd, [CTX, #(((round) * 16) + 3 * 4)]; \
297         eor rc, rc, rnc; \
298         preload_first_key((round) - 1, rna); \
299         eor rd, rd, rnd;
300
301 #define do_decround(next_r, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
302         ldr rnb, [CTX, #(((next_r) * 16) + 1 * 4)]; \
303         \
304         and RT0, RMASK, ra, lsl#2; \
305         ldr rnc, [CTX, #(((next_r) * 16) + 2 * 4)]; \
306         and RT1, RMASK, ra, lsr#(8 - 2); \
307         ldr rnd, [CTX, #(((next_r) * 16) + 3 * 4)]; \
308         and RT2, RMASK, ra, lsr#(16 - 2); \
309         ldr RT0, [RTAB, xRT0]; \
310         and ra,  RMASK, ra, lsr#(24 - 2); \
311         \
312         ldr RT1, [RTAB, xRT1]; \
313         eor rna, rna, RT0; \
314         ldr RT2, [RTAB, xRT2]; \
315         and RT0, RMASK, rb, lsl#2; \
316         ldr ra,  [RTAB, x##ra]; \
317         \
318         eor rnb, rnb, RT1, ror #24; \
319         and RT1, RMASK, rb, lsr#(8 - 2); \
320         eor rnc, rnc, RT2, ror #16; \
321         and RT2, RMASK, rb, lsr#(16 - 2); \
322         eor rnd, rnd, ra, ror #8; \
323         ldr RT0, [RTAB, xRT0]; \
324         and rb,  RMASK, rb, lsr#(24 - 2); \
325         \
326         ldr RT1, [RTAB, xRT1]; \
327         eor rnb, rnb, RT0; \
328         ldr RT2, [RTAB, xRT2]; \
329         and RT0, RMASK, rc, lsl#2; \
330         ldr rb,  [RTAB, x##rb]; \
331         \
332         eor rnc, rnc, RT1, ror #24; \
333         and RT1, RMASK, rc, lsr#(8 - 2); \
334         eor rnd, rnd, RT2, ror #16; \
335         and RT2, RMASK, rc, lsr#(16 - 2); \
336         eor rna, rna, rb, ror #8; \
337         ldr RT0, [RTAB, xRT0]; \
338         and rc,  RMASK, rc, lsr#(24 - 2); \
339         \
340         ldr RT1, [RTAB, xRT1]; \
341         eor rnc, rnc, RT0; \
342         ldr RT2, [RTAB, xRT2]; \
343         and RT0, RMASK, rd, lsl#2; \
344         ldr rc,  [RTAB, x##rc]; \
345         \
346         eor rnd, rnd, RT1, ror #24; \
347         and RT1, RMASK, rd, lsr#(8 - 2); \
348         eor rna, rna, RT2, ror #16; \
349         and RT2, RMASK, rd, lsr#(16 - 2); \
350         eor rnb, rnb, rc, ror #8; \
351         ldr RT0, [RTAB, xRT0]; \
352         and rd,  RMASK, rd, lsr#(24 - 2); \
353         \
354         ldr RT1, [RTAB, xRT1]; \
355         eor rnd, rnd, RT0; \
356         ldr RT2, [RTAB, xRT2]; \
357         eor rna, rna, RT1, ror #24; \
358         ldr rd,  [RTAB, x##rd]; \
359         \
360         eor rnb, rnb, RT2, ror #16; \
361         preload_key((next_r) - 1, ra); \
362         eor rnc, rnc, rd, ror #8;
363
364 #define do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd) \
365         and RT0, RMASK, ra; \
366         and RT1, RMASK, ra, lsr#8; \
367         and RT2, RMASK, ra, lsr#16; \
368         ldrb rna, [RTAB, xRT0]; \
369         lsr ra,  ra, #24; \
370         ldrb rnb, [RTAB, xRT1]; \
371         and RT0, RMASK, rb; \
372         ldrb rnc, [RTAB, xRT2]; \
373         ror rnb, rnb, #24; \
374         ldrb rnd, [RTAB, x##ra]; \
375         and RT1, RMASK, rb, lsr#8; \
376         ror rnc, rnc, #16; \
377         and RT2, RMASK, rb, lsr#16; \
378         ror rnd, rnd, #8; \
379         ldrb RT0, [RTAB, xRT0]; \
380         lsr rb,  rb, #24; \
381         ldrb RT1, [RTAB, xRT1]; \
382         \
383         orr rnb, rnb, RT0; \
384         ldrb RT2, [RTAB, xRT2]; \
385         and RT0, RMASK, rc; \
386         ldrb rb,  [RTAB, x##rb]; \
387         orr rnc, rnc, RT1, ror #24; \
388         and RT1, RMASK, rc, lsr#8; \
389         orr rnd, rnd, RT2, ror #16; \
390         and RT2, RMASK, rc, lsr#16; \
391         orr rna, rna, rb, ror #8; \
392         ldrb RT0, [RTAB, xRT0]; \
393         lsr rc,  rc, #24; \
394         ldrb RT1, [RTAB, xRT1]; \
395         \
396         orr rnc, rnc, RT0; \
397         ldrb RT2, [RTAB, xRT2]; \
398         and RT0, RMASK, rd; \
399         ldrb rc,  [RTAB, x##rc]; \
400         orr rnd, rnd, RT1, ror #24; \
401         and RT1, RMASK, rd, lsr#8; \
402         orr rna, rna, RT2, ror #16; \
403         ldrb RT0, [RTAB, xRT0]; \
404         and RT2, RMASK, rd, lsr#16; \
405         ldrb RT1, [RTAB, xRT1]; \
406         orr rnb, rnb, rc, ror #8; \
407         ldrb RT2, [RTAB, xRT2]; \
408         lsr rd,  rd, #24; \
409         ldrb rd,  [RTAB, x##rd]; \
410         \
411         orr rnd, rnd, RT0; \
412         orr rna, rna, RT1, ror #24; \
413         orr rnb, rnb, RT2, ror #16; \
414         orr rnc, rnc, rd, ror #8;
415
416 #define firstdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
417         addroundkey_dec(((round) + 1), ra, rb, rc, rd, rna, rnb, rnc, rnd); \
418         do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_first_key);
419
420 #define decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key) \
421         do_decround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd, preload_key);
422
423 #define set_last_round_rmask(_, __) \
424         mov RMASK, #0xff;
425
426 #define lastdecround(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
427         add RTAB, RTAB, #(4 * 256); \
428         do_lastdecround(ra, rb, rc, rd, rna, rnb, rnc, rnd); \
429         addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
430
431 .globl _gcry_aes_arm_decrypt_block
432 ELF(.type   _gcry_aes_arm_decrypt_block,%function;)
433
434 _gcry_aes_arm_decrypt_block:
435         /* input:
436          *      %x0: keysched, CTX
437          *      %x1: dst
438          *      %x2: src
439          *      %w3: number of rounds.. 10, 12 or 14
440          *      %x4: decryption table
441          */
442
443         /* read input block */
444
445         /* aligned load */
446         ldp     RA, RB, [RSRC];
447         ldp     RC, RD, [RSRC, #8];
448 #ifndef __AARCH64EL__
449         rev     RA, RA;
450         rev     RB, RB;
451         rev     RC, RC;
452         rev     RD, RD;
453 #endif
454
455         mov     RMASK, #(0xff << 2);
456
457         cmp     NROUNDS, #12;
458         bge     .Ldec_256;
459
460         firstdecround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND);
461 .Ldec_tail:
462         decround(8, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
463         decround(7, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
464         decround(6, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
465         decround(5, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
466         decround(4, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
467         decround(3, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
468         decround(2, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
469         decround(1, RA, RB, RC, RD, RNA, RNB, RNC, RND, set_last_round_rmask);
470         lastdecround(0, RNA, RNB, RNC, RND, RA, RB, RC, RD);
471
472         /* store output block */
473
474         /* aligned store */
475 #ifndef __AARCH64EL__
476         rev     RA, RA;
477         rev     RB, RB;
478         rev     RC, RC;
479         rev     RD, RD;
480 #endif
481         /* write output block */
482         stp     RA, RB, [RDST];
483         stp     RC, RD, [RDST, #8];
484
485         mov     x0, #(0);
486         ret;
487
488 .ltorg
489 .Ldec_256:
490         beq .Ldec_192;
491
492         firstdecround(13, RA, RB, RC, RD, RNA, RNB, RNC, RND);
493         decround(12, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
494         decround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
495         decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
496         decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
497
498         b .Ldec_tail;
499
500 .ltorg
501 .Ldec_192:
502         firstdecround(11, RA, RB, RC, RD, RNA, RNB, RNC, RND);
503         decround(10, RNA, RNB, RNC, RND, RA, RB, RC, RD, preload_first_key);
504         decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
505
506         b .Ldec_tail;
507 ELF(.size _gcry_aes_arm_decrypt_block,.-_gcry_aes_arm_decrypt_block;)
508
509 #endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/
510 #endif /*__AARCH64EL__ */