Added assembler AES for x86 and x86_64.
[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 %else
223
224 %define etab_b(x)   byte [t_fn+3072+4*x]
225
226 %endif
227
228 ; ROUND FUNCTION.  Build column[2] on ESI and column[3] on EDI that have the
229 ; round keys pre-loaded. Build column[0] in EBP and column[1] in EBX.
230 ;
231 ; Input:
232 ;
233 ;   EAX     column[0]
234 ;   EBX     column[1]
235 ;   ECX     column[2]
236 ;   EDX     column[3]
237 ;   ESI     column key[round][2]
238 ;   EDI     column key[round][3]
239 ;   EBP     scratch
240 ;
241 ; Output:
242 ;
243 ;   EBP     column[0]   unkeyed
244 ;   EBX     column[1]   unkeyed
245 ;   ESI     column[2]   keyed
246 ;   EDI     column[3]   keyed
247 ;   EAX     scratch
248 ;   ECX     scratch
249 ;   EDX     scratch
250
251 %macro rnd_fun 2
252
253     rol     ebx,16
254     %1      esi, cl, 0, ebp
255     %1      esi, dh, 1, ebp
256     %1      esi, bh, 3, ebp
257     %1      edi, dl, 0, ebp
258     %1      edi, ah, 1, ebp
259     %1      edi, bl, 2, ebp
260     %2      ebp, al, 0, ebp
261     shr     ebx,16
262     and     eax,0xffff0000
263     or      eax,ebx
264     shr     edx,16
265     %1      ebp, ah, 1, ebx
266     %1      ebp, dh, 3, ebx
267     %2      ebx, dl, 2, ebx
268     %1      ebx, ch, 1, edx
269     %1      ebx, al, 0, edx
270     shr     eax,16
271     shr     ecx,16
272     %1      ebp, cl, 2, edx
273     %1      edi, ch, 3, edx
274     %1      esi, al, 2, edx
275     %1      ebx, ah, 3, edx
276
277 %endmacro
278
279 ; Basic MOV and XOR Operations for normal rounds
280
281 %macro  nr_xor  4
282     movzx   %4,%2
283     xor     %1,etab_%3(%4)
284 %endmacro
285
286 %macro  nr_mov  4
287     movzx   %4,%2
288     mov     %1,etab_%3(%4)
289 %endmacro
290
291 ; Basic MOV and XOR Operations for last round
292
293 %ifdef LAST_ROUND_TABLES
294
295     %macro  lr_xor  4
296         movzx   %4,%2
297         xor     %1,eltab_%3(%4)
298     %endmacro
299
300     %macro  lr_mov  4
301         movzx   %4,%2
302         mov     %1,eltab_%3(%4)
303     %endmacro
304
305 %else
306
307     %macro  lr_xor  4
308         movzx   %4,%2
309         movzx   %4,etab_b(%4)
310     %if %3 != 0
311         shl     %4,8*%3
312     %endif
313         xor     %1,%4
314     %endmacro
315
316     %macro  lr_mov  4
317         movzx   %4,%2
318         movzx   %1,etab_b(%4)
319     %if %3 != 0
320         shl     %1,8*%3
321     %endif
322     %endmacro
323
324 %endif
325
326 %macro enc_round 0
327
328     add     ebp,16
329     save    0,ebp
330     mov     esi,[ebp+8]
331     mov     edi,[ebp+12]
332
333     rnd_fun nr_xor, nr_mov
334
335     mov     eax,ebp
336     mov     ecx,esi
337     mov     edx,edi
338     restore ebp,0
339     xor     eax,[ebp]
340     xor     ebx,[ebp+4]
341
342 %endmacro
343
344 %macro enc_last_round 0
345
346     add     ebp,16
347     save    0,ebp
348     mov     esi,[ebp+8]
349     mov     edi,[ebp+12]
350
351     rnd_fun lr_xor, lr_mov
352
353     mov     eax,ebp
354     restore ebp,0
355     xor     eax,[ebp]
356     xor     ebx,[ebp+4]
357
358 %endmacro
359
360     section .text align=32
361
362 ; AES Encryption Subroutine
363
364     do_name aes_encrypt
365
366     sub     esp,stk_spc
367     mov     [esp+16],ebp
368     mov     [esp+12],ebx
369     mov     [esp+ 8],esi
370     mov     [esp+ 4],edi
371
372     mov     esi,[esp+in_blk+stk_spc] ; input pointer
373     mov     eax,[esi   ]
374     mov     ebx,[esi+ 4]
375     mov     ecx,[esi+ 8]
376     mov     edx,[esi+12]
377
378     mov     ebp,[esp+ctx+stk_spc]    ; key pointer
379     movzx   edi,byte [ebp+4*KS_LENGTH]
380     xor     eax,[ebp   ]
381     xor     ebx,[ebp+ 4]
382     xor     ecx,[ebp+ 8]
383     xor     edx,[ebp+12]
384
385 ; determine the number of rounds
386
387     cmp     edi,10*16
388     je      .3
389     cmp     edi,12*16
390     je      .2
391     cmp     edi,14*16
392     je      .1
393     mov     eax,-1
394     jmp     .5
395
396 .1: enc_round
397     enc_round
398 .2: enc_round
399     enc_round
400 .3: enc_round
401     enc_round
402     enc_round
403     enc_round
404     enc_round
405     enc_round
406     enc_round
407     enc_round
408     enc_round
409     enc_last_round
410
411     mov     edx,[esp+out_blk+stk_spc]
412     mov     [edx],eax
413     mov     [edx+4],ebx
414     mov     [edx+8],esi
415     mov     [edx+12],edi
416     xor     eax,eax
417
418 .5: mov     ebp,[esp+16]
419     mov     ebx,[esp+12]
420     mov     esi,[esp+ 8]
421     mov     edi,[esp+ 4]
422     add     esp,stk_spc
423     do_exit
424
425 %endif
426
427 %ifdef  DECRYPTION
428
429     extern  t_in
430
431 %define dtab_0(x)   [t_in+4*x]
432 %define dtab_1(x)   [t_in+1024+4*x]
433 %define dtab_2(x)   [t_in+2048+4*x]
434 %define dtab_3(x)   [t_in+3072+4*x]
435
436 %ifdef LAST_ROUND_TABLES
437
438     extern  t_il
439
440 %define dltab_0(x)  [t_il+4*x]
441 %define dltab_1(x)  [t_il+1024+4*x]
442 %define dltab_2(x)  [t_il+2048+4*x]
443 %define dltab_3(x)  [t_il+3072+4*x]
444
445 %else
446
447     extern  t_ibox
448
449 %define dtab_x(x)   byte [t_ibox+x]
450
451 %endif
452
453 %macro irn_fun 2
454
455     rol eax,16
456     %1      esi, cl, 0, ebp
457     %1      esi, bh, 1, ebp
458     %1      esi, al, 2, ebp
459     %1      edi, dl, 0, ebp
460     %1      edi, ch, 1, ebp
461     %1      edi, ah, 3, ebp
462     %2      ebp, bl, 0, ebp
463     shr     eax,16
464     and     ebx,0xffff0000
465     or      ebx,eax
466     shr     ecx,16
467     %1      ebp, bh, 1, eax
468     %1      ebp, ch, 3, eax
469     %2      eax, cl, 2, ecx
470     %1      eax, bl, 0, ecx
471     %1      eax, dh, 1, ecx
472     shr     ebx,16
473     shr     edx,16
474     %1      esi, dh, 3, ecx
475     %1      ebp, dl, 2, ecx
476     %1      eax, bh, 3, ecx
477     %1      edi, bl, 2, ecx
478
479 %endmacro
480
481 ; Basic MOV and XOR Operations for normal rounds
482
483 %macro  ni_xor  4
484     movzx   %4,%2
485     xor     %1,dtab_%3(%4)
486 %endmacro
487
488 %macro  ni_mov  4
489     movzx   %4,%2
490     mov     %1,dtab_%3(%4)
491 %endmacro
492
493 ; Basic MOV and XOR Operations for last round
494
495 %ifdef LAST_ROUND_TABLES
496
497 %macro  li_xor  4
498     movzx   %4,%2
499     xor     %1,dltab_%3(%4)
500 %endmacro
501
502 %macro  li_mov  4
503     movzx   %4,%2
504     mov     %1,dltab_%3(%4)
505 %endmacro
506
507 %else
508
509     %macro  li_xor  4
510         movzx   %4,%2
511         movzx   %4,dtab_x(%4)
512     %if %3 != 0
513         shl     %4,8*%3
514     %endif
515         xor     %1,%4
516     %endmacro
517
518     %macro  li_mov  4
519         movzx   %4,%2
520         movzx   %1,dtab_x(%4)
521     %if %3 != 0
522         shl     %1,8*%3
523     %endif
524     %endmacro
525
526 %endif
527
528 %macro dec_round 0
529
530 %ifdef AES_REV_DKS
531     add     ebp,16
532 %else
533     sub     ebp,16
534 %endif
535     save    0,ebp
536     mov     esi,[ebp+8]
537     mov     edi,[ebp+12]
538
539     irn_fun ni_xor, ni_mov
540
541     mov     ebx,ebp
542     mov     ecx,esi
543     mov     edx,edi
544     restore ebp,0
545     xor     eax,[ebp]
546     xor     ebx,[ebp+4]
547
548 %endmacro
549
550 %macro dec_last_round 0
551
552 %ifdef AES_REV_DKS
553     add     ebp,16
554 %else
555     sub     ebp,16
556 %endif
557     save    0,ebp
558     mov     esi,[ebp+8]
559     mov     edi,[ebp+12]
560
561     irn_fun li_xor, li_mov
562
563     mov     ebx,ebp
564     restore ebp,0
565     xor     eax,[ebp]
566     xor     ebx,[ebp+4]
567
568 %endmacro
569
570     section .text align=32
571
572 ; AES Decryption Subroutine
573
574     do_name aes_decrypt
575
576     sub     esp,stk_spc
577     mov     [esp+16],ebp
578     mov     [esp+12],ebx
579     mov     [esp+ 8],esi
580     mov     [esp+ 4],edi
581
582 ; input four columns and xor in first round key
583
584     mov     esi,[esp+in_blk+stk_spc] ; input pointer
585     mov     eax,[esi   ]
586     mov     ebx,[esi+ 4]
587     mov     ecx,[esi+ 8]
588     mov     edx,[esi+12]
589     lea     esi,[esi+16]
590
591     mov     ebp,[esp+ctx+stk_spc]    ; key pointer
592     movzx   edi,byte[ebp+4*KS_LENGTH]
593 %ifndef  AES_REV_DKS        ; if decryption key schedule is not reversed
594     lea     ebp,[ebp+edi]   ; we have to access it from the top down
595 %endif
596     xor     eax,[ebp   ]    ; key schedule
597     xor     ebx,[ebp+ 4]
598     xor     ecx,[ebp+ 8]
599     xor     edx,[ebp+12]
600
601 ; determine the number of rounds
602
603     cmp     edi,10*16
604     je      .3
605     cmp     edi,12*16
606     je      .2
607     cmp     edi,14*16
608     je      .1
609     mov     eax,-1
610     jmp     .5
611
612 .1: dec_round
613     dec_round
614 .2: dec_round
615     dec_round
616 .3: dec_round
617     dec_round
618     dec_round
619     dec_round
620     dec_round
621     dec_round
622     dec_round
623     dec_round
624     dec_round
625     dec_last_round
626
627 ; move final values to the output array.
628
629     mov     ebp,[esp+out_blk+stk_spc]
630     mov     [ebp],eax
631     mov     [ebp+4],ebx
632     mov     [ebp+8],esi
633     mov     [ebp+12],edi
634     xor     eax,eax
635
636 .5: mov     ebp,[esp+16]
637     mov     ebx,[esp+12]
638     mov     esi,[esp+ 8]
639     mov     edi,[esp+ 4]
640     add     esp,stk_spc
641     do_exit
642
643 %endif
644
645     end