aarch64: Enable building the aarch64 cipher assembly for windows
[libgcrypt.git] / cipher / twofish-aarch64.S
1 /* twofish-aarch64.S  -  ARMv8/AArch64 assembly implementation of Twofish 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 /* structure of TWOFISH_context: */
29 #define s0 0
30 #define s1 ((s0) + 4 * 256)
31 #define s2 ((s1) + 4 * 256)
32 #define s3 ((s2) + 4 * 256)
33 #define w  ((s3) + 4 * 256)
34 #define k  ((w) + 4 * 8)
35
36 /* register macros */
37 #define CTX x0
38 #define RDST x1
39 #define RSRC x2
40 #define CTXs0 CTX
41 #define CTXs1 x3
42 #define CTXs2 x4
43 #define CTXs3 x5
44 #define CTXw x17
45
46 #define RA w6
47 #define RB w7
48 #define RC w8
49 #define RD w9
50
51 #define RX w10
52 #define RY w11
53
54 #define xRX x10
55 #define xRY x11
56
57 #define RMASK w12
58
59 #define RT0 w13
60 #define RT1 w14
61 #define RT2 w15
62 #define RT3 w16
63
64 #define xRT0 x13
65 #define xRT1 x14
66 #define xRT2 x15
67 #define xRT3 x16
68
69 /* helper macros */
70 #ifndef __AARCH64EL__
71         /* bswap on big-endian */
72         #define host_to_le(reg) \
73                 rev reg, reg;
74         #define le_to_host(reg) \
75                 rev reg, reg;
76 #else
77         /* nop on little-endian */
78         #define host_to_le(reg) /*_*/
79         #define le_to_host(reg) /*_*/
80 #endif
81
82 #define ldr_input_aligned_le(rin, a, b, c, d) \
83         ldr a, [rin, #0]; \
84         ldr b, [rin, #4]; \
85         le_to_host(a); \
86         ldr c, [rin, #8]; \
87         le_to_host(b); \
88         ldr d, [rin, #12]; \
89         le_to_host(c); \
90         le_to_host(d);
91
92 #define str_output_aligned_le(rout, a, b, c, d) \
93         le_to_host(a); \
94         le_to_host(b); \
95         str a, [rout, #0]; \
96         le_to_host(c); \
97         str b, [rout, #4]; \
98         le_to_host(d); \
99         str c, [rout, #8]; \
100         str d, [rout, #12];
101
102 /* unaligned word reads/writes allowed */
103 #define ldr_input_le(rin, ra, rb, rc, rd, rtmp) \
104         ldr_input_aligned_le(rin, ra, rb, rc, rd)
105
106 #define str_output_le(rout, ra, rb, rc, rd, rtmp0, rtmp1) \
107         str_output_aligned_le(rout, ra, rb, rc, rd)
108
109 /**********************************************************************
110   1-way twofish
111  **********************************************************************/
112 #define encrypt_round(a, b, rc, rd, n, ror_a, adj_a) \
113         and RT0, RMASK, b, lsr#(8 - 2); \
114         and RY, RMASK, b, lsr#(16 - 2); \
115         and RT1, RMASK, b, lsr#(24 - 2); \
116         ldr RY, [CTXs3, xRY]; \
117         and RT2, RMASK, b, lsl#(2); \
118         ldr RT0, [CTXs2, xRT0]; \
119         and RT3, RMASK, a, lsr#(16 - 2 + (adj_a)); \
120         ldr RT1, [CTXs0, xRT1]; \
121         and RX, RMASK, a, lsr#(8 - 2 + (adj_a)); \
122         ldr RT2, [CTXs1, xRT2]; \
123         ldr RX, [CTXs1, xRX]; \
124         ror_a(a); \
125         \
126         eor RY, RY, RT0; \
127         ldr RT3, [CTXs2, xRT3]; \
128         and RT0, RMASK, a, lsl#(2); \
129         eor RY, RY, RT1; \
130         and RT1, RMASK, a, lsr#(24 - 2); \
131         eor RY, RY, RT2; \
132         ldr RT0, [CTXs0, xRT0]; \
133         eor RX, RX, RT3; \
134         ldr RT1, [CTXs3, xRT1]; \
135         eor RX, RX, RT0; \
136         \
137         ldr RT3, [CTXs3, #(k - s3 + 8 * (n) + 4)]; \
138         eor RX, RX, RT1; \
139         ldr RT2, [CTXs3, #(k - s3 + 8 * (n))]; \
140         \
141         add RT0, RX, RY, lsl #1; \
142         add RX, RX, RY; \
143         add RT0, RT0, RT3; \
144         add RX, RX, RT2; \
145         eor rd, RT0, rd, ror #31; \
146         eor rc, rc, RX;
147
148 #define dummy(x) /*_*/
149
150 #define ror1(r) \
151         ror r, r, #1;
152
153 #define decrypt_round(a, b, rc, rd, n, ror_b, adj_b) \
154         and RT3, RMASK, b, lsl#(2 - (adj_b)); \
155         and RT1, RMASK, b, lsr#(8 - 2 + (adj_b)); \
156         ror_b(b); \
157         and RT2, RMASK, a, lsl#(2); \
158         and RT0, RMASK, a, lsr#(8 - 2); \
159         \
160         ldr RY, [CTXs1, xRT3]; \
161         ldr RX, [CTXs0, xRT2]; \
162         and RT3, RMASK, b, lsr#(16 - 2); \
163         ldr RT1, [CTXs2, xRT1]; \
164         and RT2, RMASK, a, lsr#(16 - 2); \
165         ldr RT0, [CTXs1, xRT0]; \
166         \
167         ldr RT3, [CTXs3, xRT3]; \
168         eor RY, RY, RT1; \
169         \
170         and RT1, RMASK, b, lsr#(24 - 2); \
171         eor RX, RX, RT0; \
172         ldr RT2, [CTXs2, xRT2]; \
173         and RT0, RMASK, a, lsr#(24 - 2); \
174         \
175         ldr RT1, [CTXs0, xRT1]; \
176         \
177         eor RY, RY, RT3; \
178         ldr RT0, [CTXs3, xRT0]; \
179         eor RX, RX, RT2; \
180         eor RY, RY, RT1; \
181         \
182         ldr RT1, [CTXs3, #(k - s3 + 8 * (n) + 4)]; \
183         eor RX, RX, RT0; \
184         ldr RT2, [CTXs3, #(k - s3 + 8 * (n))]; \
185         \
186         add RT0, RX, RY, lsl #1; \
187         add RX, RX, RY; \
188         add RT0, RT0, RT1; \
189         add RX, RX, RT2; \
190         eor rd, rd, RT0; \
191         eor rc, RX, rc, ror #31;
192
193 #define first_encrypt_cycle(nc) \
194         encrypt_round(RA, RB, RC, RD, (nc) * 2, dummy, 0); \
195         encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1);
196
197 #define encrypt_cycle(nc) \
198         encrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \
199         encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1);
200
201 #define last_encrypt_cycle(nc) \
202         encrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \
203         encrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \
204         ror1(RA);
205
206 #define first_decrypt_cycle(nc) \
207         decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, dummy, 0); \
208         decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1);
209
210 #define decrypt_cycle(nc) \
211         decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \
212         decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1);
213
214 #define last_decrypt_cycle(nc) \
215         decrypt_round(RC, RD, RA, RB, (nc) * 2 + 1, ror1, 1); \
216         decrypt_round(RA, RB, RC, RD, (nc) * 2, ror1, 1); \
217         ror1(RD);
218
219 .globl _gcry_twofish_arm_encrypt_block
220 ELF(.type   _gcry_twofish_arm_encrypt_block,%function;)
221
222 _gcry_twofish_arm_encrypt_block:
223         /* input:
224          *      x0: ctx
225          *      x1: dst
226          *      x2: src
227          */
228
229         add CTXw, CTX, #(w);
230
231         ldr_input_le(RSRC, RA, RB, RC, RD, RT0);
232
233         /* Input whitening */
234         ldp RT0, RT1, [CTXw, #(0*8)];
235         ldp RT2, RT3, [CTXw, #(1*8)];
236         add CTXs3, CTX, #(s3);
237         add CTXs2, CTX, #(s2);
238         add CTXs1, CTX, #(s1);
239         mov RMASK, #(0xff << 2);
240         eor RA, RA, RT0;
241         eor RB, RB, RT1;
242         eor RC, RC, RT2;
243         eor RD, RD, RT3;
244
245         first_encrypt_cycle(0);
246         encrypt_cycle(1);
247         encrypt_cycle(2);
248         encrypt_cycle(3);
249         encrypt_cycle(4);
250         encrypt_cycle(5);
251         encrypt_cycle(6);
252         last_encrypt_cycle(7);
253
254         /* Output whitening */
255         ldp RT0, RT1, [CTXw, #(2*8)];
256         ldp RT2, RT3, [CTXw, #(3*8)];
257         eor RC, RC, RT0;
258         eor RD, RD, RT1;
259         eor RA, RA, RT2;
260         eor RB, RB, RT3;
261
262         str_output_le(RDST, RC, RD, RA, RB, RT0, RT1);
263
264         ret;
265 .ltorg
266 ELF(.size _gcry_twofish_arm_encrypt_block,.-_gcry_twofish_arm_encrypt_block;)
267
268 .globl _gcry_twofish_arm_decrypt_block
269 ELF(.type   _gcry_twofish_arm_decrypt_block,%function;)
270
271 _gcry_twofish_arm_decrypt_block:
272         /* input:
273          *      %r0: ctx
274          *      %r1: dst
275          *      %r2: src
276          */
277
278         add CTXw, CTX, #(w);
279
280         ldr_input_le(RSRC, RC, RD, RA, RB, RT0);
281
282         /* Input whitening */
283         ldp RT0, RT1, [CTXw, #(2*8)];
284         ldp RT2, RT3, [CTXw, #(3*8)];
285         add CTXs3, CTX, #(s3);
286         add CTXs2, CTX, #(s2);
287         add CTXs1, CTX, #(s1);
288         mov RMASK, #(0xff << 2);
289         eor RC, RC, RT0;
290         eor RD, RD, RT1;
291         eor RA, RA, RT2;
292         eor RB, RB, RT3;
293
294         first_decrypt_cycle(7);
295         decrypt_cycle(6);
296         decrypt_cycle(5);
297         decrypt_cycle(4);
298         decrypt_cycle(3);
299         decrypt_cycle(2);
300         decrypt_cycle(1);
301         last_decrypt_cycle(0);
302
303         /* Output whitening */
304         ldp RT0, RT1, [CTXw, #(0*8)];
305         ldp RT2, RT3, [CTXw, #(1*8)];
306         eor RA, RA, RT0;
307         eor RB, RB, RT1;
308         eor RC, RC, RT2;
309         eor RD, RD, RT3;
310
311         str_output_le(RDST, RA, RB, RC, RD, RT0, RT1);
312
313         ret;
314 ELF(.size _gcry_twofish_arm_decrypt_block,.-_gcry_twofish_arm_decrypt_block;)
315
316 #endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/
317 #endif /*__AARCH64EL__*/