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