1 /***************************************************************************
2 * Copyright (C) 2006 by Joachim Fritschi, <jfritschi@freenet.de> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
20 .file "twofish-x86_64-asm.S"
23 #include <asm/asm-offsets.h>
30 /* Structure of the crypto context struct*/
32 #define s0 0 /* S0 Array 256 Words each */
33 #define s1 1024 /* S1 Array */
34 #define s2 2048 /* S2 Array */
35 #define s3 3072 /* S3 Array */
36 #define w 4096 /* 8 whitening keys (word) */
37 #define k 4128 /* key 1-32 ( word ) */
39 /* define a few register aliases to allow macro substitution */
62 /* performs input whitening */
63 #define input_whitening(src,context,offset)\
64 xor w+offset(context), src;
66 /* performs input whitening */
67 #define output_whitening(src,context,offset)\
68 xor w+16+offset(context), src;
72 * a input register containing a (rotated 16)
73 * b input register containing b
74 * c input register containing c
75 * d input register containing d (already rol $1)
76 * operations on a and b are interleaved to increase performance
78 #define encrypt_round(a,b,c,d,round)\
80 mov s1(%r11,%rdi,4),%r8d;\
82 mov s2(%r11,%rdi,4),%r9d;\
85 xor s2(%r11,%rdi,4),%r8d;\
88 xor s3(%r11,%rdi,4),%r9d;\
90 xor s3(%r11,%rdi,4),%r8d;\
92 xor (%r11,%rdi,4), %r9d;\
95 xor (%r11,%rdi,4), %r8d;\
97 xor s1(%r11,%rdi,4),%r9d;\
100 add k+round(%r11), %r9d;\
103 add k+4+round(%r11),%r8d;\
107 * a input register containing a(rotated 16)
108 * b input register containing b
109 * c input register containing c
110 * d input register containing d (already rol $1)
111 * operations on a and b are interleaved to increase performance
112 * during the round a and b are prepared for the output whitening
114 #define encrypt_last_round(a,b,c,d,round)\
118 mov s1(%r11,%rdi,4),%r8d;\
120 mov s2(%r11,%rdi,4),%r9d;\
123 xor s2(%r11,%rdi,4),%r8d;\
126 xor s3(%r11,%rdi,4),%r9d;\
128 xor s3(%r11,%rdi,4),%r8d;\
130 xor (%r11,%rdi,4), %r9d;\
133 xor (%r11,%rdi,4), %r8d;\
135 xor s1(%r11,%rdi,4),%r9d;\
138 add k+round(%r11), %r9d;\
141 add k+4+round(%r11),%r8d;\
145 * a input register containing a
146 * b input register containing b (rotated 16)
147 * c input register containing c (already rol $1)
148 * d input register containing d
149 * operations on a and b are interleaved to increase performance
151 #define decrypt_round(a,b,c,d,round)\
153 mov (%r11,%rdi,4), %r9d;\
155 mov s3(%r11,%rdi,4),%r8d;\
158 xor s1(%r11,%rdi,4),%r9d;\
161 xor (%r11,%rdi,4), %r8d;\
163 xor s2(%r11,%rdi,4),%r9d;\
165 xor s1(%r11,%rdi,4),%r8d;\
168 xor s3(%r11,%rdi,4),%r9d;\
170 xor s2(%r11,%rdi,4),%r8d;\
173 add k+round(%r11), %r9d;\
175 add k+4+round(%r11),%r8d;\
180 * a input register containing a
181 * b input register containing b
182 * c input register containing c (already rol $1)
183 * d input register containing d
184 * operations on a and b are interleaved to increase performance
185 * during the round a and b are prepared for the output whitening
187 #define decrypt_last_round(a,b,c,d,round)\
189 mov (%r11,%rdi,4), %r9d;\
191 mov s3(%r11,%rdi,4),%r8d;\
194 xor (%r11,%rdi,4), %r8d;\
200 xor s1(%r11,%rdi,4),%r9d;\
202 xor s1(%r11,%rdi,4),%r8d;\
204 xor s2(%r11,%rdi,4),%r9d;\
206 xor s2(%r11,%rdi,4),%r8d;\
208 xor s3(%r11,%rdi,4),%r9d;\
211 add k+round(%r11), %r9d;\
213 add k+4+round(%r11),%r8d;\
218 .global twofish_enc_blk
219 .global twofish_dec_blk
224 /* %rdi contains the crypto tfm address */
225 /* %rsi contains the output address */
226 /* %rdx contains the input address */
227 add $crypto_tfm_ctx_offset, %rdi /* set ctx address */
228 /* ctx address is moved to free one non-rex register
229 as target for the 8bit high operations */
234 input_whitening(R1,%r11,a_offset)
235 input_whitening(R3,%r11,c_offset)
243 encrypt_round(R0,R1,R2,R3,0);
244 encrypt_round(R2,R3,R0,R1,8);
245 encrypt_round(R0,R1,R2,R3,2*8);
246 encrypt_round(R2,R3,R0,R1,3*8);
247 encrypt_round(R0,R1,R2,R3,4*8);
248 encrypt_round(R2,R3,R0,R1,5*8);
249 encrypt_round(R0,R1,R2,R3,6*8);
250 encrypt_round(R2,R3,R0,R1,7*8);
251 encrypt_round(R0,R1,R2,R3,8*8);
252 encrypt_round(R2,R3,R0,R1,9*8);
253 encrypt_round(R0,R1,R2,R3,10*8);
254 encrypt_round(R2,R3,R0,R1,11*8);
255 encrypt_round(R0,R1,R2,R3,12*8);
256 encrypt_round(R2,R3,R0,R1,13*8);
257 encrypt_round(R0,R1,R2,R3,14*8);
258 encrypt_last_round(R2,R3,R0,R1,15*8);
261 output_whitening(%r10,%r11,a_offset)
267 output_whitening(R1,%r11,c_offset)
277 /* %rdi contains the crypto tfm address */
278 /* %rsi contains the output address */
279 /* %rdx contains the input address */
280 add $crypto_tfm_ctx_offset, %rdi /* set ctx address */
281 /* ctx address is moved to free one non-rex register
282 as target for the 8bit high operations */
287 output_whitening(R1,%r11,a_offset)
288 output_whitening(R3,%r11,c_offset)
296 decrypt_round(R0,R1,R2,R3,15*8);
297 decrypt_round(R2,R3,R0,R1,14*8);
298 decrypt_round(R0,R1,R2,R3,13*8);
299 decrypt_round(R2,R3,R0,R1,12*8);
300 decrypt_round(R0,R1,R2,R3,11*8);
301 decrypt_round(R2,R3,R0,R1,10*8);
302 decrypt_round(R0,R1,R2,R3,9*8);
303 decrypt_round(R2,R3,R0,R1,8*8);
304 decrypt_round(R0,R1,R2,R3,7*8);
305 decrypt_round(R2,R3,R0,R1,6*8);
306 decrypt_round(R0,R1,R2,R3,5*8);
307 decrypt_round(R2,R3,R0,R1,4*8);
308 decrypt_round(R0,R1,R2,R3,3*8);
309 decrypt_round(R2,R3,R0,R1,2*8);
310 decrypt_round(R0,R1,R2,R3,1*8);
311 decrypt_last_round(R2,R3,R0,R1,0);
313 input_whitening(%r10,%r11,a_offset)
319 input_whitening(R1,%r11,c_offset)