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