|
|
1.1 root 1:
2: ; ---------------------------------------------------------------------------
3: ; Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved.
4: ;
5: ; LICENSE TERMS
6: ;
7: ; The free distribution and use of this software is allowed (with or without
8: ; changes) provided that:
9: ;
10: ; 1. source code distributions include the above copyright notice, this
11: ; list of conditions and the following disclaimer;
12: ;
13: ; 2. binary distributions include the above copyright notice, this list
14: ; of conditions and the following disclaimer in their documentation;
15: ;
16: ; 3. the name of the copyright holder is not used to endorse products
17: ; built using this software without specific written permission.
18: ;
19: ; DISCLAIMER
20: ;
21: ; This software is provided 'as is' with no explicit or implied warranties
22: ; in respect of its properties, including, but not limited to, correctness
23: ; and/or fitness for purpose.
24: ; ---------------------------------------------------------------------------
25: ; Issue 20/12/2007
26: ;
27: ; This code requires ASM_X86_V1C to be set in aesopt.h. It requires the C files
28: ; aeskey.c and aestab.c for support.
29:
1.1.1.2 ! root 30: ;
! 31: ; Adapted for TrueCrypt by the TrueCrypt Foundation:
! 32: ; - Adapted for NASM
! 33: ;
! 34:
1.1 root 35: ; An AES implementation for x86 processors using the YASM (or NASM) assembler.
36: ; This is an assembler implementation that covers encryption and decryption
37: ; only and is intended as a replacement of the C file aescrypt.c. It hence
38: ; requires the file aeskey.c for keying and aestab.c for the AES tables. It
39: ; employs full tables rather than compressed tables.
40:
41: ; This code provides the standard AES block size (128 bits, 16 bytes) and the
42: ; three standard AES key sizes (128, 192 and 256 bits). It has the same call
43: ; interface as my C implementation. The ebx, esi, edi and ebp registers are
44: ; preserved across calls but eax, ecx and edx and the artihmetic status flags
45: ; are not. It is also important that the defines below match those used in the
46: ; C code. This code uses the VC++ register saving conentions; if it is used
47: ; with another compiler, conventions for using and saving registers may need to
48: ; be checked (and calling conventions). The YASM command line for the VC++
49: ; custom build step is:
50: ;
51: ; yasm -Xvc -f win32 -o "$(TargetDir)\$(InputName).obj" "$(InputPath)"
52: ;
53: ; The calling intefaces are:
54: ;
55: ; AES_RETURN aes_encrypt(const unsigned char in_blk[],
56: ; unsigned char out_blk[], const aes_encrypt_ctx cx[1]);
57: ;
58: ; AES_RETURN aes_decrypt(const unsigned char in_blk[],
59: ; unsigned char out_blk[], const aes_decrypt_ctx cx[1]);
60: ;
61: ; AES_RETURN aes_encrypt_key<NNN>(const unsigned char key[],
62: ; const aes_encrypt_ctx cx[1]);
63: ;
64: ; AES_RETURN aes_decrypt_key<NNN>(const unsigned char key[],
65: ; const aes_decrypt_ctx cx[1]);
66: ;
67: ; AES_RETURN aes_encrypt_key(const unsigned char key[],
68: ; unsigned int len, const aes_decrypt_ctx cx[1]);
69: ;
70: ; AES_RETURN aes_decrypt_key(const unsigned char key[],
71: ; unsigned int len, const aes_decrypt_ctx cx[1]);
72: ;
73: ; where <NNN> is 128, 102 or 256. In the last two calls the length can be in
74: ; either bits or bytes.
75: ;
76: ; Comment in/out the following lines to obtain the desired subroutines. These
77: ; selections MUST match those in the C header file aes.h
78:
79: ; %define AES_128 ; define if AES with 128 bit keys is needed
80: ; %define AES_192 ; define if AES with 192 bit keys is needed
81: %define AES_256 ; define if AES with 256 bit keys is needed
82: ; %define AES_VAR ; define if a variable key size is needed
83: %define ENCRYPTION ; define if encryption is needed
84: %define DECRYPTION ; define if decryption is needed
85: %define AES_REV_DKS ; define if key decryption schedule is reversed
86: %define LAST_ROUND_TABLES ; define if tables are to be used for last round
87:
88: ; offsets to parameters
89:
90: in_blk equ 4 ; input byte array address parameter
91: out_blk equ 8 ; output byte array address parameter
92: ctx equ 12 ; AES context structure
93: stk_spc equ 20 ; stack space
94: %define parms 12 ; parameter space on stack
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: ; These macros implement stack based local variables
164:
165: %macro save 2
166: mov [esp+4*%1],%2
167: %endmacro
168:
169: %macro restore 2
170: mov %1,[esp+4*%2]
171: %endmacro
172:
173: ; the DLL has to implement the _stdcall calling interface on return
174: ; In this case we have to take our parameters (3 4-byte pointers)
175: ; off the stack
176:
177: %macro do_name 1-2 parms
178: %ifndef DLL_EXPORT
179: align 32
180: global %1
181: %1:
182: %else
183: align 32
184: global %1@%2
185: export %1@%2
186: %1@%2:
187: %endif
188: %endmacro
189:
190: %macro do_call 1-2 parms
191: %ifndef DLL_EXPORT
192: call %1
193: add esp,%2
194: %else
195: call %1@%2
196: %endif
197: %endmacro
198:
199: %macro do_exit 0-1 parms
200: %ifdef DLL_EXPORT
201: ret %1
202: %else
203: ret
204: %endif
205: %endmacro
206:
207: %ifdef ENCRYPTION
208:
209: extern _t_fn
210:
211: %define etab_0(x) [_t_fn+4*x]
212: %define etab_1(x) [_t_fn+1024+4*x]
213: %define etab_2(x) [_t_fn+2048+4*x]
214: %define etab_3(x) [_t_fn+3072+4*x]
215:
216: %ifdef LAST_ROUND_TABLES
217:
218: extern _t_fl
219:
220: %define eltab_0(x) [_t_fl+4*x]
221: %define eltab_1(x) [_t_fl+1024+4*x]
222: %define eltab_2(x) [_t_fl+2048+4*x]
223: %define eltab_3(x) [_t_fl+3072+4*x]
224:
225: %else
226:
227: %define etab_b(x) byte [_t_fn+3072+4*x]
228:
229: %endif
230:
231: ; ROUND FUNCTION. Build column[2] on ESI and column[3] on EDI that have the
232: ; round keys pre-loaded. Build column[0] in EBP and column[1] in EBX.
233: ;
234: ; Input:
235: ;
236: ; EAX column[0]
237: ; EBX column[1]
238: ; ECX column[2]
239: ; EDX column[3]
240: ; ESI column key[round][2]
241: ; EDI column key[round][3]
242: ; EBP scratch
243: ;
244: ; Output:
245: ;
246: ; EBP column[0] unkeyed
247: ; EBX column[1] unkeyed
248: ; ESI column[2] keyed
249: ; EDI column[3] keyed
250: ; EAX scratch
251: ; ECX scratch
252: ; EDX scratch
253:
254: %macro rnd_fun 2
255:
256: rol ebx,16
257: %1 esi, cl, 0, ebp
258: %1 esi, dh, 1, ebp
259: %1 esi, bh, 3, ebp
260: %1 edi, dl, 0, ebp
261: %1 edi, ah, 1, ebp
262: %1 edi, bl, 2, ebp
263: %2 ebp, al, 0, ebp
264: shr ebx,16
265: and eax,0xffff0000
266: or eax,ebx
267: shr edx,16
268: %1 ebp, ah, 1, ebx
269: %1 ebp, dh, 3, ebx
270: %2 ebx, dl, 2, ebx
271: %1 ebx, ch, 1, edx
272: %1 ebx, al, 0, edx
273: shr eax,16
274: shr ecx,16
275: %1 ebp, cl, 2, edx
276: %1 edi, ch, 3, edx
277: %1 esi, al, 2, edx
278: %1 ebx, ah, 3, edx
279:
280: %endmacro
281:
282: ; Basic MOV and XOR Operations for normal rounds
283:
284: %macro nr_xor 4
285: movzx %4,%2
286: xor %1,etab_%3(%4)
287: %endmacro
288:
289: %macro nr_mov 4
290: movzx %4,%2
291: mov %1,etab_%3(%4)
292: %endmacro
293:
294: ; Basic MOV and XOR Operations for last round
295:
296: %ifdef LAST_ROUND_TABLES
297:
298: %macro lr_xor 4
299: movzx %4,%2
300: xor %1,eltab_%3(%4)
301: %endmacro
302:
303: %macro lr_mov 4
304: movzx %4,%2
305: mov %1,eltab_%3(%4)
306: %endmacro
307:
308: %else
309:
310: %macro lr_xor 4
311: movzx %4,%2
312: movzx %4,etab_b(%4)
313: %if %3 != 0
314: shl %4,8*%3
315: %endif
316: xor %1,%4
317: %endmacro
318:
319: %macro lr_mov 4
320: movzx %4,%2
321: movzx %1,etab_b(%4)
322: %if %3 != 0
323: shl %1,8*%3
324: %endif
325: %endmacro
326:
327: %endif
328:
329: %macro enc_round 0
330:
331: add ebp,16
332: save 0,ebp
333: mov esi,[ebp+8]
334: mov edi,[ebp+12]
335:
336: rnd_fun nr_xor, nr_mov
337:
338: mov eax,ebp
339: mov ecx,esi
340: mov edx,edi
341: restore ebp,0
342: xor eax,[ebp]
343: xor ebx,[ebp+4]
344:
345: %endmacro
346:
347: %macro enc_last_round 0
348:
349: add ebp,16
350: save 0,ebp
351: mov esi,[ebp+8]
352: mov edi,[ebp+12]
353:
354: rnd_fun lr_xor, lr_mov
355:
356: mov eax,ebp
357: restore ebp,0
358: xor eax,[ebp]
359: xor ebx,[ebp+4]
360:
361: %endmacro
362:
363: section .text align=32
364:
365: ; AES Encryption Subroutine
366:
367: do_name _aes_encrypt
368:
369: sub esp,stk_spc
370: mov [esp+16],ebp
371: mov [esp+12],ebx
372: mov [esp+ 8],esi
373: mov [esp+ 4],edi
374:
375: mov esi,[esp+in_blk+stk_spc] ; input pointer
376: mov eax,[esi ]
377: mov ebx,[esi+ 4]
378: mov ecx,[esi+ 8]
379: mov edx,[esi+12]
380:
381: mov ebp,[esp+ctx+stk_spc] ; key pointer
382: movzx edi,byte [ebp+4*KS_LENGTH]
383: xor eax,[ebp ]
384: xor ebx,[ebp+ 4]
385: xor ecx,[ebp+ 8]
386: xor edx,[ebp+12]
387:
388: ; determine the number of rounds
389:
390: cmp edi,10*16
391: je .3
392: cmp edi,12*16
393: je .2
394: cmp edi,14*16
395: je .1
396: mov eax,-1
397: jmp .5
398:
399: .1: enc_round
400: enc_round
401: .2: enc_round
402: enc_round
403: .3: enc_round
404: enc_round
405: enc_round
406: enc_round
407: enc_round
408: enc_round
409: enc_round
410: enc_round
411: enc_round
412: enc_last_round
413:
414: mov edx,[esp+out_blk+stk_spc]
415: mov [edx],eax
416: mov [edx+4],ebx
417: mov [edx+8],esi
418: mov [edx+12],edi
419: xor eax,eax
420:
421: .5: mov ebp,[esp+16]
422: mov ebx,[esp+12]
423: mov esi,[esp+ 8]
424: mov edi,[esp+ 4]
425: add esp,stk_spc
426: do_exit
427:
428: %endif
429:
430: %ifdef DECRYPTION
431:
432: extern _t_in
433:
434: %define dtab_0(x) [_t_in+4*x]
435: %define dtab_1(x) [_t_in+1024+4*x]
436: %define dtab_2(x) [_t_in+2048+4*x]
437: %define dtab_3(x) [_t_in+3072+4*x]
438:
439: %ifdef LAST_ROUND_TABLES
440:
441: extern _t_il
442:
443: %define dltab_0(x) [_t_il+4*x]
444: %define dltab_1(x) [_t_il+1024+4*x]
445: %define dltab_2(x) [_t_il+2048+4*x]
446: %define dltab_3(x) [_t_il+3072+4*x]
447:
448: %else
449:
450: extern _t_ibox
451:
452: %define dtab_x(x) byte [_t_ibox+x]
453:
454: %endif
455:
456: %macro irn_fun 2
457:
458: rol eax,16
459: %1 esi, cl, 0, ebp
460: %1 esi, bh, 1, ebp
461: %1 esi, al, 2, ebp
462: %1 edi, dl, 0, ebp
463: %1 edi, ch, 1, ebp
464: %1 edi, ah, 3, ebp
465: %2 ebp, bl, 0, ebp
466: shr eax,16
467: and ebx,0xffff0000
468: or ebx,eax
469: shr ecx,16
470: %1 ebp, bh, 1, eax
471: %1 ebp, ch, 3, eax
472: %2 eax, cl, 2, ecx
473: %1 eax, bl, 0, ecx
474: %1 eax, dh, 1, ecx
475: shr ebx,16
476: shr edx,16
477: %1 esi, dh, 3, ecx
478: %1 ebp, dl, 2, ecx
479: %1 eax, bh, 3, ecx
480: %1 edi, bl, 2, ecx
481:
482: %endmacro
483:
484: ; Basic MOV and XOR Operations for normal rounds
485:
486: %macro ni_xor 4
487: movzx %4,%2
488: xor %1,dtab_%3(%4)
489: %endmacro
490:
491: %macro ni_mov 4
492: movzx %4,%2
493: mov %1,dtab_%3(%4)
494: %endmacro
495:
496: ; Basic MOV and XOR Operations for last round
497:
498: %ifdef LAST_ROUND_TABLES
499:
500: %macro li_xor 4
501: movzx %4,%2
502: xor %1,dltab_%3(%4)
503: %endmacro
504:
505: %macro li_mov 4
506: movzx %4,%2
507: mov %1,dltab_%3(%4)
508: %endmacro
509:
510: %else
511:
512: %macro li_xor 4
513: movzx %4,%2
514: movzx %4,dtab_x(%4)
515: %if %3 != 0
516: shl %4,8*%3
517: %endif
518: xor %1,%4
519: %endmacro
520:
521: %macro li_mov 4
522: movzx %4,%2
523: movzx %1,dtab_x(%4)
524: %if %3 != 0
525: shl %1,8*%3
526: %endif
527: %endmacro
528:
529: %endif
530:
531: %macro dec_round 0
532:
533: %ifdef AES_REV_DKS
534: add ebp,16
535: %else
536: sub ebp,16
537: %endif
538: save 0,ebp
539: mov esi,[ebp+8]
540: mov edi,[ebp+12]
541:
542: irn_fun ni_xor, ni_mov
543:
544: mov ebx,ebp
545: mov ecx,esi
546: mov edx,edi
547: restore ebp,0
548: xor eax,[ebp]
549: xor ebx,[ebp+4]
550:
551: %endmacro
552:
553: %macro dec_last_round 0
554:
555: %ifdef AES_REV_DKS
556: add ebp,16
557: %else
558: sub ebp,16
559: %endif
560: save 0,ebp
561: mov esi,[ebp+8]
562: mov edi,[ebp+12]
563:
564: irn_fun li_xor, li_mov
565:
566: mov ebx,ebp
567: restore ebp,0
568: xor eax,[ebp]
569: xor ebx,[ebp+4]
570:
571: %endmacro
572:
573: section .text
574:
575: ; AES Decryption Subroutine
576:
577: do_name _aes_decrypt
578:
579: sub esp,stk_spc
580: mov [esp+16],ebp
581: mov [esp+12],ebx
582: mov [esp+ 8],esi
583: mov [esp+ 4],edi
584:
585: ; input four columns and xor in first round key
586:
587: mov esi,[esp+in_blk+stk_spc] ; input pointer
588: mov eax,[esi ]
589: mov ebx,[esi+ 4]
590: mov ecx,[esi+ 8]
591: mov edx,[esi+12]
592: lea esi,[esi+16]
593:
594: mov ebp,[esp+ctx+stk_spc] ; key pointer
595: movzx edi,byte[ebp+4*KS_LENGTH]
596: %ifndef AES_REV_DKS ; if decryption key schedule is not reversed
597: lea ebp,[ebp+edi] ; we have to access it from the top down
598: %endif
599: xor eax,[ebp ] ; key schedule
600: xor ebx,[ebp+ 4]
601: xor ecx,[ebp+ 8]
602: xor edx,[ebp+12]
603:
604: ; determine the number of rounds
605:
606: cmp edi,10*16
607: je .3
608: cmp edi,12*16
609: je .2
610: cmp edi,14*16
611: je .1
612: mov eax,-1
613: jmp .5
614:
615: .1: dec_round
616: dec_round
617: .2: dec_round
618: dec_round
619: .3: dec_round
620: dec_round
621: dec_round
622: dec_round
623: dec_round
624: dec_round
625: dec_round
626: dec_round
627: dec_round
628: dec_last_round
629:
630: ; move final values to the output array.
631:
632: mov ebp,[esp+out_blk+stk_spc]
633: mov [ebp],eax
634: mov [ebp+4],ebx
635: mov [ebp+8],esi
636: mov [ebp+12],edi
637: xor eax,eax
638:
639: .5: mov ebp,[esp+16]
640: mov ebx,[esp+12]
641: mov esi,[esp+ 8]
642: mov edi,[esp+ 4]
643: add esp,stk_spc
644: do_exit
645:
646: %endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.