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