xref: /openbmc/linux/arch/x86/crypto/twofish-x86_64-asm_64-3way.S (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
11a59d1b8SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
28280daadSJussi Kivilinna/*
38280daadSJussi Kivilinna * Twofish Cipher 3-way parallel algorithm (x86_64)
48280daadSJussi Kivilinna *
58280daadSJussi Kivilinna * Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
68280daadSJussi Kivilinna */
78280daadSJussi Kivilinna
8d3f5188dSJussi Kivilinna#include <linux/linkage.h>
9d3f5188dSJussi Kivilinna
108280daadSJussi Kivilinna.file "twofish-x86_64-asm-3way.S"
118280daadSJussi Kivilinna.text
128280daadSJussi Kivilinna
138280daadSJussi Kivilinna/* structure of crypto context */
148280daadSJussi Kivilinna#define s0	0
158280daadSJussi Kivilinna#define s1	1024
168280daadSJussi Kivilinna#define s2	2048
178280daadSJussi Kivilinna#define s3	3072
188280daadSJussi Kivilinna#define w	4096
198280daadSJussi Kivilinna#define k	4128
208280daadSJussi Kivilinna
218280daadSJussi Kivilinna/**********************************************************************
228280daadSJussi Kivilinna  3-way twofish
238280daadSJussi Kivilinna **********************************************************************/
248280daadSJussi Kivilinna#define CTX %rdi
258280daadSJussi Kivilinna#define RIO %rdx
268280daadSJussi Kivilinna
278280daadSJussi Kivilinna#define RAB0 %rax
288280daadSJussi Kivilinna#define RAB1 %rbx
298280daadSJussi Kivilinna#define RAB2 %rcx
308280daadSJussi Kivilinna
318280daadSJussi Kivilinna#define RAB0d %eax
328280daadSJussi Kivilinna#define RAB1d %ebx
338280daadSJussi Kivilinna#define RAB2d %ecx
348280daadSJussi Kivilinna
358280daadSJussi Kivilinna#define RAB0bh %ah
368280daadSJussi Kivilinna#define RAB1bh %bh
378280daadSJussi Kivilinna#define RAB2bh %ch
388280daadSJussi Kivilinna
398280daadSJussi Kivilinna#define RAB0bl %al
408280daadSJussi Kivilinna#define RAB1bl %bl
418280daadSJussi Kivilinna#define RAB2bl %cl
428280daadSJussi Kivilinna
43d8c7fe9fSEric Biggers#define CD0 0x0(%rsp)
44d8c7fe9fSEric Biggers#define CD1 0x8(%rsp)
45d8c7fe9fSEric Biggers#define CD2 0x10(%rsp)
46d8c7fe9fSEric Biggers
47d8c7fe9fSEric Biggers# used only before/after all rounds
488280daadSJussi Kivilinna#define RCD0 %r8
498280daadSJussi Kivilinna#define RCD1 %r9
508280daadSJussi Kivilinna#define RCD2 %r10
518280daadSJussi Kivilinna
52d8c7fe9fSEric Biggers# used only during rounds
53d8c7fe9fSEric Biggers#define RX0 %r8
54d8c7fe9fSEric Biggers#define RX1 %r9
55d8c7fe9fSEric Biggers#define RX2 %r10
568280daadSJussi Kivilinna
57d8c7fe9fSEric Biggers#define RX0d %r8d
58d8c7fe9fSEric Biggers#define RX1d %r9d
59d8c7fe9fSEric Biggers#define RX2d %r10d
608280daadSJussi Kivilinna
61d8c7fe9fSEric Biggers#define RY0 %r11
62d8c7fe9fSEric Biggers#define RY1 %r12
63d8c7fe9fSEric Biggers#define RY2 %r13
648280daadSJussi Kivilinna
65d8c7fe9fSEric Biggers#define RY0d %r11d
66d8c7fe9fSEric Biggers#define RY1d %r12d
67d8c7fe9fSEric Biggers#define RY2d %r13d
688280daadSJussi Kivilinna
698280daadSJussi Kivilinna#define RT0 %rdx
708280daadSJussi Kivilinna#define RT1 %rsi
718280daadSJussi Kivilinna
728280daadSJussi Kivilinna#define RT0d %edx
738280daadSJussi Kivilinna#define RT1d %esi
748280daadSJussi Kivilinna
75d8c7fe9fSEric Biggers#define RT1bl %sil
76d8c7fe9fSEric Biggers
778280daadSJussi Kivilinna#define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
788280daadSJussi Kivilinna	movzbl ab ## bl,		tmp2 ## d; \
798280daadSJussi Kivilinna	movzbl ab ## bh,		tmp1 ## d; \
808280daadSJussi Kivilinna	rorq $(rot),			ab; \
818280daadSJussi Kivilinna	op1##l T0(CTX, tmp2, 4),	dst ## d; \
828280daadSJussi Kivilinna	op2##l T1(CTX, tmp1, 4),	dst ## d;
838280daadSJussi Kivilinna
84d8c7fe9fSEric Biggers#define swap_ab_with_cd(ab, cd, tmp)	\
85d8c7fe9fSEric Biggers	movq cd, tmp;			\
86d8c7fe9fSEric Biggers	movq ab, cd;			\
87d8c7fe9fSEric Biggers	movq tmp, ab;
88d8c7fe9fSEric Biggers
898280daadSJussi Kivilinna/*
908280daadSJussi Kivilinna * Combined G1 & G2 function. Reordered with help of rotates to have moves
91163b0991SIngo Molnar * at beginning.
928280daadSJussi Kivilinna */
938280daadSJussi Kivilinna#define g1g2_3(ab, cd, Tx0, Tx1, Tx2, Tx3, Ty0, Ty1, Ty2, Ty3, x, y) \
948280daadSJussi Kivilinna	/* G1,1 && G2,1 */ \
958280daadSJussi Kivilinna	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 0, ab ## 0, x ## 0); \
968280daadSJussi Kivilinna	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 0, ab ## 0, y ## 0); \
978280daadSJussi Kivilinna	\
988280daadSJussi Kivilinna	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 1, ab ## 1, x ## 1); \
998280daadSJussi Kivilinna	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 1, ab ## 1, y ## 1); \
1008280daadSJussi Kivilinna	\
1018280daadSJussi Kivilinna	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 2, ab ## 2, x ## 2); \
1028280daadSJussi Kivilinna	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 2, ab ## 2, y ## 2); \
1038280daadSJussi Kivilinna	\
1048280daadSJussi Kivilinna	/* G1,2 && G2,2 */ \
1058280daadSJussi Kivilinna	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
1068280daadSJussi Kivilinna	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
107d8c7fe9fSEric Biggers	swap_ab_with_cd(ab ## 0, cd ## 0, RT0); \
1088280daadSJussi Kivilinna	\
1098280daadSJussi Kivilinna	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
1108280daadSJussi Kivilinna	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
111d8c7fe9fSEric Biggers	swap_ab_with_cd(ab ## 1, cd ## 1, RT0); \
1128280daadSJussi Kivilinna	\
1138280daadSJussi Kivilinna	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
1148280daadSJussi Kivilinna	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
115d8c7fe9fSEric Biggers	swap_ab_with_cd(ab ## 2, cd ## 2, RT0);
1168280daadSJussi Kivilinna
1178280daadSJussi Kivilinna#define enc_round_end(ab, x, y, n) \
1188280daadSJussi Kivilinna	addl y ## d,			x ## d; \
1198280daadSJussi Kivilinna	addl x ## d,			y ## d; \
1208280daadSJussi Kivilinna	addl k+4*(2*(n))(CTX),		x ## d; \
1218280daadSJussi Kivilinna	xorl ab ## d,			x ## d; \
1228280daadSJussi Kivilinna	addl k+4*(2*(n)+1)(CTX),	y ## d; \
1238280daadSJussi Kivilinna	shrq $32,			ab; \
1248280daadSJussi Kivilinna	roll $1,			ab ## d; \
1258280daadSJussi Kivilinna	xorl y ## d,			ab ## d; \
1268280daadSJussi Kivilinna	shlq $32,			ab; \
1278280daadSJussi Kivilinna	rorl $1,			x ## d; \
1288280daadSJussi Kivilinna	orq x,				ab;
1298280daadSJussi Kivilinna
1308280daadSJussi Kivilinna#define dec_round_end(ba, x, y, n) \
1318280daadSJussi Kivilinna	addl y ## d,			x ## d; \
1328280daadSJussi Kivilinna	addl x ## d,			y ## d; \
1338280daadSJussi Kivilinna	addl k+4*(2*(n))(CTX),		x ## d; \
1348280daadSJussi Kivilinna	addl k+4*(2*(n)+1)(CTX),	y ## d; \
1358280daadSJussi Kivilinna	xorl ba ## d,			y ## d; \
1368280daadSJussi Kivilinna	shrq $32,			ba; \
1378280daadSJussi Kivilinna	roll $1,			ba ## d; \
1388280daadSJussi Kivilinna	xorl x ## d,			ba ## d; \
1398280daadSJussi Kivilinna	shlq $32,			ba; \
1408280daadSJussi Kivilinna	rorl $1,			y ## d; \
1418280daadSJussi Kivilinna	orq y,				ba;
1428280daadSJussi Kivilinna
1438280daadSJussi Kivilinna#define encrypt_round3(ab, cd, n) \
1448280daadSJussi Kivilinna	g1g2_3(ab, cd, s0, s1, s2, s3, s0, s1, s2, s3, RX, RY); \
1458280daadSJussi Kivilinna	\
1468280daadSJussi Kivilinna	enc_round_end(ab ## 0, RX0, RY0, n); \
1478280daadSJussi Kivilinna	enc_round_end(ab ## 1, RX1, RY1, n); \
1488280daadSJussi Kivilinna	enc_round_end(ab ## 2, RX2, RY2, n);
1498280daadSJussi Kivilinna
1508280daadSJussi Kivilinna#define decrypt_round3(ba, dc, n) \
1518280daadSJussi Kivilinna	g1g2_3(ba, dc, s1, s2, s3, s0, s3, s0, s1, s2, RY, RX); \
1528280daadSJussi Kivilinna	\
1538280daadSJussi Kivilinna	dec_round_end(ba ## 0, RX0, RY0, n); \
1548280daadSJussi Kivilinna	dec_round_end(ba ## 1, RX1, RY1, n); \
1558280daadSJussi Kivilinna	dec_round_end(ba ## 2, RX2, RY2, n);
1568280daadSJussi Kivilinna
1578280daadSJussi Kivilinna#define encrypt_cycle3(ab, cd, n) \
1588280daadSJussi Kivilinna	encrypt_round3(ab, cd, n*2); \
1598280daadSJussi Kivilinna	encrypt_round3(ab, cd, (n*2)+1);
1608280daadSJussi Kivilinna
1618280daadSJussi Kivilinna#define decrypt_cycle3(ba, dc, n) \
1628280daadSJussi Kivilinna	decrypt_round3(ba, dc, (n*2)+1); \
1638280daadSJussi Kivilinna	decrypt_round3(ba, dc, (n*2));
1648280daadSJussi Kivilinna
165d8c7fe9fSEric Biggers#define push_cd()	\
166d8c7fe9fSEric Biggers	pushq RCD2;	\
167d8c7fe9fSEric Biggers	pushq RCD1;	\
168d8c7fe9fSEric Biggers	pushq RCD0;
169d8c7fe9fSEric Biggers
170d8c7fe9fSEric Biggers#define pop_cd()	\
171d8c7fe9fSEric Biggers	popq RCD0;	\
172d8c7fe9fSEric Biggers	popq RCD1;	\
173d8c7fe9fSEric Biggers	popq RCD2;
174d8c7fe9fSEric Biggers
1758280daadSJussi Kivilinna#define inpack3(in, n, xy, m) \
1768280daadSJussi Kivilinna	movq 4*(n)(in),			xy ## 0; \
1778280daadSJussi Kivilinna	xorq w+4*m(CTX),		xy ## 0; \
1788280daadSJussi Kivilinna	\
1798280daadSJussi Kivilinna	movq 4*(4+(n))(in),		xy ## 1; \
1808280daadSJussi Kivilinna	xorq w+4*m(CTX),		xy ## 1; \
1818280daadSJussi Kivilinna	\
1828280daadSJussi Kivilinna	movq 4*(8+(n))(in),		xy ## 2; \
1838280daadSJussi Kivilinna	xorq w+4*m(CTX),		xy ## 2;
1848280daadSJussi Kivilinna
1858280daadSJussi Kivilinna#define outunpack3(op, out, n, xy, m) \
1868280daadSJussi Kivilinna	xorq w+4*m(CTX),		xy ## 0; \
1878280daadSJussi Kivilinna	op ## q xy ## 0,		4*(n)(out); \
1888280daadSJussi Kivilinna	\
1898280daadSJussi Kivilinna	xorq w+4*m(CTX),		xy ## 1; \
1908280daadSJussi Kivilinna	op ## q xy ## 1,		4*(4+(n))(out); \
1918280daadSJussi Kivilinna	\
1928280daadSJussi Kivilinna	xorq w+4*m(CTX),		xy ## 2; \
1938280daadSJussi Kivilinna	op ## q xy ## 2,		4*(8+(n))(out);
1948280daadSJussi Kivilinna
1958280daadSJussi Kivilinna#define inpack_enc3() \
1968280daadSJussi Kivilinna	inpack3(RIO, 0, RAB, 0); \
1978280daadSJussi Kivilinna	inpack3(RIO, 2, RCD, 2);
1988280daadSJussi Kivilinna
1998280daadSJussi Kivilinna#define outunpack_enc3(op) \
2008280daadSJussi Kivilinna	outunpack3(op, RIO, 2, RAB, 6); \
2018280daadSJussi Kivilinna	outunpack3(op, RIO, 0, RCD, 4);
2028280daadSJussi Kivilinna
2038280daadSJussi Kivilinna#define inpack_dec3() \
2048280daadSJussi Kivilinna	inpack3(RIO, 0, RAB, 4); \
2058280daadSJussi Kivilinna	rorq $32,			RAB0; \
2068280daadSJussi Kivilinna	rorq $32,			RAB1; \
2078280daadSJussi Kivilinna	rorq $32,			RAB2; \
2088280daadSJussi Kivilinna	inpack3(RIO, 2, RCD, 6); \
2098280daadSJussi Kivilinna	rorq $32,			RCD0; \
2108280daadSJussi Kivilinna	rorq $32,			RCD1; \
2118280daadSJussi Kivilinna	rorq $32,			RCD2;
2128280daadSJussi Kivilinna
2138280daadSJussi Kivilinna#define outunpack_dec3() \
2148280daadSJussi Kivilinna	rorq $32,			RCD0; \
2158280daadSJussi Kivilinna	rorq $32,			RCD1; \
2168280daadSJussi Kivilinna	rorq $32,			RCD2; \
2178280daadSJussi Kivilinna	outunpack3(mov, RIO, 0, RCD, 0); \
2188280daadSJussi Kivilinna	rorq $32,			RAB0; \
2198280daadSJussi Kivilinna	rorq $32,			RAB1; \
2208280daadSJussi Kivilinna	rorq $32,			RAB2; \
2218280daadSJussi Kivilinna	outunpack3(mov, RIO, 2, RAB, 2);
2228280daadSJussi Kivilinna
2236dcc5627SJiri SlabySYM_FUNC_START(__twofish_enc_blk_3way)
2248280daadSJussi Kivilinna	/* input:
2258280daadSJussi Kivilinna	 *	%rdi: ctx, CTX
2268280daadSJussi Kivilinna	 *	%rsi: dst
2278280daadSJussi Kivilinna	 *	%rdx: src, RIO
2288280daadSJussi Kivilinna	 *	%rcx: bool, if true: xor output
2298280daadSJussi Kivilinna	 */
2308280daadSJussi Kivilinna	pushq %r13;
2318280daadSJussi Kivilinna	pushq %r12;
2328280daadSJussi Kivilinna	pushq %rbx;
2338280daadSJussi Kivilinna
2348280daadSJussi Kivilinna	pushq %rcx; /* bool xor */
2358280daadSJussi Kivilinna	pushq %rsi; /* dst */
2368280daadSJussi Kivilinna
2378280daadSJussi Kivilinna	inpack_enc3();
2388280daadSJussi Kivilinna
239d8c7fe9fSEric Biggers	push_cd();
240d8c7fe9fSEric Biggers	encrypt_cycle3(RAB, CD, 0);
241d8c7fe9fSEric Biggers	encrypt_cycle3(RAB, CD, 1);
242d8c7fe9fSEric Biggers	encrypt_cycle3(RAB, CD, 2);
243d8c7fe9fSEric Biggers	encrypt_cycle3(RAB, CD, 3);
244d8c7fe9fSEric Biggers	encrypt_cycle3(RAB, CD, 4);
245d8c7fe9fSEric Biggers	encrypt_cycle3(RAB, CD, 5);
246d8c7fe9fSEric Biggers	encrypt_cycle3(RAB, CD, 6);
247d8c7fe9fSEric Biggers	encrypt_cycle3(RAB, CD, 7);
248d8c7fe9fSEric Biggers	pop_cd();
2498280daadSJussi Kivilinna
2508280daadSJussi Kivilinna	popq RIO; /* dst */
251d8c7fe9fSEric Biggers	popq RT1; /* bool xor */
2528280daadSJussi Kivilinna
253d8c7fe9fSEric Biggers	testb RT1bl, RT1bl;
254d3f5188dSJussi Kivilinna	jnz .L__enc_xor3;
2558280daadSJussi Kivilinna
2568280daadSJussi Kivilinna	outunpack_enc3(mov);
2578280daadSJussi Kivilinna
2588280daadSJussi Kivilinna	popq %rbx;
2598280daadSJussi Kivilinna	popq %r12;
2608280daadSJussi Kivilinna	popq %r13;
261*f94909ceSPeter Zijlstra	RET;
2628280daadSJussi Kivilinna
263d3f5188dSJussi Kivilinna.L__enc_xor3:
2648280daadSJussi Kivilinna	outunpack_enc3(xor);
2658280daadSJussi Kivilinna
2668280daadSJussi Kivilinna	popq %rbx;
2678280daadSJussi Kivilinna	popq %r12;
2688280daadSJussi Kivilinna	popq %r13;
269*f94909ceSPeter Zijlstra	RET;
2706dcc5627SJiri SlabySYM_FUNC_END(__twofish_enc_blk_3way)
2718280daadSJussi Kivilinna
2726dcc5627SJiri SlabySYM_FUNC_START(twofish_dec_blk_3way)
2738280daadSJussi Kivilinna	/* input:
2748280daadSJussi Kivilinna	 *	%rdi: ctx, CTX
2758280daadSJussi Kivilinna	 *	%rsi: dst
2768280daadSJussi Kivilinna	 *	%rdx: src, RIO
2778280daadSJussi Kivilinna	 */
2788280daadSJussi Kivilinna	pushq %r13;
2798280daadSJussi Kivilinna	pushq %r12;
2808280daadSJussi Kivilinna	pushq %rbx;
2818280daadSJussi Kivilinna
2828280daadSJussi Kivilinna	pushq %rsi; /* dst */
2838280daadSJussi Kivilinna
2848280daadSJussi Kivilinna	inpack_dec3();
2858280daadSJussi Kivilinna
286d8c7fe9fSEric Biggers	push_cd();
287d8c7fe9fSEric Biggers	decrypt_cycle3(RAB, CD, 7);
288d8c7fe9fSEric Biggers	decrypt_cycle3(RAB, CD, 6);
289d8c7fe9fSEric Biggers	decrypt_cycle3(RAB, CD, 5);
290d8c7fe9fSEric Biggers	decrypt_cycle3(RAB, CD, 4);
291d8c7fe9fSEric Biggers	decrypt_cycle3(RAB, CD, 3);
292d8c7fe9fSEric Biggers	decrypt_cycle3(RAB, CD, 2);
293d8c7fe9fSEric Biggers	decrypt_cycle3(RAB, CD, 1);
294d8c7fe9fSEric Biggers	decrypt_cycle3(RAB, CD, 0);
295d8c7fe9fSEric Biggers	pop_cd();
2968280daadSJussi Kivilinna
2978280daadSJussi Kivilinna	popq RIO; /* dst */
2988280daadSJussi Kivilinna
2998280daadSJussi Kivilinna	outunpack_dec3();
3008280daadSJussi Kivilinna
3018280daadSJussi Kivilinna	popq %rbx;
3028280daadSJussi Kivilinna	popq %r12;
3038280daadSJussi Kivilinna	popq %r13;
304*f94909ceSPeter Zijlstra	RET;
3056dcc5627SJiri SlabySYM_FUNC_END(twofish_dec_blk_3way)
306