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