1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /***************************************************************************
3 * Copyright (C) 2006 by Joachim Fritschi, <jfritschi@freenet.de> *
5 ***************************************************************************/
7 .file "twofish-i586-asm.S"
10 #include <linux/linkage.h>
11 #include <asm/asm-offsets.h>
13 /* return address at 0 */
15 #define in_blk 12 /* input byte array address parameter*/
16 #define out_blk 8 /* output byte array address parameter*/
17 #define ctx 4 /* Twofish context structure */
24 /* Structure of the crypto context struct*/
26 #define s0 0 /* S0 Array 256 Words each */
27 #define s1 1024 /* S1 Array */
28 #define s2 2048 /* S2 Array */
29 #define s3 3072 /* S3 Array */
30 #define w 4096 /* 8 whitening keys (word) */
31 #define k 4128 /* key 1-32 ( word ) */
33 /* define a few register aliases to allow macro substitution */
52 /* performs input whitening */
53 #define input_whitening(src,context,offset)\
54 xor w+offset(context), src;
56 /* performs input whitening */
57 #define output_whitening(src,context,offset)\
58 xor w+16+offset(context), src;
61 * a input register containing a (rotated 16)
62 * b input register containing b
63 * c input register containing c
64 * d input register containing d (already rol $1)
65 * operations on a and b are interleaved to increase performance
67 #define encrypt_round(a,b,c,d,round)\
70 mov s1(%ebp,%edi,4),d ## D;\
72 mov s2(%ebp,%edi,4),%esi;\
75 xor s2(%ebp,%edi,4),d ## D;\
78 xor s3(%ebp,%edi,4),%esi;\
80 xor s3(%ebp,%edi,4),d ## D;\
82 xor (%ebp,%edi,4), %esi;\
85 xor (%ebp,%edi,4), d ## D;\
87 xor s1(%ebp,%edi,4),%esi;\
91 add k+round(%ebp), %esi;\
94 add k+4+round(%ebp),d ## D;\
98 * a input register containing a (rotated 16)
99 * b input register containing b
100 * c input register containing c
101 * d input register containing d (already rol $1)
102 * operations on a and b are interleaved to increase performance
103 * last round has different rotations for the output preparation
105 #define encrypt_last_round(a,b,c,d,round)\
108 mov s1(%ebp,%edi,4),d ## D;\
110 mov s2(%ebp,%edi,4),%esi;\
113 xor s2(%ebp,%edi,4),d ## D;\
116 xor s3(%ebp,%edi,4),%esi;\
118 xor s3(%ebp,%edi,4),d ## D;\
120 xor (%ebp,%edi,4), %esi;\
123 xor (%ebp,%edi,4), d ## D;\
125 xor s1(%ebp,%edi,4),%esi;\
129 add k+round(%ebp), %esi;\
132 add k+4+round(%ebp),d ## D;\
136 * a input register containing a
137 * b input register containing b (rotated 16)
138 * c input register containing c
139 * d input register containing d (already rol $1)
140 * operations on a and b are interleaved to increase performance
142 #define decrypt_round(a,b,c,d,round)\
145 mov (%ebp,%edi,4), c ## D;\
147 mov s3(%ebp,%edi,4),%esi;\
150 xor s1(%ebp,%edi,4),c ## D;\
153 xor (%ebp,%edi,4), %esi;\
155 xor s2(%ebp,%edi,4),c ## D;\
157 xor s1(%ebp,%edi,4),%esi;\
160 xor s3(%ebp,%edi,4),c ## D;\
162 xor s2(%ebp,%edi,4),%esi;\
166 add k+round(%ebp), c ## D;\
168 add k+4+round(%ebp),%esi;\
173 * a input register containing a
174 * b input register containing b (rotated 16)
175 * c input register containing c
176 * d input register containing d (already rol $1)
177 * operations on a and b are interleaved to increase performance
178 * last round has different rotations for the output preparation
180 #define decrypt_last_round(a,b,c,d,round)\
183 mov (%ebp,%edi,4), c ## D;\
185 mov s3(%ebp,%edi,4),%esi;\
188 xor s1(%ebp,%edi,4),c ## D;\
191 xor (%ebp,%edi,4), %esi;\
193 xor s2(%ebp,%edi,4),c ## D;\
195 xor s1(%ebp,%edi,4),%esi;\
198 xor s3(%ebp,%edi,4),c ## D;\
200 xor s2(%ebp,%edi,4),%esi;\
204 add k+round(%ebp), c ## D;\
206 add k+4+round(%ebp),%esi;\
210 SYM_FUNC_START(twofish_enc_blk)
211 push %ebp /* save registers according to calling convention*/
216 mov ctx + 16(%esp), %ebp /* abuse the base pointer: set new base
217 * pointer to the ctx address */
218 mov in_blk+16(%esp),%edi /* input address in edi */
221 mov b_offset(%edi), %ebx
222 mov c_offset(%edi), %ecx
223 mov d_offset(%edi), %edx
224 input_whitening(%eax,%ebp,a_offset)
226 input_whitening(%ebx,%ebp,b_offset)
227 input_whitening(%ecx,%ebp,c_offset)
228 input_whitening(%edx,%ebp,d_offset)
231 encrypt_round(R0,R1,R2,R3,0);
232 encrypt_round(R2,R3,R0,R1,8);
233 encrypt_round(R0,R1,R2,R3,2*8);
234 encrypt_round(R2,R3,R0,R1,3*8);
235 encrypt_round(R0,R1,R2,R3,4*8);
236 encrypt_round(R2,R3,R0,R1,5*8);
237 encrypt_round(R0,R1,R2,R3,6*8);
238 encrypt_round(R2,R3,R0,R1,7*8);
239 encrypt_round(R0,R1,R2,R3,8*8);
240 encrypt_round(R2,R3,R0,R1,9*8);
241 encrypt_round(R0,R1,R2,R3,10*8);
242 encrypt_round(R2,R3,R0,R1,11*8);
243 encrypt_round(R0,R1,R2,R3,12*8);
244 encrypt_round(R2,R3,R0,R1,13*8);
245 encrypt_round(R0,R1,R2,R3,14*8);
246 encrypt_last_round(R2,R3,R0,R1,15*8);
248 output_whitening(%eax,%ebp,c_offset)
249 output_whitening(%ebx,%ebp,d_offset)
250 output_whitening(%ecx,%ebp,a_offset)
251 output_whitening(%edx,%ebp,b_offset)
252 mov out_blk+16(%esp),%edi;
253 mov %eax, c_offset(%edi)
254 mov %ebx, d_offset(%edi)
256 mov %edx, b_offset(%edi)
264 SYM_FUNC_END(twofish_enc_blk)
266 SYM_FUNC_START(twofish_dec_blk)
267 push %ebp /* save registers according to calling convention*/
273 mov ctx + 16(%esp), %ebp /* abuse the base pointer: set new base
274 * pointer to the ctx address */
275 mov in_blk+16(%esp),%edi /* input address in edi */
278 mov b_offset(%edi), %ebx
279 mov c_offset(%edi), %ecx
280 mov d_offset(%edi), %edx
281 output_whitening(%eax,%ebp,a_offset)
282 output_whitening(%ebx,%ebp,b_offset)
284 output_whitening(%ecx,%ebp,c_offset)
285 output_whitening(%edx,%ebp,d_offset)
288 decrypt_round(R0,R1,R2,R3,15*8);
289 decrypt_round(R2,R3,R0,R1,14*8);
290 decrypt_round(R0,R1,R2,R3,13*8);
291 decrypt_round(R2,R3,R0,R1,12*8);
292 decrypt_round(R0,R1,R2,R3,11*8);
293 decrypt_round(R2,R3,R0,R1,10*8);
294 decrypt_round(R0,R1,R2,R3,9*8);
295 decrypt_round(R2,R3,R0,R1,8*8);
296 decrypt_round(R0,R1,R2,R3,7*8);
297 decrypt_round(R2,R3,R0,R1,6*8);
298 decrypt_round(R0,R1,R2,R3,5*8);
299 decrypt_round(R2,R3,R0,R1,4*8);
300 decrypt_round(R0,R1,R2,R3,3*8);
301 decrypt_round(R2,R3,R0,R1,2*8);
302 decrypt_round(R0,R1,R2,R3,1*8);
303 decrypt_last_round(R2,R3,R0,R1,0);
305 input_whitening(%eax,%ebp,c_offset)
306 input_whitening(%ebx,%ebp,d_offset)
307 input_whitening(%ecx,%ebp,a_offset)
308 input_whitening(%edx,%ebp,b_offset)
309 mov out_blk+16(%esp),%edi;
310 mov %eax, c_offset(%edi)
311 mov %ebx, d_offset(%edi)
313 mov %edx, b_offset(%edi)
321 SYM_FUNC_END(twofish_dec_blk)