Add crypto hash SM3.
[libgcrypt.git] / cipher / blowfish-amd64.S
1 /* blowfish-amd64.S  -  AMD64 assembly implementation of Blowfish 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(USE_BLOWFISH) && \
24     (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
25      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
26
27 #ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
28 # define ELF(...) __VA_ARGS__
29 #else
30 # define ELF(...) /*_*/
31 #endif
32
33 .text
34
35 /* structure of BLOWFISH_context: */
36 #define s0      0
37 #define s1      ((s0) + 256 * 4)
38 #define s2      ((s1) + 256 * 4)
39 #define s3      ((s2) + 256 * 4)
40 #define p       ((s3) + 256 * 4)
41
42 /* register macros */
43 #define CTX %rdi
44 #define RIO %rsi
45
46 #define RX0 %rax
47 #define RX1 %rbx
48 #define RX2 %rcx
49 #define RX3 %rdx
50
51 #define RX0d %eax
52 #define RX1d %ebx
53 #define RX2d %ecx
54 #define RX3d %edx
55
56 #define RX0bl %al
57 #define RX1bl %bl
58 #define RX2bl %cl
59 #define RX3bl %dl
60
61 #define RX0bh %ah
62 #define RX1bh %bh
63 #define RX2bh %ch
64 #define RX3bh %dh
65
66 #define RT0 %rbp
67 #define RT1 %rsi
68 #define RT2 %r8
69 #define RT3 %r9
70
71 #define RT0d %ebp
72 #define RT1d %esi
73 #define RT2d %r8d
74 #define RT3d %r9d
75
76 #define RKEY %r10
77
78 /***********************************************************************
79  * 1-way blowfish
80  ***********************************************************************/
81 #define F() \
82         movzbl RX0bh,           RT1d; \
83         movzbl RX0bl,           RT3d; \
84         rorq $16,               RX0; \
85         movzbl RX0bh,           RT0d; \
86         movzbl RX0bl,           RT2d; \
87         rorq $16,               RX0; \
88         movl s0(CTX,RT0,4),     RT0d; \
89         addl s1(CTX,RT2,4),     RT0d; \
90         xorl s2(CTX,RT1,4),     RT0d; \
91         addl s3(CTX,RT3,4),     RT0d; \
92         xorq RT0,               RX0;
93
94 #define load_roundkey_enc(n) \
95         movq p+4*(n)(CTX),      RX3;
96
97 #define add_roundkey_enc() \
98         xorq RX3,               RX0;
99
100 #define round_enc(n) \
101         add_roundkey_enc(); \
102         load_roundkey_enc(n); \
103         \
104         F(); \
105         F();
106
107 #define load_roundkey_dec(n) \
108         movq p+4*(n-1)(CTX),    RX3; \
109         rorq $32,               RX3;
110
111 #define add_roundkey_dec() \
112         xorq RX3,               RX0;
113
114 #define round_dec(n) \
115         add_roundkey_dec(); \
116         load_roundkey_dec(n); \
117         \
118         F(); \
119         F();
120
121 #define read_block() \
122         movq (RIO),             RX0; \
123         rorq $32,               RX0; \
124         bswapq                  RX0;
125
126 #define write_block() \
127         bswapq                  RX0; \
128         movq RX0,               (RIO);
129
130 .align 8
131 ELF(.type   __blowfish_enc_blk1,@function;)
132
133 __blowfish_enc_blk1:
134         /* input:
135          *      %rdi: ctx, CTX
136          *      RX0: input plaintext block
137          * output:
138          *      RX0: output plaintext block
139          */
140         movq %rbp, %r11;
141
142         load_roundkey_enc(0);
143         round_enc(2);
144         round_enc(4);
145         round_enc(6);
146         round_enc(8);
147         round_enc(10);
148         round_enc(12);
149         round_enc(14);
150         round_enc(16);
151         add_roundkey_enc();
152
153         movq %r11, %rbp;
154
155         ret;
156 ELF(.size __blowfish_enc_blk1,.-__blowfish_enc_blk1;)
157
158 .align 8
159 .globl  _gcry_blowfish_amd64_do_encrypt
160 ELF(.type   _gcry_blowfish_amd64_do_encrypt,@function;)
161
162 _gcry_blowfish_amd64_do_encrypt:
163         /* input:
164          *      %rdi: ctx, CTX
165          *      %rsi: u32 *ret_xl
166          *      %rdx: u32 *ret_xr
167          */
168         movl (%rdx), RX0d;
169         shlq $32, RX0;
170         movl (%rsi), RT3d;
171         movq %rdx, %r10;
172         orq RT3, RX0;
173         movq %rsi, RX2;
174
175         call __blowfish_enc_blk1;
176
177         movl RX0d, (%r10);
178         shrq $32, RX0;
179         movl RX0d, (RX2);
180
181         ret;
182 ELF(.size _gcry_blowfish_amd64_do_encrypt,.-_gcry_blowfish_amd64_do_encrypt;)
183
184 .align 8
185 .globl  _gcry_blowfish_amd64_encrypt_block
186 ELF(.type   _gcry_blowfish_amd64_encrypt_block,@function;)
187
188 _gcry_blowfish_amd64_encrypt_block:
189         /* input:
190          *      %rdi: ctx, CTX
191          *      %rsi: dst
192          *      %rdx: src
193          */
194
195         movq %rsi, %r10;
196
197         movq %rdx, RIO;
198         read_block();
199
200         call __blowfish_enc_blk1;
201
202         movq %r10, RIO;
203         write_block();
204
205         ret;
206 ELF(.size _gcry_blowfish_amd64_encrypt_block,.-_gcry_blowfish_amd64_encrypt_block;)
207
208 .align 8
209 .globl  _gcry_blowfish_amd64_decrypt_block
210 ELF(.type   _gcry_blowfish_amd64_decrypt_block,@function;)
211
212 _gcry_blowfish_amd64_decrypt_block:
213         /* input:
214          *      %rdi: ctx, CTX
215          *      %rsi: dst
216          *      %rdx: src
217          */
218         movq %rbp, %r11;
219
220         movq %rsi, %r10;
221         movq %rdx, RIO;
222
223         read_block();
224
225         load_roundkey_dec(17);
226         round_dec(15);
227         round_dec(13);
228         round_dec(11);
229         round_dec(9);
230         round_dec(7);
231         round_dec(5);
232         round_dec(3);
233         round_dec(1);
234         add_roundkey_dec();
235
236         movq %r10, RIO;
237         write_block();
238
239         movq %r11, %rbp;
240
241         ret;
242 ELF(.size _gcry_blowfish_amd64_decrypt_block,.-_gcry_blowfish_amd64_decrypt_block;)
243
244 /**********************************************************************
245   4-way blowfish, four blocks parallel
246  **********************************************************************/
247 #define F4(x) \
248         movzbl x ## bh,         RT1d; \
249         movzbl x ## bl,         RT3d; \
250         rorq $16,               x; \
251         movzbl x ## bh,         RT0d; \
252         movzbl x ## bl,         RT2d; \
253         rorq $16,               x; \
254         movl s0(CTX,RT0,4),     RT0d; \
255         addl s1(CTX,RT2,4),     RT0d; \
256         xorl s2(CTX,RT1,4),     RT0d; \
257         addl s3(CTX,RT3,4),     RT0d; \
258         xorq RT0,               x;
259
260 #define add_preloaded_roundkey4() \
261         xorq RKEY,              RX0; \
262         xorq RKEY,              RX1; \
263         xorq RKEY,              RX2; \
264         xorq RKEY,              RX3;
265
266 #define preload_roundkey_enc(n) \
267         movq p+4*(n)(CTX),      RKEY;
268
269 #define add_roundkey_enc4(n) \
270         add_preloaded_roundkey4(); \
271         preload_roundkey_enc(n + 2);
272
273 #define round_enc4(n) \
274         add_roundkey_enc4(n); \
275         \
276         F4(RX0); \
277         F4(RX1); \
278         F4(RX2); \
279         F4(RX3); \
280         \
281         F4(RX0); \
282         F4(RX1); \
283         F4(RX2); \
284         F4(RX3);
285
286 #define preload_roundkey_dec(n) \
287         movq p+4*((n)-1)(CTX),  RKEY; \
288         rorq $32,               RKEY;
289
290 #define add_roundkey_dec4(n) \
291         add_preloaded_roundkey4(); \
292         preload_roundkey_dec(n - 2);
293
294 #define round_dec4(n) \
295         add_roundkey_dec4(n); \
296         \
297         F4(RX0); \
298         F4(RX1); \
299         F4(RX2); \
300         F4(RX3); \
301         \
302         F4(RX0); \
303         F4(RX1); \
304         F4(RX2); \
305         F4(RX3);
306
307 #define inbswap_block4() \
308         rorq $32,               RX0; \
309         bswapq                  RX0; \
310         rorq $32,               RX1; \
311         bswapq                  RX1; \
312         rorq $32,               RX2; \
313         bswapq                  RX2; \
314         rorq $32,               RX3; \
315         bswapq                  RX3;
316
317 #define inctrswap_block4() \
318         rorq $32,               RX0; \
319         rorq $32,               RX1; \
320         rorq $32,               RX2; \
321         rorq $32,               RX3;
322
323 #define outbswap_block4() \
324         bswapq                  RX0; \
325         bswapq                  RX1; \
326         bswapq                  RX2; \
327         bswapq                  RX3;
328
329 .align 8
330 ELF(.type   __blowfish_enc_blk4,@function;)
331
332 __blowfish_enc_blk4:
333         /* input:
334          *      %rdi: ctx, CTX
335          *      RX0,RX1,RX2,RX3: four input inbswapped plaintext blocks
336          * output:
337          *      RX0,RX1,RX2,RX3: four output ciphertext blocks
338          */
339         preload_roundkey_enc(0);
340
341         round_enc4(0);
342         round_enc4(2);
343         round_enc4(4);
344         round_enc4(6);
345         round_enc4(8);
346         round_enc4(10);
347         round_enc4(12);
348         round_enc4(14);
349         add_preloaded_roundkey4();
350
351         outbswap_block4();
352
353         ret;
354 ELF(.size __blowfish_enc_blk4,.-__blowfish_enc_blk4;)
355
356 .align 8
357 ELF(.type   __blowfish_dec_blk4,@function;)
358
359 __blowfish_dec_blk4:
360         /* input:
361          *      %rdi: ctx, CTX
362          *      RX0,RX1,RX2,RX3: four input ciphertext blocks
363          * output:
364          *      RX0,RX1,RX2,RX3: four output plaintext blocks
365          */
366         preload_roundkey_dec(17);
367
368         inbswap_block4();
369
370         round_dec4(17);
371         round_dec4(15);
372         round_dec4(13);
373         round_dec4(11);
374         round_dec4(9);
375         round_dec4(7);
376         round_dec4(5);
377         round_dec4(3);
378         add_preloaded_roundkey4();
379
380         outbswap_block4();
381
382         ret;
383 ELF(.size __blowfish_dec_blk4,.-__blowfish_dec_blk4;)
384
385 .align 8
386 .globl  _gcry_blowfish_amd64_ctr_enc
387 ELF(.type   _gcry_blowfish_amd64_ctr_enc,@function;)
388 _gcry_blowfish_amd64_ctr_enc:
389         /* input:
390          *      %rdi: ctx, CTX
391          *      %rsi: dst (4 blocks)
392          *      %rdx: src (4 blocks)
393          *      %rcx: iv (big endian, 64bit)
394          */
395         pushq %rbp;
396         pushq %rbx;
397         pushq %r12;
398         pushq %r13;
399
400         /* %r11-%r13 are not used by __blowfish_enc_blk4 */
401         movq %rcx, %r13; /*iv*/
402         movq %rdx, %r12; /*src*/
403         movq %rsi, %r11; /*dst*/
404
405         /* load IV and byteswap */
406         movq (%r13), RT0;
407         bswapq RT0;
408         movq RT0, RX0;
409
410         /* construct IVs */
411         leaq 1(RT0), RX1;
412         leaq 2(RT0), RX2;
413         leaq 3(RT0), RX3;
414         leaq 4(RT0), RT0;
415         bswapq RT0;
416
417         inctrswap_block4();
418
419         /* store new IV */
420         movq RT0, (%r13);
421
422         call __blowfish_enc_blk4;
423
424         /* XOR key-stream with plaintext */
425         xorq 0 * 8(%r12), RX0;
426         xorq 1 * 8(%r12), RX1;
427         xorq 2 * 8(%r12), RX2;
428         xorq 3 * 8(%r12), RX3;
429         movq RX0, 0 * 8(%r11);
430         movq RX1, 1 * 8(%r11);
431         movq RX2, 2 * 8(%r11);
432         movq RX3, 3 * 8(%r11);
433
434         popq %r13;
435         popq %r12;
436         popq %rbx;
437         popq %rbp;
438
439         ret;
440 ELF(.size _gcry_blowfish_amd64_ctr_enc,.-_gcry_blowfish_amd64_ctr_enc;)
441
442 .align 8
443 .globl  _gcry_blowfish_amd64_cbc_dec
444 ELF(.type   _gcry_blowfish_amd64_cbc_dec,@function;)
445 _gcry_blowfish_amd64_cbc_dec:
446         /* input:
447          *      %rdi: ctx, CTX
448          *      %rsi: dst (4 blocks)
449          *      %rdx: src (4 blocks)
450          *      %rcx: iv (64bit)
451          */
452         pushq %rbp;
453         pushq %rbx;
454         pushq %r12;
455         pushq %r13;
456
457         /* %r11-%r13 are not used by __blowfish_dec_blk4 */
458         movq %rsi, %r11; /*dst*/
459         movq %rdx, %r12; /*src*/
460         movq %rcx, %r13; /*iv*/
461
462         /* load input */
463         movq 0 * 8(%r12), RX0;
464         movq 1 * 8(%r12), RX1;
465         movq 2 * 8(%r12), RX2;
466         movq 3 * 8(%r12), RX3;
467
468         call __blowfish_dec_blk4;
469
470         movq 3 * 8(%r12), RT0;
471         xorq      (%r13), RX0;
472         xorq 0 * 8(%r12), RX1;
473         xorq 1 * 8(%r12), RX2;
474         xorq 2 * 8(%r12), RX3;
475         movq RT0, (%r13); /* store new IV */
476
477         movq RX0, 0 * 8(%r11);
478         movq RX1, 1 * 8(%r11);
479         movq RX2, 2 * 8(%r11);
480         movq RX3, 3 * 8(%r11);
481
482         popq %r13;
483         popq %r12;
484         popq %rbx;
485         popq %rbp;
486
487         ret;
488 ELF(.size _gcry_blowfish_amd64_cbc_dec,.-_gcry_blowfish_amd64_cbc_dec;)
489
490 .align 8
491 .globl  _gcry_blowfish_amd64_cfb_dec
492 ELF(.type   _gcry_blowfish_amd64_cfb_dec,@function;)
493 _gcry_blowfish_amd64_cfb_dec:
494         /* input:
495          *      %rdi: ctx, CTX
496          *      %rsi: dst (4 blocks)
497          *      %rdx: src (4 blocks)
498          *      %rcx: iv (64bit)
499          */
500         pushq %rbp;
501         pushq %rbx;
502         pushq %r12;
503         pushq %r13;
504
505         /* %r11-%r13 are not used by __blowfish_enc_blk4 */
506         movq %rcx, %r13; /*iv*/
507         movq %rdx, %r12; /*src*/
508         movq %rsi, %r11; /*dst*/
509
510         /* Load input */
511         movq (%r13), RX0;
512         movq 0 * 8(%r12), RX1;
513         movq 1 * 8(%r12), RX2;
514         movq 2 * 8(%r12), RX3;
515
516         inbswap_block4();
517
518         /* Update IV */
519         movq 3 * 8(%r12), RT0;
520         movq RT0, (%r13);
521
522         call __blowfish_enc_blk4;
523
524         xorq 0 * 8(%r12), RX0;
525         xorq 1 * 8(%r12), RX1;
526         xorq 2 * 8(%r12), RX2;
527         xorq 3 * 8(%r12), RX3;
528         movq RX0, 0 * 8(%r11);
529         movq RX1, 1 * 8(%r11);
530         movq RX2, 2 * 8(%r11);
531         movq RX3, 3 * 8(%r11);
532
533         popq %r13;
534         popq %r12;
535         popq %rbx;
536         popq %rbp;
537         ret;
538 ELF(.size _gcry_blowfish_amd64_cfb_dec,.-_gcry_blowfish_amd64_cfb_dec;)
539
540 #endif /*defined(USE_BLOWFISH)*/
541 #endif /*__x86_64*/