This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / i386 / crypto / aes-i586-asm.S
1 // -------------------------------------------------------------------------
2 // Copyright (c) 2001, Dr Brian Gladman <                 >, Worcester, UK.
3 // All rights reserved.
4 //
5 // LICENSE TERMS
6 //
7 // The free distribution and use of this software in both source and binary 
8 // form is allowed (with or without changes) provided that:
9 //
10 //   1. distributions of this source code include the above copyright 
11 //      notice, this list of conditions and the following disclaimer//
12 //
13 //   2. distributions in binary form include the above copyright
14 //      notice, this list of conditions and the following disclaimer
15 //      in the documentation and/or other associated materials//
16 //
17 //   3. the copyright holder's name is not used to endorse products 
18 //      built using this software without specific written permission.
19 //
20 //
21 // ALTERNATIVELY, provided that this notice is retained in full, this product
22 // may be distributed under the terms of the GNU General Public License (GPL),
23 // in which case the provisions of the GPL apply INSTEAD OF those given above.
24 //
25 // Copyright (c) 2004 Linus Torvalds <torvalds@osdl.org>
26 // Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
27
28 // DISCLAIMER
29 //
30 // This software is provided 'as is' with no explicit or implied warranties
31 // in respect of its properties including, but not limited to, correctness 
32 // and fitness for purpose.
33 // -------------------------------------------------------------------------
34 // Issue Date: 29/07/2002
35
36 .file "aes-i586-asm.S"
37 .text
38
39 // aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])//
40 // aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])//
41         
42 #define tlen 1024   // length of each of 4 'xor' arrays (256 32-bit words)
43
44 // offsets to parameters with one register pushed onto stack
45
46 #define in_blk    8  // input byte array address parameter
47 #define out_blk  12  // output byte array address parameter
48 #define ctx      16  // AES context structure
49
50 // offsets in context structure
51
52 #define ekey     0   // encryption key schedule base address
53 #define nrnd   256   // number of rounds
54 #define dkey   260   // decryption key schedule base address
55
56 // register mapping for encrypt and decrypt subroutines
57
58 #define r0  eax
59 #define r1  ebx
60 #define r2  ecx
61 #define r3  edx
62 #define r4  esi
63 #define r5  edi
64 #define r6  ebp
65
66 #define eaxl  al
67 #define eaxh  ah
68 #define ebxl  bl
69 #define ebxh  bh
70 #define ecxl  cl
71 #define ecxh  ch
72 #define edxl  dl
73 #define edxh  dh
74
75 #define _h(reg) reg##h
76 #define h(reg) _h(reg)
77
78 #define _l(reg) reg##l
79 #define l(reg) _l(reg)
80
81 // This macro takes a 32-bit word representing a column and uses
82 // each of its four bytes to index into four tables of 256 32-bit
83 // words to obtain values that are then xored into the appropriate
84 // output registers r0, r1, r4 or r5.  
85
86 // Parameters:
87 //   %1  out_state[0]
88 //   %2  out_state[1]
89 //   %3  out_state[2]
90 //   %4  out_state[3]
91 //   %5  table base address
92 //   %6  input register for the round (destroyed)
93 //   %7  scratch register for the round
94
95 #define do_col(a1, a2, a3, a4, a5, a6, a7)      \
96         movzx   %l(a6),%a7;                     \
97         xor     a5(,%a7,4),%a1;                 \
98         movzx   %h(a6),%a7;                     \
99         shr     $16,%a6;                        \
100         xor     a5+tlen(,%a7,4),%a2;            \
101         movzx   %l(a6),%a7;                     \
102         movzx   %h(a6),%a6;                     \
103         xor     a5+2*tlen(,%a7,4),%a3;          \
104         xor     a5+3*tlen(,%a6,4),%a4;
105
106 // initialise output registers from the key schedule
107
108 #define do_fcol(a1, a2, a3, a4, a5, a6, a7, a8) \
109         mov     0 a8,%a1;                       \
110         movzx   %l(a6),%a7;                     \
111         mov     12 a8,%a2;                      \
112         xor     a5(,%a7,4),%a1;                 \
113         mov     4 a8,%a4;                       \
114         movzx   %h(a6),%a7;                     \
115         shr     $16,%a6;                        \
116         xor     a5+tlen(,%a7,4),%a2;            \
117         movzx   %l(a6),%a7;                     \
118         movzx   %h(a6),%a6;                     \
119         xor     a5+3*tlen(,%a6,4),%a4;          \
120         mov     %a3,%a6;                        \
121         mov     8 a8,%a3;                       \
122         xor     a5+2*tlen(,%a7,4),%a3;
123
124 // initialise output registers from the key schedule
125
126 #define do_icol(a1, a2, a3, a4, a5, a6, a7, a8) \
127         mov     0 a8,%a1;                       \
128         movzx   %l(a6),%a7;                     \
129         mov     4 a8,%a2;                       \
130         xor     a5(,%a7,4),%a1;                 \
131         mov     12 a8,%a4;                      \
132         movzx   %h(a6),%a7;                     \
133         shr     $16,%a6;                        \
134         xor     a5+tlen(,%a7,4),%a2;            \
135         movzx   %l(a6),%a7;                     \
136         movzx   %h(a6),%a6;                     \
137         xor     a5+3*tlen(,%a6,4),%a4;          \
138         mov     %a3,%a6;                        \
139         mov     8 a8,%a3;                       \
140         xor     a5+2*tlen(,%a7,4),%a3;
141
142
143 // original Gladman had conditional saves to MMX regs.
144 #define save(a1, a2)            \
145         mov     %a2,4*a1(%esp)
146
147 #define restore(a1, a2)         \
148         mov     4*a2(%esp),%a1
149
150 // This macro performs a forward encryption cycle. It is entered with
151 // the first previous round column values in r0, r1, r4 and r5 and
152 // exits with the final values in the same registers, using the MMX
153 // registers mm0-mm1 or the stack for temporary storage
154
155 // mov current column values into the MMX registers
156 #define fwd_rnd(arg, table)                                     \
157         /* mov current column values into the MMX registers */  \
158         mov     %r0,%r2;                                        \
159         save   (0,r1);                                          \
160         save   (1,r5);                                          \
161                                                                 \
162         /* compute new column values */                         \
163         do_fcol(r0,r5,r4,r1,table, r2,r3, arg);                 \
164         do_col (r4,r1,r0,r5,table, r2,r3);                      \
165         restore(r2,0);                                          \
166         do_col (r1,r0,r5,r4,table, r2,r3);                      \
167         restore(r2,1);                                          \
168         do_col (r5,r4,r1,r0,table, r2,r3);
169
170 // This macro performs an inverse encryption cycle. It is entered with
171 // the first previous round column values in r0, r1, r4 and r5 and
172 // exits with the final values in the same registers, using the MMX
173 // registers mm0-mm1 or the stack for temporary storage
174
175 #define inv_rnd(arg, table)                                     \
176         /* mov current column values into the MMX registers */  \
177         mov     %r0,%r2;                                        \
178         save    (0,r1);                                         \
179         save    (1,r5);                                         \
180                                                                 \
181         /* compute new column values */                         \
182         do_icol(r0,r1,r4,r5, table, r2,r3, arg);                \
183         do_col (r4,r5,r0,r1, table, r2,r3);                     \
184         restore(r2,0);                                          \
185         do_col (r1,r4,r5,r0, table, r2,r3);                     \
186         restore(r2,1);                                          \
187         do_col (r5,r0,r1,r4, table, r2,r3);
188
189 // AES (Rijndael) Encryption Subroutine
190
191 .global  aes_enc_blk
192
193 .extern  ft_tab
194 .extern  fl_tab
195
196 .align 4
197
198 aes_enc_blk:
199         push    %ebp
200         mov     ctx(%esp),%ebp      // pointer to context
201         xor     %eax,%eax
202
203 // CAUTION: the order and the values used in these assigns 
204 // rely on the register mappings
205
206 1:      push    %ebx
207         mov     in_blk+4(%esp),%r2
208         push    %esi
209         mov     nrnd(%ebp),%r3   // number of rounds
210         push    %edi
211         lea     ekey(%ebp),%r6   // key pointer
212
213 // input four columns and xor in first round key
214
215         mov     (%r2),%r0
216         mov     4(%r2),%r1
217         mov     8(%r2),%r4
218         mov     12(%r2),%r5
219         xor     (%r6),%r0
220         xor     4(%r6),%r1
221         xor     8(%r6),%r4
222         xor     12(%r6),%r5
223
224         sub     $8,%esp           // space for register saves on stack
225         add     $16,%r6           // increment to next round key   
226         sub     $10,%r3          
227         je      4f              // 10 rounds for 128-bit key
228         add     $32,%r6
229         sub     $2,%r3
230         je      3f              // 12 rounds for 128-bit key
231         add     $32,%r6
232
233 2:      fwd_rnd( -64(%r6) ,ft_tab)      // 14 rounds for 128-bit key
234         fwd_rnd( -48(%r6) ,ft_tab)
235 3:      fwd_rnd( -32(%r6) ,ft_tab)      // 12 rounds for 128-bit key
236         fwd_rnd( -16(%r6) ,ft_tab)
237 4:      fwd_rnd(    (%r6) ,ft_tab)      // 10 rounds for 128-bit key
238         fwd_rnd( +16(%r6) ,ft_tab)
239         fwd_rnd( +32(%r6) ,ft_tab)
240         fwd_rnd( +48(%r6) ,ft_tab)
241         fwd_rnd( +64(%r6) ,ft_tab)
242         fwd_rnd( +80(%r6) ,ft_tab)
243         fwd_rnd( +96(%r6) ,ft_tab)
244         fwd_rnd(+112(%r6) ,ft_tab)
245         fwd_rnd(+128(%r6) ,ft_tab)
246         fwd_rnd(+144(%r6) ,fl_tab)      // last round uses a different table
247
248 // move final values to the output array.  CAUTION: the 
249 // order of these assigns rely on the register mappings
250
251         add     $8,%esp
252         mov     out_blk+12(%esp),%r6
253         mov     %r5,12(%r6)
254         pop     %edi
255         mov     %r4,8(%r6)
256         pop     %esi
257         mov     %r1,4(%r6)
258         pop     %ebx
259         mov     %r0,(%r6)
260         pop     %ebp
261         mov     $1,%eax
262         ret
263
264 // AES (Rijndael) Decryption Subroutine
265
266 .global  aes_dec_blk
267
268 .extern  it_tab
269 .extern  il_tab
270
271 .align 4
272
273 aes_dec_blk:
274         push    %ebp
275         mov     ctx(%esp),%ebp       // pointer to context
276         xor     %eax,%eax
277
278 // CAUTION: the order and the values used in these assigns 
279 // rely on the register mappings
280
281 1:      push    %ebx
282         mov     in_blk+4(%esp),%r2
283         push    %esi
284         mov     nrnd(%ebp),%r3   // number of rounds
285         push    %edi
286         lea     dkey(%ebp),%r6   // key pointer
287         mov     %r3,%r0
288         shl     $4,%r0
289         add     %r0,%r6
290         
291 // input four columns and xor in first round key
292
293         mov     (%r2),%r0
294         mov     4(%r2),%r1
295         mov     8(%r2),%r4
296         mov     12(%r2),%r5
297         xor     (%r6),%r0
298         xor     4(%r6),%r1
299         xor     8(%r6),%r4
300         xor     12(%r6),%r5
301
302         sub     $8,%esp           // space for register saves on stack
303         sub     $16,%r6           // increment to next round key   
304         sub     $10,%r3          
305         je      4f              // 10 rounds for 128-bit key
306         sub     $32,%r6
307         sub     $2,%r3
308         je      3f              // 12 rounds for 128-bit key
309         sub     $32,%r6
310
311 2:      inv_rnd( +64(%r6), it_tab)      // 14 rounds for 128-bit key 
312         inv_rnd( +48(%r6), it_tab)
313 3:      inv_rnd( +32(%r6), it_tab)      // 12 rounds for 128-bit key
314         inv_rnd( +16(%r6), it_tab)
315 4:      inv_rnd(    (%r6), it_tab)      // 10 rounds for 128-bit key
316         inv_rnd( -16(%r6), it_tab)
317         inv_rnd( -32(%r6), it_tab)
318         inv_rnd( -48(%r6), it_tab)
319         inv_rnd( -64(%r6), it_tab)
320         inv_rnd( -80(%r6), it_tab)
321         inv_rnd( -96(%r6), it_tab)
322         inv_rnd(-112(%r6), it_tab)
323         inv_rnd(-128(%r6), it_tab)
324         inv_rnd(-144(%r6), il_tab)      // last round uses a different table
325
326 // move final values to the output array.  CAUTION: the 
327 // order of these assigns rely on the register mappings
328
329         add     $8,%esp
330         mov     out_blk+12(%esp),%r6
331         mov     %r5,12(%r6)
332         pop     %edi
333         mov     %r4,8(%r6)
334         pop     %esi
335         mov     %r1,4(%r6)
336         pop     %ebx
337         mov     %r0,(%r6)
338         pop     %ebp
339         mov     $1,%eax
340         ret
341