Add ARMv8/CE acceleration for AES-XTS
[libgcrypt.git] / cipher / cast5-amd64.S
1 /* cast5-amd64.S  -  AMD64 assembly implementation of CAST5 cipher
2  *
3  * Copyright (C) 2013 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 #ifdef __x86_64
22 #include <config.h>
23 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
24      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_CAST5)
25
26 #include "asm-common-amd64.h"
27
28 .text
29
30 .extern _gcry_cast5_s1to4;
31
32 #define s1 0
33 #define s2 (s1 + (4 * 256))
34 #define s3 (s2 + (4 * 256))
35 #define s4 (s3 + (4 * 256))
36
37 /* structure of CAST5_context: */
38 #define Km 0
39 #define Kr (Km + (16 * 4))
40
41 /* register macros */
42 #define CTX %rdi
43 #define RIO %rsi
44 #define RTAB %r8
45
46 #define RLR0 %r9
47 #define RLR1 %r10
48 #define RLR2 %r11
49 #define RLR3 %r12
50
51 #define RLR0d %r9d
52 #define RLR1d %r10d
53 #define RLR2d %r11d
54 #define RLR3d %r12d
55
56 #define RX0 %rax
57 #define RX1 %rbx
58 #define RX2 %rdx
59
60 #define RX0d %eax
61 #define RX1d %ebx
62 #define RX2d %edx
63
64 #define RX0bl %al
65 #define RX1bl %bl
66 #define RX2bl %dl
67
68 #define RX0bh %ah
69 #define RX1bh %bh
70 #define RX2bh %dh
71
72 #define RKR %rcx
73 #define RKRd %ecx
74 #define RKRbl %cl
75
76 #define RT0 %rbp
77 #define RT1 %rsi
78
79 #define RT0d %ebp
80 #define RT1d %esi
81
82 #define RKM0d %r13d
83 #define RKM1d %r14d
84
85 /***********************************************************************
86  * 1-way cast5
87  ***********************************************************************/
88 #define dummy(x)
89
90 #define shr_kr(none) \
91         shrq $8,                        RKR;
92
93 #define F(km, load_next_kr, op0, op1, op2, op3) \
94         op0 ## l RLR0d,                 km ## d; \
95         roll RKRbl,                     km ## d; \
96         rorq $32,                       RLR0; \
97         movzbl km ## bh,                RT0d; \
98         movzbl km ## bl,                RT1d; \
99         roll $16,                       km ## d; \
100         movl s1(RTAB,RT0,4),            RT0d; \
101         op1 ## l s2(RTAB,RT1,4),        RT0d; \
102         load_next_kr(kr_next); \
103         movzbl km ## bh,                RT1d; \
104         movzbl km ## bl,                km ## d; \
105         op2 ## l s3(RTAB,RT1,4),        RT0d; \
106         op3 ## l s4(RTAB,km,4),         RT0d; \
107         xorq RT0,                       RLR0;
108
109 #define F1(km, load_next_kr) \
110         F(##km, load_next_kr, add, xor, sub, add)
111 #define F2(km, load_next_kr) \
112         F(##km, load_next_kr, xor, sub, add, xor)
113 #define F3(km, load_next_kr) \
114         F(##km, load_next_kr, sub, add, xor, sub)
115
116 #define get_round_km(n, km) \
117         movl Km+4*(n)(CTX),             km;
118
119 #define get_round_kr_enc(n) \
120         movq $0x1010101010101010,       RKR; \
121         \
122         /* merge rorl rk and rorl $16 */ \
123         xorq Kr+(n)(CTX),               RKR;
124
125 #define get_round_kr_dec(n) \
126         movq $0x1010101010101010,       RKR; \
127         \
128         /* merge rorl rk and rorl $16 */ \
129         xorq Kr+(n - 7)(CTX),           RKR; \
130         bswapq                          RKR;
131
132 #define round_enc(n, FA, FB, fn1, fn2) \
133         get_round_km(n + 1, RX2d); \
134         FA(RX0, fn1); \
135         get_round_km(n + 2, RX0d); \
136         FB(RX2, fn2);
137
138 #define round_enc_last(n, FXA, FXB) \
139         get_round_km(n + 1, RX2d); \
140         \
141         FXA(RX0, shr_kr); \
142         FXB(RX2, dummy);
143
144 #define round_enc_1(n, FA, FB) \
145         round_enc(n, FA, FB, shr_kr, shr_kr)
146
147 #define round_enc_2(n, FA, FB) \
148         round_enc(n, FA, FB, shr_kr, dummy)
149
150 #define round_dec(n, FA, FB, fn1, fn2) \
151         get_round_km(n - 1, RX2d); \
152         FA(RX0, fn1); \
153         get_round_km(n - 2, RX0d); \
154         FB(RX2, fn2);
155
156 #define round_dec_last(n, FXA, FXB) \
157         get_round_km(n - 1, RX2d); \
158         FXA(RX0, shr_kr); \
159         FXB(RX2, dummy);
160
161 #define round_dec_1(n, FA, FB) \
162         round_dec(n, FA, FB, shr_kr, shr_kr)
163
164 #define round_dec_2(n, FA, FB) \
165         round_dec(n, FA, FB, shr_kr, dummy)
166
167 #define read_block() \
168         movq (RIO),             RLR0; \
169         bswapq                  RLR0;
170
171 #define write_block() \
172         bswapq                  RLR0; \
173         rorq $32,               RLR0; \
174         movq RLR0,              (RIO);
175
176 .align 8
177 .globl _gcry_cast5_amd64_encrypt_block
178 ELF(.type   _gcry_cast5_amd64_encrypt_block,@function;)
179
180 _gcry_cast5_amd64_encrypt_block:
181         /* input:
182          *      %rdi: ctx, CTX
183          *      %rsi: dst
184          *      %rdx: src
185          */
186         ENTER_SYSV_FUNC_PARAMS_0_4
187
188         pushq %rbp;
189         pushq %rbx;
190
191         movq %rsi, %r10;
192
193         GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
194
195         movq %rdx, RIO;
196         read_block();
197
198         get_round_km(0, RX0d);
199         get_round_kr_enc(0);
200         round_enc_1(0, F1, F2);
201         round_enc_1(2, F3, F1);
202         round_enc_1(4, F2, F3);
203         round_enc_2(6, F1, F2);
204         get_round_kr_enc(8);
205         round_enc_1(8, F3, F1);
206         round_enc_1(10, F2, F3);
207         round_enc_1(12, F1, F2);
208         round_enc_last(14, F3, F1);
209
210         movq %r10, RIO;
211         write_block();
212
213         popq %rbx;
214         popq %rbp;
215
216         EXIT_SYSV_FUNC
217         ret;
218 ELF(.size _gcry_cast5_amd64_encrypt_block,.-_gcry_cast5_amd64_encrypt_block;)
219
220 .align 8
221 .globl _gcry_cast5_amd64_decrypt_block
222 ELF(.type   _gcry_cast5_amd64_decrypt_block,@function;)
223
224 _gcry_cast5_amd64_decrypt_block:
225         /* input:
226          *      %rdi: ctx, CTX
227          *      %rsi: dst
228          *      %rdx: src
229          */
230         ENTER_SYSV_FUNC_PARAMS_0_4
231
232         pushq %rbp;
233         pushq %rbx;
234
235         movq %rsi, %r10;
236
237         GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
238
239         movq %rdx, RIO;
240         read_block();
241
242         get_round_km(15, RX0d);
243         get_round_kr_dec(15);
244         round_dec_1(15, F1, F3);
245         round_dec_1(13, F2, F1);
246         round_dec_1(11, F3, F2);
247         round_dec_2(9, F1, F3);
248         get_round_kr_dec(7);
249         round_dec_1(7, F2, F1);
250         round_dec_1(5, F3, F2);
251         round_dec_1(3, F1, F3);
252         round_dec_last(1, F2, F1);
253
254         movq %r10, RIO;
255         write_block();
256
257         popq %rbx;
258         popq %rbp;
259
260         EXIT_SYSV_FUNC
261         ret;
262 ELF(.size _gcry_cast5_amd64_decrypt_block,.-_gcry_cast5_amd64_decrypt_block;)
263
264 /**********************************************************************
265   4-way cast5, four blocks parallel
266  **********************************************************************/
267 #define F_tail(rlr, rx, op1, op2, op3) \
268         movzbl rx ## bh,                RT0d; \
269         movzbl rx ## bl,                RT1d; \
270         roll $16,                       rx ## d; \
271         movl s1(RTAB,RT0,4),            RT0d; \
272         op1 ## l s2(RTAB,RT1,4),        RT0d; \
273         movzbl rx ## bh,                RT1d; \
274         movzbl rx ## bl,                rx ## d; \
275         op2 ## l s3(RTAB,RT1,4),        RT0d; \
276         op3 ## l s4(RTAB,rx,4),         RT0d; \
277         xorq RT0,                       rlr;
278
279 #define F4(km, load_next_kr, op0, op1, op2, op3) \
280         movl km,                        RX0d; \
281         op0 ## l RLR0d,                 RX0d; \
282         roll RKRbl,                     RX0d; \
283         rorq $32,                       RLR0; \
284         \
285         movl km,                        RX1d; \
286         op0 ## l RLR1d,                 RX1d; \
287         roll RKRbl,                     RX1d; \
288         rorq $32,                       RLR1; \
289         \
290         movl km,                        RX2d; \
291         op0 ## l RLR2d,                 RX2d; \
292         roll RKRbl,                     RX2d; \
293         rorq $32,                       RLR2; \
294         \
295         F_tail(RLR0, RX0, op1, op2, op3); \
296         F_tail(RLR1, RX1, op1, op2, op3); \
297         F_tail(RLR2, RX2, op1, op2, op3); \
298         \
299         movl km,                        RX0d; \
300         op0 ## l RLR3d,                 RX0d; \
301         roll RKRbl,                     RX0d; \
302         load_next_kr();                 \
303         rorq $32,                       RLR3; \
304         \
305         F_tail(RLR3, RX0, op1, op2, op3);
306
307 #define F4_1(km, load_next_kr) \
308         F4(km, load_next_kr, add, xor, sub, add)
309 #define F4_2(km, load_next_kr) \
310         F4(km, load_next_kr, xor, sub, add, xor)
311 #define F4_3(km, load_next_kr) \
312         F4(km, load_next_kr, sub, add, xor, sub)
313
314 #define round_enc4(n, FA, FB, fn1, fn2) \
315         get_round_km(n + 1, RKM1d); \
316         FA(RKM0d, fn1); \
317         get_round_km(n + 2, RKM0d); \
318         FB(RKM1d, fn2);
319
320 #define round_enc_last4(n, FXA, FXB) \
321         get_round_km(n + 1, RKM1d); \
322         FXA(RKM0d, shr_kr); \
323         FXB(RKM1d, dummy);
324
325 #define round_enc4_1(n, FA, FB) \
326         round_enc4(n, FA, FB, shr_kr, shr_kr);
327
328 #define round_enc4_2(n, FA, FB) \
329         round_enc4(n, FA, FB, shr_kr, dummy);
330
331 #define round_dec4(n, FA, FB, fn1, fn2) \
332         get_round_km(n - 1, RKM1d); \
333         FA(RKM0d, fn1); \
334         get_round_km(n - 2, RKM0d); \
335         FB(RKM1d, fn2);
336
337 #define round_dec_last4(n, FXA, FXB) \
338         get_round_km(n - 1, RKM1d); \
339         FXA(RKM0d, shr_kr); \
340         FXB(RKM1d, dummy);
341
342 #define round_dec4_1(n, FA, FB) \
343         round_dec4(n, FA, FB, shr_kr, shr_kr);
344
345 #define round_dec4_2(n, FA, FB) \
346         round_dec4(n, FA, FB, shr_kr, dummy);
347
348 #define inbswap_block4(a, b, c, d) \
349         bswapq                  a; \
350         bswapq                  b; \
351         bswapq                  c; \
352         bswapq                  d;
353
354 #define outbswap_block4(a, b, c, d) \
355         bswapq                  a; \
356         bswapq                  b; \
357         bswapq                  c; \
358         bswapq                  d; \
359         rorq $32,               a; \
360         rorq $32,               b; \
361         rorq $32,               c; \
362         rorq $32,               d;
363
364 .align 8
365 ELF(.type   __cast5_enc_blk4,@function;)
366
367 __cast5_enc_blk4:
368         /* input:
369          *      %rdi: ctx, CTX
370          *      RLR0,RLR1,RLR2,RLR3: four input plaintext blocks
371          * output:
372          *      RLR0,RLR1,RLR2,RLR3: four output ciphertext blocks
373          */
374         GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
375
376         get_round_km(0, RKM0d);
377         get_round_kr_enc(0);
378         round_enc4_1(0, F4_1, F4_2);
379         round_enc4_1(2, F4_3, F4_1);
380         round_enc4_1(4, F4_2, F4_3);
381         round_enc4_2(6, F4_1, F4_2);
382         get_round_kr_enc(8);
383         round_enc4_1(8, F4_3, F4_1);
384         round_enc4_1(10, F4_2, F4_3);
385         round_enc4_1(12, F4_1, F4_2);
386         round_enc_last4(14, F4_3, F4_1);
387
388         outbswap_block4(RLR0, RLR1, RLR2, RLR3);
389         ret;
390 ELF(.size __cast5_enc_blk4,.-__cast5_enc_blk4;)
391
392 .align 8
393 ELF(.type   __cast5_dec_blk4,@function;)
394
395 __cast5_dec_blk4:
396         /* input:
397          *      %rdi: ctx, CTX
398          *      RLR0,RLR1,RLR2,RLR3: four input ciphertext blocks
399          * output:
400          *      RLR0,RLR1,RLR2,RLR3: four output plaintext blocks
401          */
402         GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
403
404         inbswap_block4(RLR0, RLR1, RLR2, RLR3);
405
406         get_round_km(15, RKM0d);
407         get_round_kr_dec(15);
408         round_dec4_1(15, F4_1, F4_3);
409         round_dec4_1(13, F4_2, F4_1);
410         round_dec4_1(11, F4_3, F4_2);
411         round_dec4_2(9, F4_1, F4_3);
412         get_round_kr_dec(7);
413         round_dec4_1(7, F4_2, F4_1);
414         round_dec4_1(5, F4_3, F4_2);
415         round_dec4_1(3, F4_1, F4_3);
416         round_dec_last4(1, F4_2, F4_1);
417
418         outbswap_block4(RLR0, RLR1, RLR2, RLR3);
419         ret;
420 ELF(.size __cast5_dec_blk4,.-__cast5_dec_blk4;)
421
422 .align 8
423 .globl _gcry_cast5_amd64_ctr_enc
424 ELF(.type   _gcry_cast5_amd64_ctr_enc,@function;)
425 _gcry_cast5_amd64_ctr_enc:
426         /* input:
427          *      %rdi: ctx, CTX
428          *      %rsi: dst (8 blocks)
429          *      %rdx: src (8 blocks)
430          *      %rcx: iv (big endian, 64bit)
431          */
432         ENTER_SYSV_FUNC_PARAMS_0_4
433
434         pushq %rbp;
435         pushq %rbx;
436         pushq %r12;
437         pushq %r13;
438         pushq %r14;
439
440         pushq %rsi;
441         pushq %rdx;
442
443         /* load IV and byteswap */
444         movq (%rcx), RX0;
445         bswapq RX0;
446         movq RX0, RLR0;
447
448         /* construct IVs */
449         leaq 1(RX0), RLR1;
450         leaq 2(RX0), RLR2;
451         leaq 3(RX0), RLR3;
452         leaq 4(RX0), RX0;
453         bswapq RX0;
454
455         /* store new IV */
456         movq RX0, (%rcx);
457
458         call __cast5_enc_blk4;
459
460         popq %r14; /*src*/
461         popq %r13; /*dst*/
462
463         /* XOR key-stream with plaintext */
464         xorq 0 * 8(%r14), RLR0;
465         xorq 1 * 8(%r14), RLR1;
466         xorq 2 * 8(%r14), RLR2;
467         xorq 3 * 8(%r14), RLR3;
468         movq RLR0, 0 * 8(%r13);
469         movq RLR1, 1 * 8(%r13);
470         movq RLR2, 2 * 8(%r13);
471         movq RLR3, 3 * 8(%r13);
472
473         popq %r14;
474         popq %r13;
475         popq %r12;
476         popq %rbx;
477         popq %rbp;
478
479         EXIT_SYSV_FUNC
480         ret
481 ELF(.size _gcry_cast5_amd64_ctr_enc,.-_gcry_cast5_amd64_ctr_enc;)
482
483 .align 8
484 .globl _gcry_cast5_amd64_cbc_dec
485 ELF(.type   _gcry_cast5_amd64_cbc_dec,@function;)
486 _gcry_cast5_amd64_cbc_dec:
487         /* input:
488          *      %rdi: ctx, CTX
489          *      %rsi: dst (8 blocks)
490          *      %rdx: src (8 blocks)
491          *      %rcx: iv (64bit)
492          */
493         ENTER_SYSV_FUNC_PARAMS_0_4
494
495         pushq %rbp;
496         pushq %rbx;
497         pushq %r12;
498         pushq %r13;
499         pushq %r14;
500
501         pushq %rcx;
502         pushq %rsi;
503         pushq %rdx;
504
505         /* load input */
506         movq 0 * 8(%rdx), RLR0;
507         movq 1 * 8(%rdx), RLR1;
508         movq 2 * 8(%rdx), RLR2;
509         movq 3 * 8(%rdx), RLR3;
510
511         call __cast5_dec_blk4;
512
513         popq RX0; /*src*/
514         popq RX1; /*dst*/
515         popq RX2; /*iv*/
516
517         movq 3 * 8(RX0), %r14;
518         xorq      (RX2), RLR0;
519         xorq 0 * 8(RX0), RLR1;
520         xorq 1 * 8(RX0), RLR2;
521         xorq 2 * 8(RX0), RLR3;
522         movq %r14, (RX2); /* store new IV */
523
524         movq RLR0, 0 * 8(RX1);
525         movq RLR1, 1 * 8(RX1);
526         movq RLR2, 2 * 8(RX1);
527         movq RLR3, 3 * 8(RX1);
528
529         popq %r14;
530         popq %r13;
531         popq %r12;
532         popq %rbx;
533         popq %rbp;
534
535         EXIT_SYSV_FUNC
536         ret;
537
538 ELF(.size _gcry_cast5_amd64_cbc_dec,.-_gcry_cast5_amd64_cbc_dec;)
539
540 .align 8
541 .globl _gcry_cast5_amd64_cfb_dec
542 ELF(.type   _gcry_cast5_amd64_cfb_dec,@function;)
543 _gcry_cast5_amd64_cfb_dec:
544         /* input:
545          *      %rdi: ctx, CTX
546          *      %rsi: dst (8 blocks)
547          *      %rdx: src (8 blocks)
548          *      %rcx: iv (64bit)
549          */
550         ENTER_SYSV_FUNC_PARAMS_0_4
551
552         pushq %rbp;
553         pushq %rbx;
554         pushq %r12;
555         pushq %r13;
556         pushq %r14;
557
558         pushq %rsi;
559         pushq %rdx;
560
561         /* Load input */
562         movq (%rcx), RLR0;
563         movq 0 * 8(%rdx), RLR1;
564         movq 1 * 8(%rdx), RLR2;
565         movq 2 * 8(%rdx), RLR3;
566
567         inbswap_block4(RLR0, RLR1, RLR2, RLR3);
568
569         /* Update IV */
570         movq 3 * 8(%rdx), %rdx;
571         movq %rdx, (%rcx);
572
573         call __cast5_enc_blk4;
574
575         popq %rdx; /*src*/
576         popq %rcx; /*dst*/
577
578         xorq 0 * 8(%rdx), RLR0;
579         xorq 1 * 8(%rdx), RLR1;
580         xorq 2 * 8(%rdx), RLR2;
581         xorq 3 * 8(%rdx), RLR3;
582         movq RLR0, 0 * 8(%rcx);
583         movq RLR1, 1 * 8(%rcx);
584         movq RLR2, 2 * 8(%rcx);
585         movq RLR3, 3 * 8(%rcx);
586
587         popq %r14;
588         popq %r13;
589         popq %r12;
590         popq %rbx;
591         popq %rbp;
592
593         EXIT_SYSV_FUNC
594         ret;
595
596 ELF(.size _gcry_cast5_amd64_cfb_dec,.-_gcry_cast5_amd64_cfb_dec;)
597
598 #endif /*defined(USE_CAST5)*/
599 #endif /*__x86_64*/