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