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