1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /***************************************************************************
3 * Copyright (C) 2006 by Joachim Fritschi, <jfritschi@freenet.de> *
5 ***************************************************************************/
7 .file "twofish-x86_64-asm.S"
10 #include <linux/linkage.h>
11 #include <asm/asm-offsets.h>
18 /* Structure of the crypto context struct*/
20 #define s0 0 /* S0 Array 256 Words each */
21 #define s1 1024 /* S1 Array */
22 #define s2 2048 /* S2 Array */
23 #define s3 3072 /* S3 Array */
24 #define w 4096 /* 8 whitening keys (word) */
25 #define k 4128 /* key 1-32 ( word ) */
27 /* define a few register aliases to allow macro substitution */
50 /* performs input whitening */
51 #define input_whitening(src,context,offset)\
52 xor w+offset(context), src;
54 /* performs input whitening */
55 #define output_whitening(src,context,offset)\
56 xor w+16+offset(context), src;
60 * a input register containing a (rotated 16)
61 * b input register containing b
62 * c input register containing c
63 * d input register containing d (already rol $1)
64 * operations on a and b are interleaved to increase performance
66 #define encrypt_round(a,b,c,d,round)\
68 mov s1(%r11,%rdi,4),%r8d;\
70 mov s2(%r11,%rdi,4),%r9d;\
73 xor s2(%r11,%rdi,4),%r8d;\
76 xor s3(%r11,%rdi,4),%r9d;\
78 xor s3(%r11,%rdi,4),%r8d;\
80 xor (%r11,%rdi,4), %r9d;\
83 xor (%r11,%rdi,4), %r8d;\
85 xor s1(%r11,%rdi,4),%r9d;\
88 add k+round(%r11), %r9d;\
91 add k+4+round(%r11),%r8d;\
95 * a input register containing a(rotated 16)
96 * b input register containing b
97 * c input register containing c
98 * d input register containing d (already rol $1)
99 * operations on a and b are interleaved to increase performance
100 * during the round a and b are prepared for the output whitening
102 #define encrypt_last_round(a,b,c,d,round)\
106 mov s1(%r11,%rdi,4),%r8d;\
108 mov s2(%r11,%rdi,4),%r9d;\
111 xor s2(%r11,%rdi,4),%r8d;\
114 xor s3(%r11,%rdi,4),%r9d;\
116 xor s3(%r11,%rdi,4),%r8d;\
118 xor (%r11,%rdi,4), %r9d;\
121 xor (%r11,%rdi,4), %r8d;\
123 xor s1(%r11,%rdi,4),%r9d;\
126 add k+round(%r11), %r9d;\
129 add k+4+round(%r11),%r8d;\
133 * a input register containing a
134 * b input register containing b (rotated 16)
135 * c input register containing c (already rol $1)
136 * d input register containing d
137 * operations on a and b are interleaved to increase performance
139 #define decrypt_round(a,b,c,d,round)\
141 mov (%r11,%rdi,4), %r9d;\
143 mov s3(%r11,%rdi,4),%r8d;\
146 xor s1(%r11,%rdi,4),%r9d;\
149 xor (%r11,%rdi,4), %r8d;\
151 xor s2(%r11,%rdi,4),%r9d;\
153 xor s1(%r11,%rdi,4),%r8d;\
156 xor s3(%r11,%rdi,4),%r9d;\
158 xor s2(%r11,%rdi,4),%r8d;\
161 add k+round(%r11), %r9d;\
163 add k+4+round(%r11),%r8d;\
168 * a input register containing a
169 * b input register containing b
170 * c input register containing c (already rol $1)
171 * d input register containing d
172 * operations on a and b are interleaved to increase performance
173 * during the round a and b are prepared for the output whitening
175 #define decrypt_last_round(a,b,c,d,round)\
177 mov (%r11,%rdi,4), %r9d;\
179 mov s3(%r11,%rdi,4),%r8d;\
182 xor (%r11,%rdi,4), %r8d;\
188 xor s1(%r11,%rdi,4),%r9d;\
190 xor s1(%r11,%rdi,4),%r8d;\
192 xor s2(%r11,%rdi,4),%r9d;\
194 xor s2(%r11,%rdi,4),%r8d;\
196 xor s3(%r11,%rdi,4),%r9d;\
199 add k+round(%r11), %r9d;\
201 add k+4+round(%r11),%r8d;\
205 SYM_FUNC_START(twofish_enc_blk)
208 /* %rdi contains the ctx address */
209 /* %rsi contains the output address */
210 /* %rdx contains the input address */
211 /* ctx address is moved to free one non-rex register
212 as target for the 8bit high operations */
217 input_whitening(R1,%r11,a_offset)
218 input_whitening(R3,%r11,c_offset)
226 encrypt_round(R0,R1,R2,R3,0);
227 encrypt_round(R2,R3,R0,R1,8);
228 encrypt_round(R0,R1,R2,R3,2*8);
229 encrypt_round(R2,R3,R0,R1,3*8);
230 encrypt_round(R0,R1,R2,R3,4*8);
231 encrypt_round(R2,R3,R0,R1,5*8);
232 encrypt_round(R0,R1,R2,R3,6*8);
233 encrypt_round(R2,R3,R0,R1,7*8);
234 encrypt_round(R0,R1,R2,R3,8*8);
235 encrypt_round(R2,R3,R0,R1,9*8);
236 encrypt_round(R0,R1,R2,R3,10*8);
237 encrypt_round(R2,R3,R0,R1,11*8);
238 encrypt_round(R0,R1,R2,R3,12*8);
239 encrypt_round(R2,R3,R0,R1,13*8);
240 encrypt_round(R0,R1,R2,R3,14*8);
241 encrypt_last_round(R2,R3,R0,R1,15*8);
244 output_whitening(%r10,%r11,a_offset)
250 output_whitening(R1,%r11,c_offset)
256 SYM_FUNC_END(twofish_enc_blk)
258 SYM_FUNC_START(twofish_dec_blk)
261 /* %rdi contains the ctx address */
262 /* %rsi contains the output address */
263 /* %rdx contains the input address */
264 /* ctx address is moved to free one non-rex register
265 as target for the 8bit high operations */
270 output_whitening(R1,%r11,a_offset)
271 output_whitening(R3,%r11,c_offset)
279 decrypt_round(R0,R1,R2,R3,15*8);
280 decrypt_round(R2,R3,R0,R1,14*8);
281 decrypt_round(R0,R1,R2,R3,13*8);
282 decrypt_round(R2,R3,R0,R1,12*8);
283 decrypt_round(R0,R1,R2,R3,11*8);
284 decrypt_round(R2,R3,R0,R1,10*8);
285 decrypt_round(R0,R1,R2,R3,9*8);
286 decrypt_round(R2,R3,R0,R1,8*8);
287 decrypt_round(R0,R1,R2,R3,7*8);
288 decrypt_round(R2,R3,R0,R1,6*8);
289 decrypt_round(R0,R1,R2,R3,5*8);
290 decrypt_round(R2,R3,R0,R1,4*8);
291 decrypt_round(R0,R1,R2,R3,3*8);
292 decrypt_round(R2,R3,R0,R1,2*8);
293 decrypt_round(R0,R1,R2,R3,1*8);
294 decrypt_last_round(R2,R3,R0,R1,0);
296 input_whitening(%r10,%r11,a_offset)
302 input_whitening(R1,%r11,c_offset)
308 SYM_FUNC_END(twofish_dec_blk)