cb426a12e8cab2abb512606d33b7ded928512cae
[silc.git] / lib / silccrypt / aes_x86.asm
1
2 ; ---------------------------------------------------------------------------
3 ; Copyright (c) 2002, Dr Brian Gladman, Worcester, UK.   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 ; ALTERNATIVELY, provided that this notice is retained in full, this product
21 ; may be distributed under the terms of the GNU General Public License (GPL),
22 ; in which case the provisions of the GPL apply INSTEAD OF those given above.
23 ;
24 ; DISCLAIMER
25 ;
26 ; This software is provided 'as is' with no explicit or implied warranties
27 ; in respect of its properties, including, but not limited to, correctness
28 ; and/or fitness for purpose.
29 ; ---------------------------------------------------------------------------
30 ; Issue 09/09/2006
31
32 ; An AES implementation for x86 processors using the YASM (or NASM) assembler.
33 ; This is an assembler implementation that covers encryption and decryption
34 ; only and is intended as a replacement of the C file aescrypt.c. It hence
35 ; requires the file aeskey.c for keying and aestab.c for the AES tables. It
36 ; employs full tables rather than compressed tables.
37
38 ; This code provides the standard AES block size (128 bits, 16 bytes) and the
39 ; three standard AES key sizes (128, 192 and 256 bits). It has the same call
40 ; interface as my C implementation. The ebx, esi, edi and ebp registers are
41 ; preserved across calls but eax, ecx and edx and the artihmetic status flags
42 ; are not.  It is also important that the defines below match those used in the
43 ; C code.  This code uses the VC++ register saving conentions; if it is used
44 ; with another compiler, conventions for using and saving registers may need to
45 ; be checked (and calling conventions).  The YASM command line for the VC++
46 ; custom build step is:
47 ;
48 ;    yasm -Xvc -f win32 -o "$(TargetDir)\$(InputName).obj" "$(InputPath)"
49 ;
50 ;  The calling intefaces are:
51 ;
52 ;     AES_RETURN aes_encrypt(const unsigned char in_blk[],
53 ;                   unsigned char out_blk[], const aes_encrypt_ctx cx[1]);
54 ;
55 ;     AES_RETURN aes_decrypt(const unsigned char in_blk[],
56 ;                   unsigned char out_blk[], const aes_decrypt_ctx cx[1]);
57 ;
58 ;     AES_RETURN aes_encrypt_key<NNN>(const unsigned char key[],
59 ;                                            const aes_encrypt_ctx cx[1]);
60 ;
61 ;     AES_RETURN aes_decrypt_key<NNN>(const unsigned char key[],
62 ;                                            const aes_decrypt_ctx cx[1]);
63 ;
64 ;     AES_RETURN aes_encrypt_key(const unsigned char key[],
65 ;                           unsigned int len, const aes_decrypt_ctx cx[1]);
66 ;
67 ;     AES_RETURN aes_decrypt_key(const unsigned char key[],
68 ;                           unsigned int len, const aes_decrypt_ctx cx[1]);
69 ;
70 ; where <NNN> is 128, 102 or 256.  In the last two calls the length can be in
71 ; either bits or bytes.
72 ;
73 ; Comment in/out the following lines to obtain the desired subroutines. These
74 ; selections MUST match those in the C header file aes.h
75
76 %define AES_128                 ; define if AES with 128 bit keys is needed
77 %define AES_192                 ; define if AES with 192 bit keys is needed
78 %define AES_256                 ; define if AES with 256 bit keys is needed
79 %define AES_VAR                 ; define if a variable key size is needed
80 %define ENCRYPTION              ; define if encryption is needed
81 %define DECRYPTION              ; define if decryption is needed
82 %define AES_REV_DKS             ; define if key decryption schedule is reversed
83 %define LAST_ROUND_TABLES       ; define if tables are to be used for last round
84
85 ; offsets to parameters
86
87 in_blk  equ     4   ; input byte array address parameter
88 out_blk equ     8   ; output byte array address parameter
89 ctx     equ    12   ; AES context structure
90 stk_spc equ    20   ; stack space
91 %define parms  12   ; parameter space on stack
92
93 ; The encryption key schedule has the following in memory layout where N is the
94 ; number of rounds (10, 12 or 14):
95 ;
96 ; lo: | input key (round 0)  |  ; each round is four 32-bit words
97 ;     | encryption round 1   |
98 ;     | encryption round 2   |
99 ;     ....
100 ;     | encryption round N-1 |
101 ; hi: | encryption round N   |
102 ;
103 ; The decryption key schedule is normally set up so that it has the same
104 ; layout as above by actually reversing the order of the encryption key
105 ; schedule in memory (this happens when AES_REV_DKS is set):
106 ;
107 ; lo: | decryption round 0   | =              | encryption round N   |
108 ;     | decryption round 1   | = INV_MIX_COL[ | encryption round N-1 | ]
109 ;     | decryption round 2   | = INV_MIX_COL[ | encryption round N-2 | ]
110 ;     ....                       ....
111 ;     | decryption round N-1 | = INV_MIX_COL[ | encryption round 1   | ]
112 ; hi: | decryption round N   | =              | input key (round 0)  |
113 ;
114 ; with rounds except the first and last modified using inv_mix_column()
115 ; But if AES_REV_DKS is NOT set the order of keys is left as it is for
116 ; encryption so that it has to be accessed in reverse when used for
117 ; decryption (although the inverse mix column modifications are done)
118 ;
119 ; lo: | decryption round 0   | =              | input key (round 0)  |
120 ;     | decryption round 1   | = INV_MIX_COL[ | encryption round 1   | ]
121 ;     | decryption round 2   | = INV_MIX_COL[ | encryption round 2   | ]
122 ;     ....                       ....
123 ;     | decryption round N-1 | = INV_MIX_COL[ | encryption round N-1 | ]
124 ; hi: | decryption round N   | =              | encryption round N   |
125 ;
126 ; This layout is faster when the assembler key scheduling provided here
127 ; is used.
128 ;
129 ; The DLL interface must use the _stdcall convention in which the number
130 ; of bytes of parameter space is added after an @ to the sutine's name.
131 ; We must also remove our parameters from the stack before return (see
132 ; the do_exit macro). Define DLL_EXPORT for the Dynamic Link Library version.
133
134 ;%define DLL_EXPORT
135
136 ; End of user defines
137
138 %ifdef AES_VAR
139 %ifndef AES_128
140 %define AES_128
141 %endif
142 %ifndef AES_192
143 %define AES_192
144 %endif
145 %ifndef AES_256
146 %define AES_256
147 %endif
148 %endif
149
150 %ifdef AES_VAR
151 %define KS_LENGTH       60
152 %elifdef AES_256
153 %define KS_LENGTH       60
154 %elifdef AES_192
155 %define KS_LENGTH       52
156 %else
157 %define KS_LENGTH       44
158 %endif
159
160 ; These macros implement stack based local variables
161
162 %macro  save 2
163     mov     [esp+4*%1],%2
164 %endmacro
165
166 %macro  restore 2
167     mov     %1,[esp+4*%2]
168 %endmacro
169
170 ; the DLL has to implement the _stdcall calling interface on return
171 ; In this case we have to take our parameters (3 4-byte pointers)
172 ; off the stack
173
174 %macro  do_name 1-2 parms
175 %ifndef DLL_EXPORT
176     align 32
177     global  %1
178 %1:
179 %else
180     align 32
181     global  %1@%2
182     export  %1@%2
183 %1@%2:
184 %endif
185 %endmacro
186
187 %macro  do_call 1-2 parms
188 %ifndef DLL_EXPORT
189     call    %1
190     add     esp,%2
191 %else
192     call    %1@%2
193 %endif
194 %endmacro
195
196 %macro  do_exit  0-1 parms
197 %ifdef DLL_EXPORT
198     ret %1
199 %else
200     ret
201 %endif
202 %endmacro
203
204 %ifdef  ENCRYPTION
205
206     extern  t_fn
207
208 %define etab_0(x)   [t_fn+4*x]
209 %define etab_1(x)   [t_fn+1024+4*x]
210 %define etab_2(x)   [t_fn+2048+4*x]
211 %define etab_3(x)   [t_fn+3072+4*x]
212
213 %ifdef LAST_ROUND_TABLES
214
215     extern  t_fl
216
217 %define eltab_0(x)  [t_fl+4*x]
218 %define eltab_1(x)  [t_fl+1024+4*x]
219 %define eltab_2(x)  [t_fl+2048+4*x]
220 %define eltab_3(x)  [t_fl+3072+4*x]
221
222 %endif
223
224 ; ROUND FUNCTION.  Build column[2] on ESI and column[3] on EDI that have the
225 ; round keys pre-loaded. Build column[0] in EBP and column[1] in EBX.
226 ;
227 ; Input:
228 ;
229 ;   EAX     column[0]
230 ;   EBX     column[1]
231 ;   ECX     column[2]
232 ;   EDX     column[3]
233 ;   ESI     column key[round][2]
234 ;   EDI     column key[round][3]
235 ;   EBP     scratch
236 ;
237 ; Output:
238 ;
239 ;   EBP     column[0]   unkeyed
240 ;   EBX     column[1]   unkeyed
241 ;   ESI     column[2]   keyed
242 ;   EDI     column[3]   keyed
243 ;   EAX     scratch
244 ;   ECX     scratch
245 ;   EDX     scratch
246
247 %macro rnd_fun 2
248
249     rol     ebx,16
250     %1      esi, cl, 0, ebp
251     %1      esi, dh, 1, ebp
252     %1      esi, bh, 3, ebp
253     %1      edi, dl, 0, ebp
254     %1      edi, ah, 1, ebp
255     %1      edi, bl, 2, ebp
256     %2      ebp, al, 0, ebp
257     shr     ebx,16
258     and     eax,0xffff0000
259     or      eax,ebx
260     shr     edx,16
261     %1      ebp, ah, 1, ebx
262     %1      ebp, dh, 3, ebx
263     %2      ebx, dl, 2, ebx
264     %1      ebx, ch, 1, edx
265     %1      ebx, al, 0, edx
266     shr     eax,16
267     shr     ecx,16
268     %1      ebp, cl, 2, edx
269     %1      edi, ch, 3, edx
270     %1      esi, al, 2, edx
271     %1      ebx, ah, 3, edx
272
273 %endmacro
274
275 ; Basic MOV and XOR Operations for normal rounds
276
277 %macro  nr_xor  4
278     movzx   %4,%2
279     xor     %1,etab_%3(%4)
280 %endmacro
281
282 %macro  nr_mov  4
283     movzx   %4,%2
284     mov     %1,etab_%3(%4)
285 %endmacro
286
287 ; Basic MOV and XOR Operations for last round
288
289 %ifdef LAST_ROUND_TABLES
290
291     %macro  lr_xor  4
292         movzx   %4,%2
293         xor     %1,eltab_%3(%4)
294     %endmacro
295
296     %macro  lr_mov  4
297         movzx   %4,%2
298         mov     %1,eltab_%3(%4)
299     %endmacro
300
301 %endif
302
303 %macro enc_round 0
304
305     add     ebp,16
306     save    0,ebp
307     mov     esi,[ebp+8]
308     mov     edi,[ebp+12]
309
310     rnd_fun nr_xor, nr_mov
311
312     mov     eax,ebp
313     mov     ecx,esi
314     mov     edx,edi
315     restore ebp,0
316     xor     eax,[ebp]
317     xor     ebx,[ebp+4]
318
319 %endmacro
320
321 %macro enc_last_round 0
322
323     add     ebp,16
324     save    0,ebp
325     mov     esi,[ebp+8]
326     mov     edi,[ebp+12]
327
328     rnd_fun lr_xor, lr_mov
329
330     mov     eax,ebp
331     restore ebp,0
332     xor     eax,[ebp]
333     xor     ebx,[ebp+4]
334
335 %endmacro
336
337     section .text align=32
338
339 ; AES Encryption Subroutine
340
341     do_name aes_encrypt
342
343     sub     esp,stk_spc
344     mov     [esp+16],ebp
345     mov     [esp+12],ebx
346     mov     [esp+ 8],esi
347     mov     [esp+ 4],edi
348
349     mov     esi,[esp+in_blk+stk_spc] ; input pointer
350     mov     eax,[esi   ]
351     mov     ebx,[esi+ 4]
352     mov     ecx,[esi+ 8]
353     mov     edx,[esi+12]
354
355     mov     ebp,[esp+ctx+stk_spc]    ; key pointer
356     movzx   edi,byte [ebp+4*KS_LENGTH]
357     xor     eax,[ebp   ]
358     xor     ebx,[ebp+ 4]
359     xor     ecx,[ebp+ 8]
360     xor     edx,[ebp+12]
361
362 ; determine the number of rounds
363
364     cmp     edi,10*16
365     je      .3
366     cmp     edi,12*16
367     je      .2
368     cmp     edi,14*16
369     je      .1
370     mov     eax,-1
371     jmp     .5
372
373 .1: enc_round
374     enc_round
375 .2: enc_round
376     enc_round
377 .3: enc_round
378     enc_round
379     enc_round
380     enc_round
381     enc_round
382     enc_round
383     enc_round
384     enc_round
385     enc_round
386     enc_last_round
387
388     mov     edx,[esp+out_blk+stk_spc]
389     mov     [edx],eax
390     mov     [edx+4],ebx
391     mov     [edx+8],esi
392     mov     [edx+12],edi
393     xor     eax,eax
394
395 .5: mov     ebp,[esp+16]
396     mov     ebx,[esp+12]
397     mov     esi,[esp+ 8]
398     mov     edi,[esp+ 4]
399     add     esp,stk_spc
400     do_exit
401
402 %endif
403
404 %ifdef  DECRYPTION
405
406     extern  t_in
407
408 %define dtab_0(x)   [t_in+4*x]
409 %define dtab_1(x)   [t_in+1024+4*x]
410 %define dtab_2(x)   [t_in+2048+4*x]
411 %define dtab_3(x)   [t_in+3072+4*x]
412
413 %ifdef LAST_ROUND_TABLES
414
415     extern  t_il
416
417 %define dltab_0(x)  [t_il+4*x]
418 %define dltab_1(x)  [t_il+1024+4*x]
419 %define dltab_2(x)  [t_il+2048+4*x]
420 %define dltab_3(x)  [t_il+3072+4*x]
421
422 %endif
423
424 %macro irn_fun 2
425
426     rol eax,16
427     %1      esi, cl, 0, ebp
428     %1      esi, bh, 1, ebp
429     %1      esi, al, 2, ebp
430     %1      edi, dl, 0, ebp
431     %1      edi, ch, 1, ebp
432     %1      edi, ah, 3, ebp
433     %2      ebp, bl, 0, ebp
434     shr     eax,16
435     and     ebx,0xffff0000
436     or      ebx,eax
437     shr     ecx,16
438     %1      ebp, bh, 1, eax
439     %1      ebp, ch, 3, eax
440     %2      eax, cl, 2, ecx
441     %1      eax, bl, 0, ecx
442     %1      eax, dh, 1, ecx
443     shr     ebx,16
444     shr     edx,16
445     %1      esi, dh, 3, ecx
446     %1      ebp, dl, 2, ecx
447     %1      eax, bh, 3, ecx
448     %1      edi, bl, 2, ecx
449
450 %endmacro
451
452 ; Basic MOV and XOR Operations for normal rounds
453
454 %macro  ni_xor  4
455     movzx   %4,%2
456     xor     %1,dtab_%3(%4)
457 %endmacro
458
459 %macro  ni_mov  4
460     movzx   %4,%2
461     mov     %1,dtab_%3(%4)
462 %endmacro
463
464 ; Basic MOV and XOR Operations for last round
465
466 %ifdef LAST_ROUND_TABLES
467
468 %macro  li_xor  4
469     movzx   %4,%2
470     xor     %1,dltab_%3(%4)
471 %endmacro
472
473 %macro  li_mov  4
474     movzx   %4,%2
475     mov     %1,dltab_%3(%4)
476 %endmacro
477
478 %endif
479
480 %macro dec_round 0
481
482 %ifdef AES_REV_DKS
483     add     ebp,16
484 %else
485     sub     ebp,16
486 %endif
487     save    0,ebp
488     mov     esi,[ebp+8]
489     mov     edi,[ebp+12]
490
491     irn_fun ni_xor, ni_mov
492
493     mov     ebx,ebp
494     mov     ecx,esi
495     mov     edx,edi
496     restore ebp,0
497     xor     eax,[ebp]
498     xor     ebx,[ebp+4]
499
500 %endmacro
501
502 %macro dec_last_round 0
503
504 %ifdef AES_REV_DKS
505     add     ebp,16
506 %else
507     sub     ebp,16
508 %endif
509     save    0,ebp
510     mov     esi,[ebp+8]
511     mov     edi,[ebp+12]
512
513     irn_fun li_xor, li_mov
514
515     mov     ebx,ebp
516     restore ebp,0
517     xor     eax,[ebp]
518     xor     ebx,[ebp+4]
519
520 %endmacro
521
522     section .text align=32
523
524 ; AES Decryption Subroutine
525
526     do_name aes_decrypt
527
528     sub     esp,stk_spc
529     mov     [esp+16],ebp
530     mov     [esp+12],ebx
531     mov     [esp+ 8],esi
532     mov     [esp+ 4],edi
533
534 ; input four columns and xor in first round key
535
536     mov     esi,[esp+in_blk+stk_spc] ; input pointer
537     mov     eax,[esi   ]
538     mov     ebx,[esi+ 4]
539     mov     ecx,[esi+ 8]
540     mov     edx,[esi+12]
541     lea     esi,[esi+16]
542
543     mov     ebp,[esp+ctx+stk_spc]    ; key pointer
544     movzx   edi,byte[ebp+4*KS_LENGTH]
545 %ifndef  AES_REV_DKS        ; if decryption key schedule is not reversed
546     lea     ebp,[ebp+edi]   ; we have to access it from the top down
547 %endif
548     xor     eax,[ebp   ]    ; key schedule
549     xor     ebx,[ebp+ 4]
550     xor     ecx,[ebp+ 8]
551     xor     edx,[ebp+12]
552
553 ; determine the number of rounds
554
555     cmp     edi,10*16
556     je      .3
557     cmp     edi,12*16
558     je      .2
559     cmp     edi,14*16
560     je      .1
561     mov     eax,-1
562     jmp     .5
563
564 .1: dec_round
565     dec_round
566 .2: dec_round
567     dec_round
568 .3: dec_round
569     dec_round
570     dec_round
571     dec_round
572     dec_round
573     dec_round
574     dec_round
575     dec_round
576     dec_round
577     dec_last_round
578
579 ; move final values to the output array.
580
581     mov     ebp,[esp+out_blk+stk_spc]
582     mov     [ebp],eax
583     mov     [ebp+4],ebx
584     mov     [ebp+8],esi
585     mov     [ebp+12],edi
586     xor     eax,eax
587
588 .5: mov     ebp,[esp+16]
589     mov     ebx,[esp+12]
590     mov     esi,[esp+ 8]
591     mov     edi,[esp+ 4]
592     add     esp,stk_spc
593     do_exit
594
595 %endif
596
597     end