Enabled AES assembler support on x86-64 in shared libraries.
[crypto.git] / lib / silccrypt / aes_x86_64.asm
1 ; ---------------------------------------------------------------------------
2 ; Copyright (c) 2002, Dr Brian Gladman, Worcester, UK.   All rights reserved.
3 ;
4 ; LICENSE TERMS
5 ;
6 ; The free distribution and use of this software in both source and binary
7 ; form is allowed (with or without changes) provided that:
8 ;
9 ;   1. distributions of this source code include the above copyright
10 ;      notice, this list of conditions and the following disclaimer;
11 ;
12 ;   2. distributions in binary form include the above copyright
13 ;      notice, this list of conditions and the following disclaimer
14 ;      in the documentation and/or other associated materials;
15 ;
16 ;   3. the copyright holder's name is not used to endorse products
17 ;      built using this software without specific written permission.
18 ;
19 ; ALTERNATIVELY, provided that this notice is retained in full, this product
20 ; may be distributed under the terms of the GNU General Public License (GPL),
21 ; in which case the provisions of the GPL apply INSTEAD OF those given above.
22 ;
23 ; DISCLAIMER
24 ;
25 ; This software is provided 'as is' with no explicit or implied warranties
26 ; in respect of its properties, including, but not limited to, correctness
27 ; and/or fitness for purpose.
28 ; ---------------------------------------------------------------------------
29 ; Issue 09/09/2006
30
31 ; I am grateful to Dag Arne Osvik for many discussions of the techniques that
32 ; can be used to optimise AES assembler code on AMD64/EM64T architectures.
33 ; Some of the techniques used in this implementation are the result of
34 ; suggestions made by him for which I am most grateful.
35
36 ; An AES implementation for AMD64 processors using the YASM assembler.  This
37 ; implemetation provides only encryption, decryption and hence requires key
38 ; scheduling support in C. It uses 8k bytes of tables but its encryption and
39 ; decryption performance is very close to that obtained using large tables.
40 ; It can use either Windows or Gnu/Linux calling conventions, which are as
41 ; follows:
42 ;               windows  gnu/linux
43 ;
44 ;   in_blk          rcx     rdi
45 ;   out_blk         rdx     rsi
46 ;   context (cx)     r8     rdx
47 ;
48 ;   preserved       rsi      -    + rbx, rbp, rsp, r12, r13, r14 & r15
49 ;   registers       rdi      -      on both
50 ;
51 ;   destroyed        -      rsi   + rax, rcx, rdx, r8, r9, r10 & r11
52 ;   registers        -      rdi     on both
53 ;
54 ; The default convention is that for windows, the gnu/linux convention being
55 ; used if __GNUC__ is defined.
56 ;
57 ; This code provides the standard AES block size (128 bits, 16 bytes) and the
58 ; three standard AES key sizes (128, 192 and 256 bits). It has the same call
59 ; interface as my C implementation.  It uses the Microsoft C AMD64 calling
60 ; conventions in which the three parameters are placed in  rcx, rdx and r8
61 ; respectively.  The rbx, rsi, rdi, rbp and r12..r15 registers are preserved.
62 ;
63 ;     AES_RETURN aes_encrypt(const unsigned char in_blk[],
64 ;                   unsigned char out_blk[], const aes_encrypt_ctx cx[1]);
65 ;
66 ;     AES_RETURN aes_decrypt(const unsigned char in_blk[],
67 ;                   unsigned char out_blk[], const aes_decrypt_ctx cx[1]);
68 ;
69 ;     AES_RETURN aes_encrypt_key<NNN>(const unsigned char key[],
70 ;                                            const aes_encrypt_ctx cx[1]);
71 ;
72 ;     AES_RETURN aes_decrypt_key<NNN>(const unsigned char key[],
73 ;                                            const aes_decrypt_ctx cx[1]);
74 ;
75 ;     AES_RETURN aes_encrypt_key(const unsigned char key[],
76 ;                           unsigned int len, const aes_decrypt_ctx cx[1]);
77 ;
78 ;     AES_RETURN aes_decrypt_key(const unsigned char key[],
79 ;                           unsigned int len, const aes_decrypt_ctx cx[1]);
80 ;
81 ; where <NNN> is 128, 102 or 256.  In the last two calls the length can be in
82 ; either bits or bytes.
83 ;
84 ; Comment in/out the following lines to obtain the desired subroutines. These
85 ; selections MUST match those in the C header file aes.h
86
87 %define AES_128                 ; define if AES with 128 bit keys is needed
88 %define AES_192                 ; define if AES with 192 bit keys is needed
89 %define AES_256                 ; define if AES with 256 bit keys is needed
90 %define AES_VAR                 ; define if a variable key size is needed
91 %define ENCRYPTION              ; define if encryption is needed
92 %define DECRYPTION              ; define if decryption is needed
93 %define AES_REV_DKS             ; define if key decryption schedule is reversed
94 %define LAST_ROUND_TABLES       ; define for the faster version using extra tables
95
96 ; The encryption key schedule has the following in memory layout where N is the
97 ; number of rounds (10, 12 or 14):
98 ;
99 ; lo: | input key (round 0)  |  ; each round is four 32-bit words
100 ;     | encryption round 1   |
101 ;     | encryption round 2   |
102 ;     ....
103 ;     | encryption round N-1 |
104 ; hi: | encryption round N   |
105 ;
106 ; The decryption key schedule is normally set up so that it has the same
107 ; layout as above by actually reversing the order of the encryption key
108 ; schedule in memory (this happens when AES_REV_DKS is set):
109 ;
110 ; lo: | decryption round 0   | =              | encryption round N   |
111 ;     | decryption round 1   | = INV_MIX_COL[ | encryption round N-1 | ]
112 ;     | decryption round 2   | = INV_MIX_COL[ | encryption round N-2 | ]
113 ;     ....                       ....
114 ;     | decryption round N-1 | = INV_MIX_COL[ | encryption round 1   | ]
115 ; hi: | decryption round N   | =              | input key (round 0)  |
116 ;
117 ; with rounds except the first and last modified using inv_mix_column()
118 ; But if AES_REV_DKS is NOT set the order of keys is left as it is for
119 ; encryption so that it has to be accessed in reverse when used for
120 ; decryption (although the inverse mix column modifications are done)
121 ;
122 ; lo: | decryption round 0   | =              | input key (round 0)  |
123 ;     | decryption round 1   | = INV_MIX_COL[ | encryption round 1   | ]
124 ;     | decryption round 2   | = INV_MIX_COL[ | encryption round 2   | ]
125 ;     ....                       ....
126 ;     | decryption round N-1 | = INV_MIX_COL[ | encryption round N-1 | ]
127 ; hi: | decryption round N   | =              | encryption round N   |
128 ;
129 ; This layout is faster when the assembler key scheduling provided here
130 ; is used.
131 ;
132 ; The DLL interface must use the _stdcall convention in which the number
133 ; of bytes of parameter space is added after an @ to the sutine's name.
134 ; We must also remove our parameters from the stack before return (see
135 ; the do_exit macro). Define DLL_EXPORT for the Dynamic Link Library version.
136
137 ;%define DLL_EXPORT
138
139 ; End of user defines
140
141 %ifdef AES_VAR
142 %ifndef AES_128
143 %define AES_128
144 %endif
145 %ifndef AES_192
146 %define AES_192
147 %endif
148 %ifndef AES_256
149 %define AES_256
150 %endif
151 %endif
152
153 %ifdef AES_VAR
154 %define KS_LENGTH       60
155 %elifdef AES_256
156 %define KS_LENGTH       60
157 %elifdef AES_192
158 %define KS_LENGTH       52
159 %else
160 %define KS_LENGTH       44
161 %endif
162
163 %define     r0  rax
164 %define     r1  rdx
165 %define     r2  rcx
166 %define     r3  rbx
167 %define     r4  rsi
168 %define     r5  rdi
169 %define     r6  rbp
170 %define     r7  rsp
171
172 %define     raxd    eax
173 %define     rdxd    edx
174 %define     rcxd    ecx
175 %define     rbxd    ebx
176 %define     rsid    esi
177 %define     rdid    edi
178 %define     rbpd    ebp
179 %define     rspd    esp
180
181 %define     raxb    al
182 %define     rdxb    dl
183 %define     rcxb    cl
184 %define     rbxb    bl
185 %define     rsib    sil
186 %define     rdib    dil
187 %define     rbpb    bpl
188 %define     rspb    spl
189
190 %define     r0h ah
191 %define     r1h dh
192 %define     r2h ch
193 %define     r3h bh
194
195 %define     r0d eax
196 %define     r1d edx
197 %define     r2d ecx
198 %define     r3d ebx
199
200 ; finite field multiplies by {02}, {04} and {08}
201
202 %define f2(x)   ((x<<1)^(((x>>7)&1)*0x11b))
203 %define f4(x)   ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b))
204 %define f8(x)   ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b))
205
206 ; finite field multiplies required in table generation
207
208 %define f3(x)   (f2(x) ^ x)
209 %define f9(x)   (f8(x) ^ x)
210 %define fb(x)   (f8(x) ^ f2(x) ^ x)
211 %define fd(x)   (f8(x) ^ f4(x) ^ x)
212 %define fe(x)   (f8(x) ^ f4(x) ^ f2(x))
213
214 ; macro for expanding S-box data
215
216 %macro enc_vals 1
217     db  %1(0x63),%1(0x7c),%1(0x77),%1(0x7b),%1(0xf2),%1(0x6b),%1(0x6f),%1(0xc5)
218     db  %1(0x30),%1(0x01),%1(0x67),%1(0x2b),%1(0xfe),%1(0xd7),%1(0xab),%1(0x76)
219     db  %1(0xca),%1(0x82),%1(0xc9),%1(0x7d),%1(0xfa),%1(0x59),%1(0x47),%1(0xf0)
220     db  %1(0xad),%1(0xd4),%1(0xa2),%1(0xaf),%1(0x9c),%1(0xa4),%1(0x72),%1(0xc0)
221     db  %1(0xb7),%1(0xfd),%1(0x93),%1(0x26),%1(0x36),%1(0x3f),%1(0xf7),%1(0xcc)
222     db  %1(0x34),%1(0xa5),%1(0xe5),%1(0xf1),%1(0x71),%1(0xd8),%1(0x31),%1(0x15)
223     db  %1(0x04),%1(0xc7),%1(0x23),%1(0xc3),%1(0x18),%1(0x96),%1(0x05),%1(0x9a)
224     db  %1(0x07),%1(0x12),%1(0x80),%1(0xe2),%1(0xeb),%1(0x27),%1(0xb2),%1(0x75)
225     db  %1(0x09),%1(0x83),%1(0x2c),%1(0x1a),%1(0x1b),%1(0x6e),%1(0x5a),%1(0xa0)
226     db  %1(0x52),%1(0x3b),%1(0xd6),%1(0xb3),%1(0x29),%1(0xe3),%1(0x2f),%1(0x84)
227     db  %1(0x53),%1(0xd1),%1(0x00),%1(0xed),%1(0x20),%1(0xfc),%1(0xb1),%1(0x5b)
228     db  %1(0x6a),%1(0xcb),%1(0xbe),%1(0x39),%1(0x4a),%1(0x4c),%1(0x58),%1(0xcf)
229     db  %1(0xd0),%1(0xef),%1(0xaa),%1(0xfb),%1(0x43),%1(0x4d),%1(0x33),%1(0x85)
230     db  %1(0x45),%1(0xf9),%1(0x02),%1(0x7f),%1(0x50),%1(0x3c),%1(0x9f),%1(0xa8)
231     db  %1(0x51),%1(0xa3),%1(0x40),%1(0x8f),%1(0x92),%1(0x9d),%1(0x38),%1(0xf5)
232     db  %1(0xbc),%1(0xb6),%1(0xda),%1(0x21),%1(0x10),%1(0xff),%1(0xf3),%1(0xd2)
233     db  %1(0xcd),%1(0x0c),%1(0x13),%1(0xec),%1(0x5f),%1(0x97),%1(0x44),%1(0x17)
234     db  %1(0xc4),%1(0xa7),%1(0x7e),%1(0x3d),%1(0x64),%1(0x5d),%1(0x19),%1(0x73)
235     db  %1(0x60),%1(0x81),%1(0x4f),%1(0xdc),%1(0x22),%1(0x2a),%1(0x90),%1(0x88)
236     db  %1(0x46),%1(0xee),%1(0xb8),%1(0x14),%1(0xde),%1(0x5e),%1(0x0b),%1(0xdb)
237     db  %1(0xe0),%1(0x32),%1(0x3a),%1(0x0a),%1(0x49),%1(0x06),%1(0x24),%1(0x5c)
238     db  %1(0xc2),%1(0xd3),%1(0xac),%1(0x62),%1(0x91),%1(0x95),%1(0xe4),%1(0x79)
239     db  %1(0xe7),%1(0xc8),%1(0x37),%1(0x6d),%1(0x8d),%1(0xd5),%1(0x4e),%1(0xa9)
240     db  %1(0x6c),%1(0x56),%1(0xf4),%1(0xea),%1(0x65),%1(0x7a),%1(0xae),%1(0x08)
241     db  %1(0xba),%1(0x78),%1(0x25),%1(0x2e),%1(0x1c),%1(0xa6),%1(0xb4),%1(0xc6)
242     db  %1(0xe8),%1(0xdd),%1(0x74),%1(0x1f),%1(0x4b),%1(0xbd),%1(0x8b),%1(0x8a)
243     db  %1(0x70),%1(0x3e),%1(0xb5),%1(0x66),%1(0x48),%1(0x03),%1(0xf6),%1(0x0e)
244     db  %1(0x61),%1(0x35),%1(0x57),%1(0xb9),%1(0x86),%1(0xc1),%1(0x1d),%1(0x9e)
245     db  %1(0xe1),%1(0xf8),%1(0x98),%1(0x11),%1(0x69),%1(0xd9),%1(0x8e),%1(0x94)
246     db  %1(0x9b),%1(0x1e),%1(0x87),%1(0xe9),%1(0xce),%1(0x55),%1(0x28),%1(0xdf)
247     db  %1(0x8c),%1(0xa1),%1(0x89),%1(0x0d),%1(0xbf),%1(0xe6),%1(0x42),%1(0x68)
248     db  %1(0x41),%1(0x99),%1(0x2d),%1(0x0f),%1(0xb0),%1(0x54),%1(0xbb),%1(0x16)
249 %endmacro
250
251 %macro dec_vals 1
252     db  %1(0x52),%1(0x09),%1(0x6a),%1(0xd5),%1(0x30),%1(0x36),%1(0xa5),%1(0x38)
253     db  %1(0xbf),%1(0x40),%1(0xa3),%1(0x9e),%1(0x81),%1(0xf3),%1(0xd7),%1(0xfb)
254     db  %1(0x7c),%1(0xe3),%1(0x39),%1(0x82),%1(0x9b),%1(0x2f),%1(0xff),%1(0x87)
255     db  %1(0x34),%1(0x8e),%1(0x43),%1(0x44),%1(0xc4),%1(0xde),%1(0xe9),%1(0xcb)
256     db  %1(0x54),%1(0x7b),%1(0x94),%1(0x32),%1(0xa6),%1(0xc2),%1(0x23),%1(0x3d)
257     db  %1(0xee),%1(0x4c),%1(0x95),%1(0x0b),%1(0x42),%1(0xfa),%1(0xc3),%1(0x4e)
258     db  %1(0x08),%1(0x2e),%1(0xa1),%1(0x66),%1(0x28),%1(0xd9),%1(0x24),%1(0xb2)
259     db  %1(0x76),%1(0x5b),%1(0xa2),%1(0x49),%1(0x6d),%1(0x8b),%1(0xd1),%1(0x25)
260     db  %1(0x72),%1(0xf8),%1(0xf6),%1(0x64),%1(0x86),%1(0x68),%1(0x98),%1(0x16)
261     db  %1(0xd4),%1(0xa4),%1(0x5c),%1(0xcc),%1(0x5d),%1(0x65),%1(0xb6),%1(0x92)
262     db  %1(0x6c),%1(0x70),%1(0x48),%1(0x50),%1(0xfd),%1(0xed),%1(0xb9),%1(0xda)
263     db  %1(0x5e),%1(0x15),%1(0x46),%1(0x57),%1(0xa7),%1(0x8d),%1(0x9d),%1(0x84)
264     db  %1(0x90),%1(0xd8),%1(0xab),%1(0x00),%1(0x8c),%1(0xbc),%1(0xd3),%1(0x0a)
265     db  %1(0xf7),%1(0xe4),%1(0x58),%1(0x05),%1(0xb8),%1(0xb3),%1(0x45),%1(0x06)
266     db  %1(0xd0),%1(0x2c),%1(0x1e),%1(0x8f),%1(0xca),%1(0x3f),%1(0x0f),%1(0x02)
267     db  %1(0xc1),%1(0xaf),%1(0xbd),%1(0x03),%1(0x01),%1(0x13),%1(0x8a),%1(0x6b)
268     db  %1(0x3a),%1(0x91),%1(0x11),%1(0x41),%1(0x4f),%1(0x67),%1(0xdc),%1(0xea)
269     db  %1(0x97),%1(0xf2),%1(0xcf),%1(0xce),%1(0xf0),%1(0xb4),%1(0xe6),%1(0x73)
270     db  %1(0x96),%1(0xac),%1(0x74),%1(0x22),%1(0xe7),%1(0xad),%1(0x35),%1(0x85)
271     db  %1(0xe2),%1(0xf9),%1(0x37),%1(0xe8),%1(0x1c),%1(0x75),%1(0xdf),%1(0x6e)
272     db  %1(0x47),%1(0xf1),%1(0x1a),%1(0x71),%1(0x1d),%1(0x29),%1(0xc5),%1(0x89)
273     db  %1(0x6f),%1(0xb7),%1(0x62),%1(0x0e),%1(0xaa),%1(0x18),%1(0xbe),%1(0x1b)
274     db  %1(0xfc),%1(0x56),%1(0x3e),%1(0x4b),%1(0xc6),%1(0xd2),%1(0x79),%1(0x20)
275     db  %1(0x9a),%1(0xdb),%1(0xc0),%1(0xfe),%1(0x78),%1(0xcd),%1(0x5a),%1(0xf4)
276     db  %1(0x1f),%1(0xdd),%1(0xa8),%1(0x33),%1(0x88),%1(0x07),%1(0xc7),%1(0x31)
277     db  %1(0xb1),%1(0x12),%1(0x10),%1(0x59),%1(0x27),%1(0x80),%1(0xec),%1(0x5f)
278     db  %1(0x60),%1(0x51),%1(0x7f),%1(0xa9),%1(0x19),%1(0xb5),%1(0x4a),%1(0x0d)
279     db  %1(0x2d),%1(0xe5),%1(0x7a),%1(0x9f),%1(0x93),%1(0xc9),%1(0x9c),%1(0xef)
280     db  %1(0xa0),%1(0xe0),%1(0x3b),%1(0x4d),%1(0xae),%1(0x2a),%1(0xf5),%1(0xb0)
281     db  %1(0xc8),%1(0xeb),%1(0xbb),%1(0x3c),%1(0x83),%1(0x53),%1(0x99),%1(0x61)
282     db  %1(0x17),%1(0x2b),%1(0x04),%1(0x7e),%1(0xba),%1(0x77),%1(0xd6),%1(0x26)
283     db  %1(0xe1),%1(0x69),%1(0x14),%1(0x63),%1(0x55),%1(0x21),%1(0x0c),%1(0x7d)
284 %endmacro
285
286 %define u8(x)   f2(x), x, x, f3(x), f2(x), x, x, f3(x)
287 %define v8(x)   fe(x), f9(x), fd(x), fb(x), fe(x), f9(x), fd(x), x
288 %define w8(x)   x, 0, 0, 0, x, 0, 0, 0
289
290 %define tptr    rbp     ; table pointer
291 %define kptr    r8      ; key schedule pointer
292 %define fofs    128     ; adjust offset in key schedule to keep |disp| < 128
293 %define fk_ref(x,y) [kptr-16*x+fofs+4*y]
294 %ifdef  AES_REV_DKS
295 %define rofs    128
296 %define ik_ref(x,y) [kptr-16*x+rofs+4*y]
297 %else
298 %define rofs    -128
299 %define ik_ref(x,y) [kptr+16*x+rofs+4*y]
300 %endif
301
302 %define tab_0(x)   [tptr+8*x]
303 %define tab_1(x)   [tptr+8*x+3]
304 %define tab_2(x)   [tptr+8*x+2]
305 %define tab_3(x)   [tptr+8*x+1]
306 %define tab_f(x)   byte [tptr+8*x+1]
307 %define tab_i(x)   byte [tptr+8*x+7]
308 %define t_ref(x,r) tab_ %+ x(r)
309
310 %macro ff_rnd 5                 ; normal forward round
311     mov     %1d, fk_ref(%5,0)
312     mov     %2d, fk_ref(%5,1)
313     mov     %3d, fk_ref(%5,2)
314     mov     %4d, fk_ref(%5,3)
315
316     movzx   esi, al
317     movzx   edi, ah
318     shr     eax, 16
319     xor     %1d, t_ref(0,rsi)
320     xor     %4d, t_ref(1,rdi)
321     movzx   esi, al
322     movzx   edi, ah
323     xor     %3d, t_ref(2,rsi)
324     xor     %2d, t_ref(3,rdi)
325
326     movzx   esi, bl
327     movzx   edi, bh
328     shr     ebx, 16
329     xor     %2d, t_ref(0,rsi)
330     xor     %1d, t_ref(1,rdi)
331     movzx   esi, bl
332     movzx   edi, bh
333     xor     %4d, t_ref(2,rsi)
334     xor     %3d, t_ref(3,rdi)
335
336     movzx   esi, cl
337     movzx   edi, ch
338     shr     ecx, 16
339     xor     %3d, t_ref(0,rsi)
340     xor     %2d, t_ref(1,rdi)
341     movzx   esi, cl
342     movzx   edi, ch
343     xor     %1d, t_ref(2,rsi)
344     xor     %4d, t_ref(3,rdi)
345
346     movzx   esi, dl
347     movzx   edi, dh
348     shr     edx, 16
349     xor     %4d, t_ref(0,rsi)
350     xor     %3d, t_ref(1,rdi)
351     movzx   esi, dl
352     movzx   edi, dh
353     xor     %2d, t_ref(2,rsi)
354     xor     %1d, t_ref(3,rdi)
355
356     mov     eax,%1d
357     mov     ebx,%2d
358     mov     ecx,%3d
359     mov     edx,%4d
360 %endmacro
361
362 %ifdef LAST_ROUND_TABLES
363
364 %macro fl_rnd 5                 ; last forward round
365     add     tptr, 2048
366     mov     %1d, fk_ref(%5,0)
367     mov     %2d, fk_ref(%5,1)
368     mov     %3d, fk_ref(%5,2)
369     mov     %4d, fk_ref(%5,3)
370
371     movzx   esi, al
372     movzx   edi, ah
373     shr     eax, 16
374     xor     %1d, t_ref(0,rsi)
375     xor     %4d, t_ref(1,rdi)
376     movzx   esi, al
377     movzx   edi, ah
378     xor     %3d, t_ref(2,rsi)
379     xor     %2d, t_ref(3,rdi)
380
381     movzx   esi, bl
382     movzx   edi, bh
383     shr     ebx, 16
384     xor     %2d, t_ref(0,rsi)
385     xor     %1d, t_ref(1,rdi)
386     movzx   esi, bl
387     movzx   edi, bh
388     xor     %4d, t_ref(2,rsi)
389     xor     %3d, t_ref(3,rdi)
390
391     movzx   esi, cl
392     movzx   edi, ch
393     shr     ecx, 16
394     xor     %3d, t_ref(0,rsi)
395     xor     %2d, t_ref(1,rdi)
396     movzx   esi, cl
397     movzx   edi, ch
398     xor     %1d, t_ref(2,rsi)
399     xor     %4d, t_ref(3,rdi)
400
401     movzx   esi, dl
402     movzx   edi, dh
403     shr     edx, 16
404     xor     %4d, t_ref(0,rsi)
405     xor     %3d, t_ref(1,rdi)
406     movzx   esi, dl
407     movzx   edi, dh
408     xor     %2d, t_ref(2,rsi)
409     xor     %1d, t_ref(3,rdi)
410 %endmacro
411
412 %else
413
414 %macro fl_rnd 5                 ; last forward round
415     mov     %1d, fk_ref(%5,0)
416     mov     %2d, fk_ref(%5,1)
417     mov     %3d, fk_ref(%5,2)
418     mov     %4d, fk_ref(%5,3)
419
420     movzx   esi, al
421     movzx   edi, ah
422     shr     eax, 16
423     movzx   esi, t_ref(f,rsi)
424     movzx   edi, t_ref(f,rdi)
425     xor     %1d, esi
426     rol     edi, 8
427     xor     %4d, edi
428     movzx   esi, al
429     movzx   edi, ah
430     movzx   esi, t_ref(f,rsi)
431     movzx   edi, t_ref(f,rdi)
432     rol     esi, 16
433     rol     edi, 24
434     xor     %3d, esi
435     xor     %2d, edi
436
437     movzx   esi, bl
438     movzx   edi, bh
439     shr     ebx, 16
440     movzx   esi, t_ref(f,rsi)
441     movzx   edi, t_ref(f,rdi)
442     xor     %2d, esi
443     rol     edi, 8
444     xor     %1d, edi
445     movzx   esi, bl
446     movzx   edi, bh
447     movzx   esi, t_ref(f,rsi)
448     movzx   edi, t_ref(f,rdi)
449     rol     esi, 16
450     rol     edi, 24
451     xor     %4d, esi
452     xor     %3d, edi
453
454     movzx   esi, cl
455     movzx   edi, ch
456     movzx   esi, t_ref(f,rsi)
457     movzx   edi, t_ref(f,rdi)
458     shr     ecx, 16
459     xor     %3d, esi
460     rol     edi, 8
461     xor     %2d, edi
462     movzx   esi, cl
463     movzx   edi, ch
464     movzx   esi, t_ref(f,rsi)
465     movzx   edi, t_ref(f,rdi)
466     rol     esi, 16
467     rol     edi, 24
468     xor     %1d, esi
469     xor     %4d, edi
470
471     movzx   esi, dl
472     movzx   edi, dh
473     movzx   esi, t_ref(f,rsi)
474     movzx   edi, t_ref(f,rdi)
475     shr     edx, 16
476     xor     %4d, esi
477     rol     edi, 8
478     xor     %3d, edi
479     movzx   esi, dl
480     movzx   edi, dh
481     movzx   esi, t_ref(f,rsi)
482     movzx   edi, t_ref(f,rdi)
483     rol     esi, 16
484     rol     edi, 24
485     xor     %2d, esi
486     xor     %1d, edi
487 %endmacro
488
489 %endif
490
491 %macro ii_rnd 5                 ; normal inverse round
492     mov     %1d, ik_ref(%5,0)
493     mov     %2d, ik_ref(%5,1)
494     mov     %3d, ik_ref(%5,2)
495     mov     %4d, ik_ref(%5,3)
496
497     movzx   esi, al
498     movzx   edi, ah
499     shr     eax, 16
500     xor     %1d, t_ref(0,rsi)
501     xor     %2d, t_ref(1,rdi)
502     movzx   esi, al
503     movzx   edi, ah
504     xor     %3d, t_ref(2,rsi)
505     xor     %4d, t_ref(3,rdi)
506
507     movzx   esi, bl
508     movzx   edi, bh
509     shr     ebx, 16
510     xor     %2d, t_ref(0,rsi)
511     xor     %3d, t_ref(1,rdi)
512     movzx   esi, bl
513     movzx   edi, bh
514     xor     %4d, t_ref(2,rsi)
515     xor     %1d, t_ref(3,rdi)
516
517     movzx   esi, cl
518     movzx   edi, ch
519     shr     ecx, 16
520     xor     %3d, t_ref(0,rsi)
521     xor     %4d, t_ref(1,rdi)
522     movzx   esi, cl
523     movzx   edi, ch
524     xor     %1d, t_ref(2,rsi)
525     xor     %2d, t_ref(3,rdi)
526
527     movzx   esi, dl
528     movzx   edi, dh
529     shr     edx, 16
530     xor     %4d, t_ref(0,rsi)
531     xor     %1d, t_ref(1,rdi)
532     movzx   esi, dl
533     movzx   edi, dh
534     xor     %2d, t_ref(2,rsi)
535     xor     %3d, t_ref(3,rdi)
536
537     mov     eax,%1d
538     mov     ebx,%2d
539     mov     ecx,%3d
540     mov     edx,%4d
541 %endmacro
542
543 %ifdef LAST_ROUND_TABLES
544
545 %macro il_rnd 5                 ; last inverse round
546     add     tptr, 2048
547     mov     %1d, ik_ref(%5,0)
548     mov     %2d, ik_ref(%5,1)
549     mov     %3d, ik_ref(%5,2)
550     mov     %4d, ik_ref(%5,3)
551
552     movzx   esi, al
553     movzx   edi, ah
554     shr     eax, 16
555     xor     %1d, t_ref(0,rsi)
556     xor     %2d, t_ref(1,rdi)
557     movzx   esi, al
558     movzx   edi, ah
559     xor     %3d, t_ref(2,rsi)
560     xor     %4d, t_ref(3,rdi)
561
562     movzx   esi, bl
563     movzx   edi, bh
564     shr     ebx, 16
565     xor     %2d, t_ref(0,rsi)
566     xor     %3d, t_ref(1,rdi)
567     movzx   esi, bl
568     movzx   edi, bh
569     xor     %4d, t_ref(2,rsi)
570     xor     %1d, t_ref(3,rdi)
571
572     movzx   esi, cl
573     movzx   edi, ch
574     shr     ecx, 16
575     xor     %3d, t_ref(0,rsi)
576     xor     %4d, t_ref(1,rdi)
577     movzx   esi, cl
578     movzx   edi, ch
579     xor     %1d, t_ref(2,rsi)
580     xor     %2d, t_ref(3,rdi)
581
582     movzx   esi, dl
583     movzx   edi, dh
584     shr     edx, 16
585     xor     %4d, t_ref(0,rsi)
586     xor     %1d, t_ref(1,rdi)
587     movzx   esi, dl
588     movzx   edi, dh
589     xor     %2d, t_ref(2,rsi)
590     xor     %3d, t_ref(3,rdi)
591 %endmacro
592
593 %else
594
595 %macro il_rnd 5                 ; last inverse round
596     mov     %1d, ik_ref(%5,0)
597     mov     %2d, ik_ref(%5,1)
598     mov     %3d, ik_ref(%5,2)
599     mov     %4d, ik_ref(%5,3)
600
601     movzx   esi, al
602     movzx   edi, ah
603     movzx   esi, t_ref(i,rsi)
604     movzx   edi, t_ref(i,rdi)
605     shr     eax, 16
606     xor     %1d, esi
607     rol     edi, 8
608     xor     %2d, edi
609     movzx   esi, al
610     movzx   edi, ah
611     movzx   esi, t_ref(i,rsi)
612     movzx   edi, t_ref(i,rdi)
613     rol     esi, 16
614     rol     edi, 24
615     xor     %3d, esi
616     xor     %4d, edi
617
618     movzx   esi, bl
619     movzx   edi, bh
620     movzx   esi, t_ref(i,rsi)
621     movzx   edi, t_ref(i,rdi)
622     shr     ebx, 16
623     xor     %2d, esi
624     rol     edi, 8
625     xor     %3d, edi
626     movzx   esi, bl
627     movzx   edi, bh
628     movzx   esi, t_ref(i,rsi)
629     movzx   edi, t_ref(i,rdi)
630     rol     esi, 16
631     rol     edi, 24
632     xor     %4d, esi
633     xor     %1d, edi
634
635     movzx   esi, cl
636     movzx   edi, ch
637     movzx   esi, t_ref(i,rsi)
638     movzx   edi, t_ref(i,rdi)
639     shr     ecx, 16
640     xor     %3d, esi
641     rol     edi, 8
642     xor     %4d, edi
643     movzx   esi, cl
644     movzx   edi, ch
645     movzx   esi, t_ref(i,rsi)
646     movzx   edi, t_ref(i,rdi)
647     rol     esi, 16
648     rol     edi, 24
649     xor     %1d, esi
650     xor     %2d, edi
651
652     movzx   esi, dl
653     movzx   edi, dh
654     movzx   esi, t_ref(i,rsi)
655     movzx   edi, t_ref(i,rdi)
656     shr     edx, 16
657     xor     %4d, esi
658     rol     edi, 8
659     xor     %1d, edi
660     movzx   esi, dl
661     movzx   edi, dh
662     movzx   esi, t_ref(i,rsi)
663     movzx   edi, t_ref(i,rdi)
664     rol     esi, 16
665     rol     edi, 24
666     xor     %2d, esi
667     xor     %3d, edi
668 %endmacro
669
670 %endif
671
672 %ifdef ENCRYPTION
673
674     global  aes_encrypt
675 %ifdef DLL_EXPORT
676     export  aes_encrypt
677 %endif
678
679     section .data align=64
680     align   64
681 enc_tab:
682     enc_vals u8
683 %ifdef LAST_ROUND_TABLES
684     enc_vals w8
685 %endif
686
687     section .text align=16
688     align   16
689 aes_encrypt:
690
691 %ifndef WIN32
692     sub     rsp, 4*8        ; gnu/linux binary interface
693     mov     [rsp+0*8], rsi  ; output pointer
694     mov     r8, rdx         ; context
695 %else
696     sub     rsp, 6*8        ; windows binary interface
697     mov     [rsp+4*8], rsi
698     mov     [rsp+5*8], rdi
699     mov     [rsp+0*8], rdx  ; output pointer
700     mov     rdi, rcx        ; input pointer
701 %endif
702     mov     [rsp+1*8], rbx  ; input pointer in rdi
703     mov     [rsp+2*8], rbp  ; output pointer in [rsp]
704     mov     [rsp+3*8], r12  ; context in r8
705
706     movzx   esi, byte [kptr+4*KS_LENGTH]
707     lea     tptr,[enc_tab wrt rip]
708     sub     kptr, fofs
709
710     mov     eax, [rdi+0*4]
711     mov     ebx, [rdi+1*4]
712     mov     ecx, [rdi+2*4]
713     mov     edx, [rdi+3*4]
714
715     xor     eax, [kptr+fofs]
716     xor     ebx, [kptr+fofs+4]
717     xor     ecx, [kptr+fofs+8]
718     xor     edx, [kptr+fofs+12]
719
720     lea     kptr,[kptr+rsi]
721     cmp     esi, 10*16
722     je      .3
723     cmp     esi, 12*16
724     je      .2
725     cmp     esi, 14*16
726     je      .1
727     mov     rax, -1
728     jmp     .4
729
730 .1: ff_rnd  r9, r10, r11, r12, 13
731     ff_rnd  r9, r10, r11, r12, 12
732 .2: ff_rnd  r9, r10, r11, r12, 11
733     ff_rnd  r9, r10, r11, r12, 10
734 .3: ff_rnd  r9, r10, r11, r12, 9
735     ff_rnd  r9, r10, r11, r12, 8
736     ff_rnd  r9, r10, r11, r12, 7
737     ff_rnd  r9, r10, r11, r12, 6
738     ff_rnd  r9, r10, r11, r12, 5
739     ff_rnd  r9, r10, r11, r12, 4
740     ff_rnd  r9, r10, r11, r12, 3
741     ff_rnd  r9, r10, r11, r12, 2
742     ff_rnd  r9, r10, r11, r12, 1
743     fl_rnd  r9, r10, r11, r12, 0
744
745     mov     rbx, [rsp]
746     mov     [rbx], r9d
747     mov     [rbx+4], r10d
748     mov     [rbx+8], r11d
749     mov     [rbx+12], r12d
750     xor     rax, rax
751 .4:
752     mov     rbx, [rsp+1*8]
753     mov     rbp, [rsp+2*8]
754     mov     r12, [rsp+3*8]
755 %ifndef WIN32
756     add     rsp, 4*8
757 %else
758     mov     rsi, [rsp+4*8]
759     mov     rdi, [rsp+5*8]
760     add     rsp, 6*8
761 %endif
762     ret
763
764 %endif
765
766 %ifdef DECRYPTION
767
768     global  aes_decrypt
769 %ifdef DLL_EXPORT
770     export  aes_decrypt
771 %endif
772
773     section .data align=64
774     align   64
775 dec_tab:
776     dec_vals v8
777 %ifdef LAST_ROUND_TABLES
778     dec_vals w8
779 %endif
780
781     section .text align=16
782     align   16
783 aes_decrypt:
784
785 %ifndef WIN32
786     sub     rsp, 4*8        ; gnu/linux binary interface
787     mov     [rsp+0*8], rsi  ; output pointer
788     mov     r8, rdx         ; context
789 %else
790     sub     rsp, 6*8        ; windows binary interface
791     mov     [rsp+4*8], rsi
792     mov     [rsp+5*8], rdi
793     mov     [rsp+0*8], rdx  ; output pointer
794     mov     rdi, rcx        ; input pointer
795 %endif
796     mov     [rsp+1*8], rbx  ; input pointer in rdi
797     mov     [rsp+2*8], rbp  ; output pointer in [rsp]
798     mov     [rsp+3*8], r12  ; context in r8
799
800     movzx   esi,byte[kptr+4*KS_LENGTH]
801     lea     tptr,[dec_tab wrt rip]
802     sub     kptr, rofs
803
804     mov     eax, [rdi+0*4]
805     mov     ebx, [rdi+1*4]
806     mov     ecx, [rdi+2*4]
807     mov     edx, [rdi+3*4]
808
809 %ifdef      AES_REV_DKS
810     mov     rdi, kptr
811     lea     kptr,[kptr+rsi]
812 %else
813     lea     rdi,[kptr+rsi]
814 %endif
815
816     xor     eax, [rdi+rofs]
817     xor     ebx, [rdi+rofs+4]
818     xor     ecx, [rdi+rofs+8]
819     xor     edx, [rdi+rofs+12]
820
821     cmp     esi, 10*16
822     je      .3
823     cmp     esi, 12*16
824     je      .2
825     cmp     esi, 14*16
826     je      .1
827     mov     rax, -1
828     jmp     .4
829
830 .1: ii_rnd  r9, r10, r11, r12, 13
831     ii_rnd  r9, r10, r11, r12, 12
832 .2: ii_rnd  r9, r10, r11, r12, 11
833     ii_rnd  r9, r10, r11, r12, 10
834 .3: ii_rnd  r9, r10, r11, r12, 9
835     ii_rnd  r9, r10, r11, r12, 8
836     ii_rnd  r9, r10, r11, r12, 7
837     ii_rnd  r9, r10, r11, r12, 6
838     ii_rnd  r9, r10, r11, r12, 5
839     ii_rnd  r9, r10, r11, r12, 4
840     ii_rnd  r9, r10, r11, r12, 3
841     ii_rnd  r9, r10, r11, r12, 2
842     ii_rnd  r9, r10, r11, r12, 1
843     il_rnd  r9, r10, r11, r12, 0
844
845     mov     rbx, [rsp]
846     mov     [rbx], r9d
847     mov     [rbx+4], r10d
848     mov     [rbx+8], r11d
849     mov     [rbx+12], r12d
850     xor     rax, rax
851 .4: mov     rbx, [rsp+1*8]
852     mov     rbp, [rsp+2*8]
853     mov     r12, [rsp+3*8]
854 %ifndef WIN32
855     add     rsp, 4*8
856 %else
857     mov     rsi, [rsp+4*8]
858     mov     rdi, [rsp+5*8]
859     add     rsp, 6*8
860 %endif
861     ret
862
863 %endif
864
865     end