|
|
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 either ASM_X86_V2 or ASM_X86_V2C to be set in aesopt.h
28: ; and the same define to be set here as well. If AES_V2C is set this file
29: ; requires the C files aeskey.c and aestab.c for support.
30:
31: ; An AES implementation for x86 processors using the YASM (or NASM) assembler.
32: ; This is a full assembler implementation covering encryption, decryption and
33: ; key scheduling. It uses 2k bytes of tables but its encryption and decryption
34: ; performance is very close to that obtained using large tables. Key schedule
35: ; expansion is slower for both encryption and decryption but this is likely to
36: ; be offset by the much smaller load that this version places on the processor
37: ; cache. I acknowledge the contribution made by Daniel Bernstein to aspects of
38: ; the design of the AES round function used here.
39: ;
40: ; This code provides the standard AES block size (128 bits, 16 bytes) and the
41: ; three standard AES key sizes (128, 192 and 256 bits). It has the same call
42: ; interface as my C implementation. The ebx, esi, edi and ebp registers are
43: ; preserved across calls but eax, ecx and edx and the artihmetic status flags
44: ; are not. Although this is a full assembler implementation, it can be used
45: ; in conjunction with my C code which provides faster key scheduling using
46: ; large tables. In this case aeskey.c should be compiled with ASM_X86_V2C
47: ; defined. It is also important that the defines below match those used in the
48: ; C code. This code uses the VC++ register saving conentions; if it is used
49: ; with another compiler, conventions for using and saving registers may need
50: ; to be checked (and calling conventions). The YASM command line for the VC++
51: ; custom build step is:
52: ;
53: ; yasm -Xvc -f win32 -D <Z> -o "$(TargetDir)\$(InputName).obj" "$(InputPath)"
54: ;
55: ; For the cryptlib build this is (pcg):
56: ;
57: ; yasm -Xvc -f win32 -D ASM_X86_V2C -o aescrypt2.obj aes_x86_v2.asm
58: ;
59: ; where <Z> is ASM_X86_V2 or ASM_X86_V2C. The calling intefaces are:
60: ;
61: ; AES_RETURN aes_encrypt(const unsigned char in_blk[],
62: ; unsigned char out_blk[], const aes_encrypt_ctx cx[1]);
63: ;
64: ; AES_RETURN aes_decrypt(const unsigned char in_blk[],
65: ; unsigned char out_blk[], const aes_decrypt_ctx cx[1]);
66: ;
67: ; AES_RETURN aes_encrypt_key<NNN>(const unsigned char key[],
68: ; const aes_encrypt_ctx cx[1]);
69: ;
70: ; AES_RETURN aes_decrypt_key<NNN>(const unsigned char key[],
71: ; const aes_decrypt_ctx cx[1]);
72: ;
73: ; AES_RETURN aes_encrypt_key(const unsigned char key[],
74: ; unsigned int len, const aes_decrypt_ctx cx[1]);
75: ;
76: ; AES_RETURN aes_decrypt_key(const unsigned char key[],
77: ; unsigned int len, const aes_decrypt_ctx cx[1]);
78: ;
79: ; where <NNN> is 128, 102 or 256. In the last two calls the length can be in
80: ; either bits or bytes.
81:
82: ; The DLL interface must use the _stdcall convention in which the number
83: ; of bytes of parameter space is added after an @ to the sutine's name.
84: ; We must also remove our parameters from the stack before return (see
85: ; the do_exit macro). Define DLL_EXPORT for the Dynamic Link Library version.
86:
87: ;
88: ; Adapted for TrueCrypt by the TrueCrypt Foundation:
89: ; - All tables generated at run-time
90: ; - Adapted for 16-bit environment
91: ;
92:
93: CPU 386
94: USE16
95: SEGMENT _TEXT PUBLIC CLASS=CODE USE16
96: SEGMENT _DATA PUBLIC CLASS=DATA USE16
97:
98: GROUP DGROUP _TEXT _DATA
99:
100: extern _aes_dec_tab ; Aestab.c
101: extern _aes_enc_tab
102:
103: ; %define DLL_EXPORT
104:
105: ; The size of the code can be reduced by using functions for the encryption
106: ; and decryption rounds in place of macro expansion
107:
108: %define REDUCE_CODE_SIZE
109:
110: ; Comment in/out the following lines to obtain the desired subroutines. These
111: ; selections MUST match those in the C header file aes.h
112:
113: ; %define AES_128 ; define if AES with 128 bit keys is needed
114: ; %define AES_192 ; define if AES with 192 bit keys is needed
115: %define AES_256 ; define if AES with 256 bit keys is needed
116: ; %define AES_VAR ; define if a variable key size is needed
117: %define ENCRYPTION ; define if encryption is needed
118: %define DECRYPTION ; define if decryption is needed
119: ; %define AES_REV_DKS ; define if key decryption schedule is reversed
120:
121: %ifndef ASM_X86_V2C
122: %define ENCRYPTION_KEY_SCHEDULE ; define if encryption key expansion is needed
123: %define DECRYPTION_KEY_SCHEDULE ; define if decryption key expansion is needed
124: %endif
125:
126: ; The encryption key schedule has the following in memory layout where N is the
127: ; number of rounds (10, 12 or 14):
128: ;
129: ; lo: | input key (round 0) | ; each round is four 32-bit words
130: ; | encryption round 1 |
131: ; | encryption round 2 |
132: ; ....
133: ; | encryption round N-1 |
134: ; hi: | encryption round N |
135: ;
136: ; The decryption key schedule is normally set up so that it has the same
137: ; layout as above by actually reversing the order of the encryption key
138: ; schedule in memory (this happens when AES_REV_DKS is set):
139: ;
140: ; lo: | decryption round 0 | = | encryption round N |
141: ; | decryption round 1 | = INV_MIX_COL[ | encryption round N-1 | ]
142: ; | decryption round 2 | = INV_MIX_COL[ | encryption round N-2 | ]
143: ; .... ....
144: ; | decryption round N-1 | = INV_MIX_COL[ | encryption round 1 | ]
145: ; hi: | decryption round N | = | input key (round 0) |
146: ;
147: ; with rounds except the first and last modified using inv_mix_column()
148: ; But if AES_REV_DKS is NOT set the order of keys is left as it is for
149: ; encryption so that it has to be accessed in reverse when used for
150: ; decryption (although the inverse mix column modifications are done)
151: ;
152: ; lo: | decryption round 0 | = | input key (round 0) |
153: ; | decryption round 1 | = INV_MIX_COL[ | encryption round 1 | ]
154: ; | decryption round 2 | = INV_MIX_COL[ | encryption round 2 | ]
155: ; .... ....
156: ; | decryption round N-1 | = INV_MIX_COL[ | encryption round N-1 | ]
157: ; hi: | decryption round N | = | encryption round N |
158: ;
159: ; This layout is faster when the assembler key scheduling provided here
160: ; is used.
161: ;
162: ; End of user defines
163:
164: %ifdef AES_VAR
165: %ifndef AES_128
166: %define AES_128
167: %endif
168: %ifndef AES_192
169: %define AES_192
170: %endif
171: %ifndef AES_256
172: %define AES_256
173: %endif
174: %endif
175:
176: %ifdef AES_VAR
177: %define KS_LENGTH 60
178: %elifdef AES_256
179: %define KS_LENGTH 60
180: %elifdef AES_192
181: %define KS_LENGTH 52
182: %else
183: %define KS_LENGTH 44
184: %endif
185:
186: ; These macros implement stack based local variables
187:
188: %macro save 2
189: mov [esp+4*%1],%2
190: %endmacro
191:
192: %macro restore 2
193: mov %1,[esp+4*%2]
194: %endmacro
195:
196: %ifdef REDUCE_CODE_SIZE
197: %macro mf_call 1
198: call %1
199: %endmacro
200: %else
201: %macro mf_call 1
202: %1
203: %endmacro
204: %endif
205:
206: ; the DLL has to implement the _stdcall calling interface on return
207: ; In this case we have to take our parameters (3 4-byte pointers)
208: ; off the stack
209:
210: %define parms 12
211:
212: %macro do_name 1-2 parms
213: %ifndef DLL_EXPORT
214: global %1
215: %1:
216: %else
217: global %1@%2
218: export %1@%2
219: %1@%2:
220: %endif
221: %endmacro
222:
223: %macro do_call 1-2 parms
224: %ifndef DLL_EXPORT
225: call %1
226: add esp,%2
227: %else
228: call %1@%2
229: %endif
230: %endmacro
231:
232: %macro do_exit 0-1 parms
233: %ifdef DLL_EXPORT
234: ret %1
235: %else
236: ret
237: %endif
238: %endmacro
239:
240: ; finite field multiplies by {02}, {04} and {08}
241:
242: %define f2(x) ((x<<1)^(((x>>7)&1)*0x11b))
243: %define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b))
244: %define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b))
245:
246: ; finite field multiplies required in table generation
247:
248: %define f3(x) (f2(x) ^ x)
249: %define f9(x) (f8(x) ^ x)
250: %define fb(x) (f8(x) ^ f2(x) ^ x)
251: %define fd(x) (f8(x) ^ f4(x) ^ x)
252: %define fe(x) (f8(x) ^ f4(x) ^ f2(x))
253:
254: %define etab_0(x) [_aes_enc_tab+4+8*x]
255: %define etab_1(x) [_aes_enc_tab+3+8*x]
256: %define etab_2(x) [_aes_enc_tab+2+8*x]
257: %define etab_3(x) [_aes_enc_tab+1+8*x]
258: %define etab_b(x) byte [_aes_enc_tab+1+8*x] ; used with movzx for 0x000000xx
259: %define etab_w(x) word [_aes_enc_tab+8*x] ; used with movzx for 0x0000xx00
260:
261: %define btab_0(x) [_aes_enc_tab+6+8*x]
262: %define btab_1(x) [_aes_enc_tab+5+8*x]
263: %define btab_2(x) [_aes_enc_tab+4+8*x]
264: %define btab_3(x) [_aes_enc_tab+3+8*x]
265:
266: ; ROUND FUNCTION. Build column[2] on ESI and column[3] on EDI that have the
267: ; round keys pre-loaded. Build column[0] in EBP and column[1] in EBX.
268: ;
269: ; Input:
270: ;
271: ; EAX column[0]
272: ; EBX column[1]
273: ; ECX column[2]
274: ; EDX column[3]
275: ; ESI column key[round][2]
276: ; EDI column key[round][3]
277: ; EBP scratch
278: ;
279: ; Output:
280: ;
281: ; EBP column[0] unkeyed
282: ; EBX column[1] unkeyed
283: ; ESI column[2] keyed
284: ; EDI column[3] keyed
285: ; EAX scratch
286: ; ECX scratch
287: ; EDX scratch
288:
289: %macro rnd_fun 2
290:
291: rol ebx,16
292: %1 esi, cl, 0, ebp
293: %1 esi, dh, 1, ebp
294: %1 esi, bh, 3, ebp
295: %1 edi, dl, 0, ebp
296: %1 edi, ah, 1, ebp
297: %1 edi, bl, 2, ebp
298: %2 ebp, al, 0, ebp
299: shr ebx,16
300: and eax,0xffff0000
301: or eax,ebx
302: shr edx,16
303: %1 ebp, ah, 1, ebx
304: %1 ebp, dh, 3, ebx
305: %2 ebx, dl, 2, ebx
306: %1 ebx, ch, 1, edx
307: %1 ebx, al, 0, edx
308: shr eax,16
309: shr ecx,16
310: %1 ebp, cl, 2, edx
311: %1 edi, ch, 3, edx
312: %1 esi, al, 2, edx
313: %1 ebx, ah, 3, edx
314:
315: %endmacro
316:
317: ; Basic MOV and XOR Operations for normal rounds
318:
319: %macro nr_xor 4
320: movzx %4,%2
321: xor %1,etab_%3(%4)
322: %endmacro
323:
324: %macro nr_mov 4
325: movzx %4,%2
326: mov %1,etab_%3(%4)
327: %endmacro
328:
329: ; Basic MOV and XOR Operations for last round
330:
331: %if 1
332:
333: %macro lr_xor 4
334: movzx %4,%2
335: movzx %4,etab_b(%4)
336: %if %3 != 0
337: shl %4,8*%3
338: %endif
339: xor %1,%4
340: %endmacro
341:
342: %macro lr_mov 4
343: movzx %4,%2
344: movzx %1,etab_b(%4)
345: %if %3 != 0
346: shl %1,8*%3
347: %endif
348: %endmacro
349:
350: %else ; less effective but worth leaving as an option
351:
352: %macro lr_xor 4
353: movzx %4,%2
354: mov %4,btab_%3(%4)
355: and %4,0x000000ff << 8 * %3
356: xor %1,%4
357: %endmacro
358:
359: %macro lr_mov 4
360: movzx %4,%2
361: mov %1,btab_%3(%4)
362: and %1,0x000000ff << 8 * %3
363: %endmacro
364:
365: %endif
366:
367: ; Apply S-Box to the 4 bytes in a 32-bit word and rotate byte positions
368:
369: %ifdef REDUCE_CODE_SIZE
370:
371: l3s_col:
372: movzx ecx,al ; in eax
373: movzx ecx, etab_b(ecx) ; out eax
374: xor edx,ecx ; scratch ecx,edx
375: movzx ecx,ah
376: movzx ecx, etab_b(ecx)
377: shl ecx,8
378: xor edx,ecx
379: shr eax,16
380: movzx ecx,al
381: movzx ecx, etab_b(ecx)
382: shl ecx,16
383: xor edx,ecx
384: movzx ecx,ah
385: movzx ecx, etab_b(ecx)
386: shl ecx,24
387: xor edx,ecx
388: mov eax,edx
389: ret
390:
391: %else
392:
393: %macro l3s_col 0
394:
395: movzx ecx,al ; in eax
396: movzx ecx, etab_b(ecx) ; out eax
397: xor edx,ecx ; scratch ecx,edx
398: movzx ecx,ah
399: movzx ecx, etab_b(ecx)
400: shl ecx,8
401: xor edx,ecx
402: shr eax,16
403: movzx ecx,al
404: movzx ecx, etab_b(ecx)
405: shl ecx,16
406: xor edx,ecx
407: movzx ecx,ah
408: movzx ecx, etab_b(ecx)
409: shl ecx,24
410: xor edx,ecx
411: mov eax,edx
412:
413: %endmacro
414:
415: %endif
416:
417: ; offsets to parameters
418:
419: in_blk equ 2 ; input byte array address parameter
420: out_blk equ 4 ; output byte array address parameter
421: ctx equ 6 ; AES context structure
422: stk_spc equ 20 ; stack space
423:
424: %ifdef ENCRYPTION
425:
426: ; %define ENCRYPTION_TABLE
427:
428: %ifdef REDUCE_CODE_SIZE
429:
430: enc_round:
431: sub sp, 2
432: add ebp,16
433: save 1,ebp
434: mov esi,[ebp+8]
435: mov edi,[ebp+12]
436:
437: rnd_fun nr_xor, nr_mov
438:
439: mov eax,ebp
440: mov ecx,esi
441: mov edx,edi
442: restore ebp,1
443: xor eax,[ebp]
444: xor ebx,[ebp+4]
445: add sp, 2
446: ret
447:
448: %else
449:
450: %macro enc_round 0
451:
452: add ebp,16
453: save 0,ebp
454: mov esi,[ebp+8]
455: mov edi,[ebp+12]
456:
457: rnd_fun nr_xor, nr_mov
458:
459: mov eax,ebp
460: mov ecx,esi
461: mov edx,edi
462: restore ebp,0
463: xor eax,[ebp]
464: xor ebx,[ebp+4]
465:
466: %endmacro
467:
468: %endif
469:
470: %macro enc_last_round 0
471:
472: add ebp,16
473: save 0,ebp
474: mov esi,[ebp+8]
475: mov edi,[ebp+12]
476:
477: rnd_fun lr_xor, lr_mov
478:
479: mov eax,ebp
480: restore ebp,0
481: xor eax,[ebp]
482: xor ebx,[ebp+4]
483:
484: %endmacro
485:
486: section _TEXT
487:
488: ; AES Encryption Subroutine
489:
490: do_name _aes_encrypt,12
491:
492: mov ax, sp
493: movzx esp, ax
494:
495: sub esp,stk_spc
496: mov [esp+16],ebp
497: mov [esp+12],ebx
498: mov [esp+ 8],esi
499: mov [esp+ 4],edi
500:
501: movzx esi,word [esp+in_blk+stk_spc] ; input pointer
502: mov eax,[esi ]
503: mov ebx,[esi+ 4]
504: mov ecx,[esi+ 8]
505: mov edx,[esi+12]
506:
507: movzx ebp,word [esp+ctx+stk_spc] ; key pointer
508: movzx edi,byte [ebp+4*KS_LENGTH]
509: xor eax,[ebp ]
510: xor ebx,[ebp+ 4]
511: xor ecx,[ebp+ 8]
512: xor edx,[ebp+12]
513:
514: ; determine the number of rounds
515:
516: %ifndef AES_256
517: cmp edi,10*16
518: je .3
519: cmp edi,12*16
520: je .2
521: cmp edi,14*16
522: je .1
523: mov eax,-1
524: jmp .5
525: %endif
526:
527: .1: mf_call enc_round
528: mf_call enc_round
529: .2: mf_call enc_round
530: mf_call enc_round
531: .3: mf_call enc_round
532: mf_call enc_round
533: mf_call enc_round
534: mf_call enc_round
535: mf_call enc_round
536: mf_call enc_round
537: mf_call enc_round
538: mf_call enc_round
539: mf_call enc_round
540: enc_last_round
541:
542: movzx edx,word [esp+out_blk+stk_spc]
543: mov [edx],eax
544: mov [edx+4],ebx
545: mov [edx+8],esi
546: mov [edx+12],edi
547: xor eax,eax
548:
549: .5: mov ebp,[esp+16]
550: mov ebx,[esp+12]
551: mov esi,[esp+ 8]
552: mov edi,[esp+ 4]
553: add esp,stk_spc
554: do_exit 12
555:
556: %endif
557:
558: %macro f_key 2
559:
560: push ecx
561: push edx
562: mov edx,esi
563: ror eax,8
564: mf_call l3s_col
565: mov esi,eax
566: pop edx
567: pop ecx
568: xor esi,rc_val
569:
570: mov [ebp+%1*%2],esi
571: xor edi,esi
572: mov [ebp+%1*%2+4],edi
573: xor ecx,edi
574: mov [ebp+%1*%2+8],ecx
575: xor edx,ecx
576: mov [ebp+%1*%2+12],edx
577: mov eax,edx
578:
579: %if %2 == 24
580:
581: %if %1 < 7
582: xor eax,[ebp+%1*%2+16-%2]
583: mov [ebp+%1*%2+16],eax
584: xor eax,[ebp+%1*%2+20-%2]
585: mov [ebp+%1*%2+20],eax
586: %endif
587:
588: %elif %2 == 32
589:
590: %if %1 < 6
591: push ecx
592: push edx
593: mov edx,[ebp+%1*%2+16-%2]
594: mf_call l3s_col
595: pop edx
596: pop ecx
597: mov [ebp+%1*%2+16],eax
598: xor eax,[ebp+%1*%2+20-%2]
599: mov [ebp+%1*%2+20],eax
600: xor eax,[ebp+%1*%2+24-%2]
601: mov [ebp+%1*%2+24],eax
602: xor eax,[ebp+%1*%2+28-%2]
603: mov [ebp+%1*%2+28],eax
604: %endif
605:
606: %endif
607:
608: %assign rc_val f2(rc_val)
609:
610: %endmacro
611:
612: %ifdef ENCRYPTION_KEY_SCHEDULE
613:
614: %ifdef AES_128
615:
616: %ifndef ENCRYPTION_TABLE
617: ; %define ENCRYPTION_TABLE
618: %endif
619:
620: %assign rc_val 1
621:
622: do_name _aes_encrypt_key128,8
623:
624: push ebp
625: push ebx
626: push esi
627: push edi
628:
629: mov ebp,[esp+24]
630: mov [ebp+4*KS_LENGTH],dword 10*16
631: mov ebx,[esp+20]
632:
633: mov esi,[ebx]
634: mov [ebp],esi
635: mov edi,[ebx+4]
636: mov [ebp+4],edi
637: mov ecx,[ebx+8]
638: mov [ebp+8],ecx
639: mov edx,[ebx+12]
640: mov [ebp+12],edx
641: add ebp,16
642: mov eax,edx
643:
644: f_key 0,16 ; 11 * 4 = 44 unsigned longs
645: f_key 1,16 ; 4 + 4 * 10 generated = 44
646: f_key 2,16
647: f_key 3,16
648: f_key 4,16
649: f_key 5,16
650: f_key 6,16
651: f_key 7,16
652: f_key 8,16
653: f_key 9,16
654:
655: pop edi
656: pop esi
657: pop ebx
658: pop ebp
659: xor eax,eax
660: do_exit 8
661:
662: %endif
663:
664: %ifdef AES_192
665:
666: %ifndef ENCRYPTION_TABLE
667: ; %define ENCRYPTION_TABLE
668: %endif
669:
670: %assign rc_val 1
671:
672: do_name _aes_encrypt_key192,8
673:
674: push ebp
675: push ebx
676: push esi
677: push edi
678:
679: mov ebp,[esp+24]
680: mov [ebp+4*KS_LENGTH],dword 12 * 16
681: mov ebx,[esp+20]
682:
683: mov esi,[ebx]
684: mov [ebp],esi
685: mov edi,[ebx+4]
686: mov [ebp+4],edi
687: mov ecx,[ebx+8]
688: mov [ebp+8],ecx
689: mov edx,[ebx+12]
690: mov [ebp+12],edx
691: mov eax,[ebx+16]
692: mov [ebp+16],eax
693: mov eax,[ebx+20]
694: mov [ebp+20],eax
695: add ebp,24
696:
697: f_key 0,24 ; 13 * 4 = 52 unsigned longs
698: f_key 1,24 ; 6 + 6 * 8 generated = 54
699: f_key 2,24
700: f_key 3,24
701: f_key 4,24
702: f_key 5,24
703: f_key 6,24
704: f_key 7,24
705:
706: pop edi
707: pop esi
708: pop ebx
709: pop ebp
710: xor eax,eax
711: do_exit 8
712:
713: %endif
714:
715: %ifdef AES_256
716:
717: %ifndef ENCRYPTION_TABLE
718: ; %define ENCRYPTION_TABLE
719: %endif
720:
721: %assign rc_val 1
722:
723: do_name _aes_encrypt_key256,8
724:
725: mov ax, sp
726: movzx esp, ax
727:
728: push ebp
729: push ebx
730: push esi
731: push edi
732:
733: movzx ebp, word [esp+20] ; ks
734: mov [ebp+4*KS_LENGTH],dword 14 * 16
735: movzx ebx, word [esp+18] ; key
736:
737: mov esi,[ebx]
738: mov [ebp],esi
739: mov edi,[ebx+4]
740: mov [ebp+4],edi
741: mov ecx,[ebx+8]
742: mov [ebp+8],ecx
743: mov edx,[ebx+12]
744: mov [ebp+12],edx
745: mov eax,[ebx+16]
746: mov [ebp+16],eax
747: mov eax,[ebx+20]
748: mov [ebp+20],eax
749: mov eax,[ebx+24]
750: mov [ebp+24],eax
751: mov eax,[ebx+28]
752: mov [ebp+28],eax
753: add ebp,32
754:
755: f_key 0,32 ; 15 * 4 = 60 unsigned longs
756: f_key 1,32 ; 8 + 8 * 7 generated = 64
757: f_key 2,32
758: f_key 3,32
759: f_key 4,32
760: f_key 5,32
761: f_key 6,32
762:
763: pop edi
764: pop esi
765: pop ebx
766: pop ebp
767: xor eax,eax
768: do_exit 8
769:
770: %endif
771:
772: %ifdef AES_VAR
773:
774: %ifndef ENCRYPTION_TABLE
775: ; %define ENCRYPTION_TABLE
776: %endif
777:
778: do_name _aes_encrypt_key,12
779:
780: mov ecx,[esp+4]
781: mov eax,[esp+8]
782: mov edx,[esp+12]
783: push edx
784: push ecx
785:
786: cmp eax,16
787: je .1
788: cmp eax,128
789: je .1
790:
791: cmp eax,24
792: je .2
793: cmp eax,192
794: je .2
795:
796: cmp eax,32
797: je .3
798: cmp eax,256
799: je .3
800: mov eax,-1
801: add esp,8
802: do_exit 12
803:
804: .1: do_call _aes_encrypt_key128,8
805: do_exit 12
806: .2: do_call _aes_encrypt_key192,8
807: do_exit 12
808: .3: do_call _aes_encrypt_key256,8
809: do_exit 12
810:
811: %endif
812:
813: %endif
814:
815: %ifdef ENCRYPTION_TABLE
816:
817: ; S-box data - 256 entries
818:
819: section _DATA
820:
821: %define u8(x) 0, x, x, f3(x), f2(x), x, x, f3(x)
822:
823: _aes_enc_tab:
824: db u8(0x63),u8(0x7c),u8(0x77),u8(0x7b),u8(0xf2),u8(0x6b),u8(0x6f),u8(0xc5)
825: db u8(0x30),u8(0x01),u8(0x67),u8(0x2b),u8(0xfe),u8(0xd7),u8(0xab),u8(0x76)
826: db u8(0xca),u8(0x82),u8(0xc9),u8(0x7d),u8(0xfa),u8(0x59),u8(0x47),u8(0xf0)
827: db u8(0xad),u8(0xd4),u8(0xa2),u8(0xaf),u8(0x9c),u8(0xa4),u8(0x72),u8(0xc0)
828: db u8(0xb7),u8(0xfd),u8(0x93),u8(0x26),u8(0x36),u8(0x3f),u8(0xf7),u8(0xcc)
829: db u8(0x34),u8(0xa5),u8(0xe5),u8(0xf1),u8(0x71),u8(0xd8),u8(0x31),u8(0x15)
830: db u8(0x04),u8(0xc7),u8(0x23),u8(0xc3),u8(0x18),u8(0x96),u8(0x05),u8(0x9a)
831: db u8(0x07),u8(0x12),u8(0x80),u8(0xe2),u8(0xeb),u8(0x27),u8(0xb2),u8(0x75)
832: db u8(0x09),u8(0x83),u8(0x2c),u8(0x1a),u8(0x1b),u8(0x6e),u8(0x5a),u8(0xa0)
833: db u8(0x52),u8(0x3b),u8(0xd6),u8(0xb3),u8(0x29),u8(0xe3),u8(0x2f),u8(0x84)
834: db u8(0x53),u8(0xd1),u8(0x00),u8(0xed),u8(0x20),u8(0xfc),u8(0xb1),u8(0x5b)
835: db u8(0x6a),u8(0xcb),u8(0xbe),u8(0x39),u8(0x4a),u8(0x4c),u8(0x58),u8(0xcf)
836: db u8(0xd0),u8(0xef),u8(0xaa),u8(0xfb),u8(0x43),u8(0x4d),u8(0x33),u8(0x85)
837: db u8(0x45),u8(0xf9),u8(0x02),u8(0x7f),u8(0x50),u8(0x3c),u8(0x9f),u8(0xa8)
838: db u8(0x51),u8(0xa3),u8(0x40),u8(0x8f),u8(0x92),u8(0x9d),u8(0x38),u8(0xf5)
839: db u8(0xbc),u8(0xb6),u8(0xda),u8(0x21),u8(0x10),u8(0xff),u8(0xf3),u8(0xd2)
840: db u8(0xcd),u8(0x0c),u8(0x13),u8(0xec),u8(0x5f),u8(0x97),u8(0x44),u8(0x17)
841: db u8(0xc4),u8(0xa7),u8(0x7e),u8(0x3d),u8(0x64),u8(0x5d),u8(0x19),u8(0x73)
842: db u8(0x60),u8(0x81),u8(0x4f),u8(0xdc),u8(0x22),u8(0x2a),u8(0x90),u8(0x88)
843: db u8(0x46),u8(0xee),u8(0xb8),u8(0x14),u8(0xde),u8(0x5e),u8(0x0b),u8(0xdb)
844: db u8(0xe0),u8(0x32),u8(0x3a),u8(0x0a),u8(0x49),u8(0x06),u8(0x24),u8(0x5c)
845: db u8(0xc2),u8(0xd3),u8(0xac),u8(0x62),u8(0x91),u8(0x95),u8(0xe4),u8(0x79)
846: db u8(0xe7),u8(0xc8),u8(0x37),u8(0x6d),u8(0x8d),u8(0xd5),u8(0x4e),u8(0xa9)
847: db u8(0x6c),u8(0x56),u8(0xf4),u8(0xea),u8(0x65),u8(0x7a),u8(0xae),u8(0x08)
848: db u8(0xba),u8(0x78),u8(0x25),u8(0x2e),u8(0x1c),u8(0xa6),u8(0xb4),u8(0xc6)
849: db u8(0xe8),u8(0xdd),u8(0x74),u8(0x1f),u8(0x4b),u8(0xbd),u8(0x8b),u8(0x8a)
850: db u8(0x70),u8(0x3e),u8(0xb5),u8(0x66),u8(0x48),u8(0x03),u8(0xf6),u8(0x0e)
851: db u8(0x61),u8(0x35),u8(0x57),u8(0xb9),u8(0x86),u8(0xc1),u8(0x1d),u8(0x9e)
852: db u8(0xe1),u8(0xf8),u8(0x98),u8(0x11),u8(0x69),u8(0xd9),u8(0x8e),u8(0x94)
853: db u8(0x9b),u8(0x1e),u8(0x87),u8(0xe9),u8(0xce),u8(0x55),u8(0x28),u8(0xdf)
854: db u8(0x8c),u8(0xa1),u8(0x89),u8(0x0d),u8(0xbf),u8(0xe6),u8(0x42),u8(0x68)
855: db u8(0x41),u8(0x99),u8(0x2d),u8(0x0f),u8(0xb0),u8(0x54),u8(0xbb),u8(0x16)
856:
857: %endif
858:
859: %ifdef DECRYPTION
860:
861: ; %define DECRYPTION_TABLE
862:
863: %define dtab_0(x) [_aes_dec_tab+ 8*x]
864: %define dtab_1(x) [_aes_dec_tab+3+8*x]
865: %define dtab_2(x) [_aes_dec_tab+2+8*x]
866: %define dtab_3(x) [_aes_dec_tab+1+8*x]
867: %define dtab_x(x) byte [_aes_dec_tab+7+8*x]
868:
869: %macro irn_fun 2
870:
871: rol eax,16
872: %1 esi, cl, 0, ebp
873: %1 esi, bh, 1, ebp
874: %1 esi, al, 2, ebp
875: %1 edi, dl, 0, ebp
876: %1 edi, ch, 1, ebp
877: %1 edi, ah, 3, ebp
878: %2 ebp, bl, 0, ebp
879: shr eax,16
880: and ebx,0xffff0000
881: or ebx,eax
882: shr ecx,16
883: %1 ebp, bh, 1, eax
884: %1 ebp, ch, 3, eax
885: %2 eax, cl, 2, ecx
886: %1 eax, bl, 0, ecx
887: %1 eax, dh, 1, ecx
888: shr ebx,16
889: shr edx,16
890: %1 esi, dh, 3, ecx
891: %1 ebp, dl, 2, ecx
892: %1 eax, bh, 3, ecx
893: %1 edi, bl, 2, ecx
894:
895: %endmacro
896:
897: ; Basic MOV and XOR Operations for normal rounds
898:
899: %macro ni_xor 4
900: movzx %4,%2
901: xor %1,dtab_%3(%4)
902: %endmacro
903:
904: %macro ni_mov 4
905: movzx %4,%2
906: mov %1,dtab_%3(%4)
907: %endmacro
908:
909: ; Basic MOV and XOR Operations for last round
910:
911: %macro li_xor 4
912: movzx %4,%2
913: movzx %4,dtab_x(%4)
914: %if %3 != 0
915: shl %4,8*%3
916: %endif
917: xor %1,%4
918: %endmacro
919:
920: %macro li_mov 4
921: movzx %4,%2
922: movzx %1,dtab_x(%4)
923: %if %3 != 0
924: shl %1,8*%3
925: %endif
926: %endmacro
927:
928: %ifdef REDUCE_CODE_SIZE
929:
930: dec_round:
931: sub sp, 2
932: %ifdef AES_REV_DKS
933: add ebp,16
934: %else
935: sub ebp,16
936: %endif
937: save 1,ebp
938: mov esi,[ebp+8]
939: mov edi,[ebp+12]
940:
941: irn_fun ni_xor, ni_mov
942:
943: mov ebx,ebp
944: mov ecx,esi
945: mov edx,edi
946: restore ebp,1
947: xor eax,[ebp]
948: xor ebx,[ebp+4]
949: add sp, 2
950: ret
951:
952: %else
953:
954: %macro dec_round 0
955:
956: %ifdef AES_REV_DKS
957: add ebp,16
958: %else
959: sub ebp,16
960: %endif
961: save 0,ebp
962: mov esi,[ebp+8]
963: mov edi,[ebp+12]
964:
965: irn_fun ni_xor, ni_mov
966:
967: mov ebx,ebp
968: mov ecx,esi
969: mov edx,edi
970: restore ebp,0
971: xor eax,[ebp]
972: xor ebx,[ebp+4]
973:
974: %endmacro
975:
976: %endif
977:
978: %macro dec_last_round 0
979:
980: %ifdef AES_REV_DKS
981: add ebp,16
982: %else
983: sub ebp,16
984: %endif
985: save 0,ebp
986: mov esi,[ebp+8]
987: mov edi,[ebp+12]
988:
989: irn_fun li_xor, li_mov
990:
991: mov ebx,ebp
992: restore ebp,0
993: xor eax,[ebp]
994: xor ebx,[ebp+4]
995:
996: %endmacro
997:
998: section _TEXT
999:
1000: ; AES Decryption Subroutine
1001:
1002: do_name _aes_decrypt,12
1003:
1004: mov ax, sp
1005: movzx esp, ax
1006:
1007: sub esp,stk_spc
1008: mov [esp+16],ebp
1009: mov [esp+12],ebx
1010: mov [esp+ 8],esi
1011: mov [esp+ 4],edi
1012:
1013: ; input four columns and xor in first round key
1014:
1015: movzx esi,word [esp+in_blk+stk_spc] ; input pointer
1016: mov eax,[esi ]
1017: mov ebx,[esi+ 4]
1018: mov ecx,[esi+ 8]
1019: mov edx,[esi+12]
1020: lea esi,[esi+16]
1021:
1022: movzx ebp, word [esp+ctx+stk_spc] ; key pointer
1023: movzx edi,byte[ebp+4*KS_LENGTH]
1024: %ifndef AES_REV_DKS ; if decryption key schedule is not reversed
1025: lea ebp,[ebp+edi] ; we have to access it from the top down
1026: %endif
1027: xor eax,[ebp ] ; key schedule
1028: xor ebx,[ebp+ 4]
1029: xor ecx,[ebp+ 8]
1030: xor edx,[ebp+12]
1031:
1032: ; determine the number of rounds
1033:
1034: %ifndef AES_256
1035: cmp edi,10*16
1036: je .3
1037: cmp edi,12*16
1038: je .2
1039: cmp edi,14*16
1040: je .1
1041: mov eax,-1
1042: jmp .5
1043: %endif
1044:
1045: .1: mf_call dec_round
1046: mf_call dec_round
1047: .2: mf_call dec_round
1048: mf_call dec_round
1049: .3: mf_call dec_round
1050: mf_call dec_round
1051: mf_call dec_round
1052: mf_call dec_round
1053: mf_call dec_round
1054: mf_call dec_round
1055: mf_call dec_round
1056: mf_call dec_round
1057: mf_call dec_round
1058: dec_last_round
1059:
1060: ; move final values to the output array.
1061:
1062: movzx ebp,word [esp+out_blk+stk_spc]
1063: mov [ebp],eax
1064: mov [ebp+4],ebx
1065: mov [ebp+8],esi
1066: mov [ebp+12],edi
1067: xor eax,eax
1068:
1069: .5: mov ebp,[esp+16]
1070: mov ebx,[esp+12]
1071: mov esi,[esp+ 8]
1072: mov edi,[esp+ 4]
1073: add esp,stk_spc
1074: do_exit 12
1075:
1076: %endif
1077:
1078: %ifdef REDUCE_CODE_SIZE
1079:
1080: inv_mix_col:
1081: movzx ecx,dl ; input eax, edx
1082: movzx ecx,etab_b(ecx) ; output eax
1083: mov eax,dtab_0(ecx) ; used ecx
1084: movzx ecx,dh
1085: shr edx,16
1086: movzx ecx,etab_b(ecx)
1087: xor eax,dtab_1(ecx)
1088: movzx ecx,dl
1089: movzx ecx,etab_b(ecx)
1090: xor eax,dtab_2(ecx)
1091: movzx ecx,dh
1092: movzx ecx,etab_b(ecx)
1093: xor eax,dtab_3(ecx)
1094: ret
1095:
1096: %else
1097:
1098: %macro inv_mix_col 0
1099:
1100: movzx ecx,dl ; input eax, edx
1101: movzx ecx,etab_b(ecx) ; output eax
1102: mov eax,dtab_0(ecx) ; used ecx
1103: movzx ecx,dh
1104: shr edx,16
1105: movzx ecx,etab_b(ecx)
1106: xor eax,dtab_1(ecx)
1107: movzx ecx,dl
1108: movzx ecx,etab_b(ecx)
1109: xor eax,dtab_2(ecx)
1110: movzx ecx,dh
1111: movzx ecx,etab_b(ecx)
1112: xor eax,dtab_3(ecx)
1113:
1114: %endmacro
1115:
1116: %endif
1117:
1118: %ifdef DECRYPTION_KEY_SCHEDULE
1119:
1120: %ifdef AES_128
1121:
1122: %ifndef DECRYPTION_TABLE
1123: ; %define DECRYPTION_TABLE
1124: %endif
1125:
1126: do_name _aes_decrypt_key128,8
1127:
1128: push ebp
1129: push ebx
1130: push esi
1131: push edi
1132: mov eax,[esp+24] ; context
1133: mov edx,[esp+20] ; key
1134: push eax
1135: push edx
1136: do_call _aes_encrypt_key128,8 ; generate expanded encryption key
1137: mov eax,10*16
1138: mov esi,[esp+24] ; pointer to first round key
1139: lea edi,[esi+eax] ; pointer to last round key
1140: add esi,32
1141: ; the inverse mix column transformation
1142: mov edx,[esi-16] ; needs to be applied to all round keys
1143: mf_call inv_mix_col ; except first and last. Hence start by
1144: mov [esi-16],eax ; transforming the four sub-keys in the
1145: mov edx,[esi-12] ; second round key
1146: mf_call inv_mix_col
1147: mov [esi-12],eax ; transformations for subsequent rounds
1148: mov edx,[esi-8] ; can then be made more efficient by
1149: mf_call inv_mix_col ; noting that for three of the four sub-keys
1150: mov [esi-8],eax ; in the encryption round key ek[r]:
1151: mov edx,[esi-4] ;
1152: mf_call inv_mix_col ; ek[r][n] = ek[r][n-1] ^ ek[r-1][n]
1153: mov [esi-4],eax ;
1154: ; where n is 1..3. Hence the corresponding
1155: .0: mov edx,[esi] ; subkeys in the decryption round key dk[r]
1156: mf_call inv_mix_col ; also obey since inv_mix_col is linear in
1157: mov [esi],eax ; GF(256):
1158: xor eax,[esi-12] ;
1159: mov [esi+4],eax ; dk[r][n] = dk[r][n-1] ^ dk[r-1][n]
1160: xor eax,[esi-8] ;
1161: mov [esi+8],eax ; So we only need one inverse mix column
1162: xor eax,[esi-4] ; operation (n = 0) for each four word cycle
1163: mov [esi+12],eax ; in the expanded key.
1164: add esi,16
1165: cmp edi,esi
1166: jg .0
1167: jmp dec_end
1168:
1169: %endif
1170:
1171: %ifdef AES_192
1172:
1173: %ifndef DECRYPTION_TABLE
1174: ; %define DECRYPTION_TABLE
1175: %endif
1176:
1177: do_name _aes_decrypt_key192,8
1178:
1179: push ebp
1180: push ebx
1181: push esi
1182: push edi
1183: mov eax,[esp+24] ; context
1184: mov edx,[esp+20] ; key
1185: push eax
1186: push edx
1187: do_call _aes_encrypt_key192,8 ; generate expanded encryption key
1188: mov eax,12*16
1189: mov esi,[esp+24] ; first round key
1190: lea edi,[esi+eax] ; last round key
1191: add esi,48 ; the first 6 words are the key, of
1192: ; which the top 2 words are part of
1193: mov edx,[esi-32] ; the second round key and hence
1194: mf_call inv_mix_col ; need to be modified. After this we
1195: mov [esi-32],eax ; need to do a further six values prior
1196: mov edx,[esi-28] ; to using a more efficient technique
1197: mf_call inv_mix_col ; based on:
1198: mov [esi-28],eax ;
1199: ; dk[r][n] = dk[r][n-1] ^ dk[r-1][n]
1200: mov edx,[esi-24] ;
1201: mf_call inv_mix_col ; for n = 1 .. 5 where the key expansion
1202: mov [esi-24],eax ; cycle is now 6 words long
1203: mov edx,[esi-20]
1204: mf_call inv_mix_col
1205: mov [esi-20],eax
1206: mov edx,[esi-16]
1207: mf_call inv_mix_col
1208: mov [esi-16],eax
1209: mov edx,[esi-12]
1210: mf_call inv_mix_col
1211: mov [esi-12],eax
1212: mov edx,[esi-8]
1213: mf_call inv_mix_col
1214: mov [esi-8],eax
1215: mov edx,[esi-4]
1216: mf_call inv_mix_col
1217: mov [esi-4],eax
1218:
1219: .0: mov edx,[esi] ; the expanded key is 13 * 4 = 44 32-bit words
1220: mf_call inv_mix_col ; of which 11 * 4 = 44 have to be modified
1221: mov [esi],eax ; using inv_mix_col. We have already done 8
1222: xor eax,[esi-20] ; of these so 36 are left - hence we need
1223: mov [esi+4],eax ; exactly 6 loops of six here
1224: xor eax,[esi-16]
1225: mov [esi+8],eax
1226: xor eax,[esi-12]
1227: mov [esi+12],eax
1228: xor eax,[esi-8]
1229: mov [esi+16],eax
1230: xor eax,[esi-4]
1231: mov [esi+20],eax
1232: add esi,24
1233: cmp edi,esi
1234: jg .0
1235: jmp dec_end
1236:
1237: %endif
1238:
1239: %ifdef AES_256
1240:
1241: %ifndef DECRYPTION_TABLE
1242: ; %define DECRYPTION_TABLE
1243: %endif
1244:
1245: do_name _aes_decrypt_key256,8
1246:
1247: mov ax, sp
1248: movzx esp, ax
1249: push ebp
1250: push ebx
1251: push esi
1252: push edi
1253:
1254: movzx eax, word [esp+20] ; ks
1255: movzx edx, word [esp+18] ; key
1256: push ax
1257: push dx
1258: do_call _aes_encrypt_key256,4 ; generate expanded encryption key
1259: mov eax,14*16
1260: movzx esi, word [esp+20] ; ks
1261: lea edi,[esi+eax]
1262: add esi,64
1263:
1264: mov edx,[esi-48] ; the primary key is 8 words, of which
1265: mf_call inv_mix_col ; the top four require modification
1266: mov [esi-48],eax
1267: mov edx,[esi-44]
1268: mf_call inv_mix_col
1269: mov [esi-44],eax
1270: mov edx,[esi-40]
1271: mf_call inv_mix_col
1272: mov [esi-40],eax
1273: mov edx,[esi-36]
1274: mf_call inv_mix_col
1275: mov [esi-36],eax
1276:
1277: mov edx,[esi-32] ; the encryption key expansion cycle is
1278: mf_call inv_mix_col ; now eight words long so we need to
1279: mov [esi-32],eax ; start by doing one complete block
1280: mov edx,[esi-28]
1281: mf_call inv_mix_col
1282: mov [esi-28],eax
1283: mov edx,[esi-24]
1284: mf_call inv_mix_col
1285: mov [esi-24],eax
1286: mov edx,[esi-20]
1287: mf_call inv_mix_col
1288: mov [esi-20],eax
1289: mov edx,[esi-16]
1290: mf_call inv_mix_col
1291: mov [esi-16],eax
1292: mov edx,[esi-12]
1293: mf_call inv_mix_col
1294: mov [esi-12],eax
1295: mov edx,[esi-8]
1296: mf_call inv_mix_col
1297: mov [esi-8],eax
1298: mov edx,[esi-4]
1299: mf_call inv_mix_col
1300: mov [esi-4],eax
1301:
1302: .0: mov edx,[esi] ; we can now speed up the remaining
1303: mf_call inv_mix_col ; rounds by using the technique
1304: mov [esi],eax ; outlined earlier. But note that
1305: xor eax,[esi-28] ; there is one extra inverse mix
1306: mov [esi+4],eax ; column operation as the 256 bit
1307: xor eax,[esi-24] ; key has an extra non-linear step
1308: mov [esi+8],eax ; for the midway element.
1309: xor eax,[esi-20]
1310: mov [esi+12],eax ; the expanded key is 15 * 4 = 60
1311: mov edx,[esi+16] ; 32-bit words of which 52 need to
1312: mf_call inv_mix_col ; be modified. We have already done
1313: mov [esi+16],eax ; 12 so 40 are left - which means
1314: xor eax,[esi-12] ; that we need exactly 5 loops of 8
1315: mov [esi+20],eax
1316: xor eax,[esi-8]
1317: mov [esi+24],eax
1318: xor eax,[esi-4]
1319: mov [esi+28],eax
1320: add esi,32
1321: cmp edi,esi
1322: jg .0
1323:
1324: %endif
1325:
1326: dec_end:
1327:
1328: %ifdef AES_REV_DKS
1329:
1330: movzx esi,word [esp+20] ; this reverses the order of the
1331: .1: mov eax,[esi] ; round keys if required
1332: mov ebx,[esi+4]
1333: mov ebp,[edi]
1334: mov edx,[edi+4]
1335: mov [esi],ebp
1336: mov [esi+4],edx
1337: mov [edi],eax
1338: mov [edi+4],ebx
1339:
1340: mov eax,[esi+8]
1341: mov ebx,[esi+12]
1342: mov ebp,[edi+8]
1343: mov edx,[edi+12]
1344: mov [esi+8],ebp
1345: mov [esi+12],edx
1346: mov [edi+8],eax
1347: mov [edi+12],ebx
1348:
1349: add esi,16
1350: sub edi,16
1351: cmp edi,esi
1352: jg .1
1353:
1354: %endif
1355:
1356: pop edi
1357: pop esi
1358: pop ebx
1359: pop ebp
1360: xor eax,eax
1361: do_exit 8
1362:
1363: %ifdef AES_VAR
1364:
1365: do_name _aes_decrypt_key,12
1366:
1367: mov ecx,[esp+4]
1368: mov eax,[esp+8]
1369: mov edx,[esp+12]
1370: push edx
1371: push ecx
1372:
1373: cmp eax,16
1374: je .1
1375: cmp eax,128
1376: je .1
1377:
1378: cmp eax,24
1379: je .2
1380: cmp eax,192
1381: je .2
1382:
1383: cmp eax,32
1384: je .3
1385: cmp eax,256
1386: je .3
1387: mov eax,-1
1388: add esp,8
1389: do_exit 12
1390:
1391: .1: do_call _aes_decrypt_key128,8
1392: do_exit 12
1393: .2: do_call _aes_decrypt_key192,8
1394: do_exit 12
1395: .3: do_call _aes_decrypt_key256,8
1396: do_exit 12
1397:
1398: %endif
1399:
1400: %endif
1401:
1402: %ifdef DECRYPTION_TABLE
1403:
1404: ; Inverse S-box data - 256 entries
1405:
1406: section _DATA
1407:
1408: %define v8(x) fe(x), f9(x), fd(x), fb(x), fe(x), f9(x), fd(x), x
1409:
1410: _aes_dec_tab:
1411: db v8(0x52),v8(0x09),v8(0x6a),v8(0xd5),v8(0x30),v8(0x36),v8(0xa5),v8(0x38)
1412: db v8(0xbf),v8(0x40),v8(0xa3),v8(0x9e),v8(0x81),v8(0xf3),v8(0xd7),v8(0xfb)
1413: db v8(0x7c),v8(0xe3),v8(0x39),v8(0x82),v8(0x9b),v8(0x2f),v8(0xff),v8(0x87)
1414: db v8(0x34),v8(0x8e),v8(0x43),v8(0x44),v8(0xc4),v8(0xde),v8(0xe9),v8(0xcb)
1415: db v8(0x54),v8(0x7b),v8(0x94),v8(0x32),v8(0xa6),v8(0xc2),v8(0x23),v8(0x3d)
1416: db v8(0xee),v8(0x4c),v8(0x95),v8(0x0b),v8(0x42),v8(0xfa),v8(0xc3),v8(0x4e)
1417: db v8(0x08),v8(0x2e),v8(0xa1),v8(0x66),v8(0x28),v8(0xd9),v8(0x24),v8(0xb2)
1418: db v8(0x76),v8(0x5b),v8(0xa2),v8(0x49),v8(0x6d),v8(0x8b),v8(0xd1),v8(0x25)
1419: db v8(0x72),v8(0xf8),v8(0xf6),v8(0x64),v8(0x86),v8(0x68),v8(0x98),v8(0x16)
1420: db v8(0xd4),v8(0xa4),v8(0x5c),v8(0xcc),v8(0x5d),v8(0x65),v8(0xb6),v8(0x92)
1421: db v8(0x6c),v8(0x70),v8(0x48),v8(0x50),v8(0xfd),v8(0xed),v8(0xb9),v8(0xda)
1422: db v8(0x5e),v8(0x15),v8(0x46),v8(0x57),v8(0xa7),v8(0x8d),v8(0x9d),v8(0x84)
1423: db v8(0x90),v8(0xd8),v8(0xab),v8(0x00),v8(0x8c),v8(0xbc),v8(0xd3),v8(0x0a)
1424: db v8(0xf7),v8(0xe4),v8(0x58),v8(0x05),v8(0xb8),v8(0xb3),v8(0x45),v8(0x06)
1425: db v8(0xd0),v8(0x2c),v8(0x1e),v8(0x8f),v8(0xca),v8(0x3f),v8(0x0f),v8(0x02)
1426: db v8(0xc1),v8(0xaf),v8(0xbd),v8(0x03),v8(0x01),v8(0x13),v8(0x8a),v8(0x6b)
1427: db v8(0x3a),v8(0x91),v8(0x11),v8(0x41),v8(0x4f),v8(0x67),v8(0xdc),v8(0xea)
1428: db v8(0x97),v8(0xf2),v8(0xcf),v8(0xce),v8(0xf0),v8(0xb4),v8(0xe6),v8(0x73)
1429: db v8(0x96),v8(0xac),v8(0x74),v8(0x22),v8(0xe7),v8(0xad),v8(0x35),v8(0x85)
1430: db v8(0xe2),v8(0xf9),v8(0x37),v8(0xe8),v8(0x1c),v8(0x75),v8(0xdf),v8(0x6e)
1431: db v8(0x47),v8(0xf1),v8(0x1a),v8(0x71),v8(0x1d),v8(0x29),v8(0xc5),v8(0x89)
1432: db v8(0x6f),v8(0xb7),v8(0x62),v8(0x0e),v8(0xaa),v8(0x18),v8(0xbe),v8(0x1b)
1433: db v8(0xfc),v8(0x56),v8(0x3e),v8(0x4b),v8(0xc6),v8(0xd2),v8(0x79),v8(0x20)
1434: db v8(0x9a),v8(0xdb),v8(0xc0),v8(0xfe),v8(0x78),v8(0xcd),v8(0x5a),v8(0xf4)
1435: db v8(0x1f),v8(0xdd),v8(0xa8),v8(0x33),v8(0x88),v8(0x07),v8(0xc7),v8(0x31)
1436: db v8(0xb1),v8(0x12),v8(0x10),v8(0x59),v8(0x27),v8(0x80),v8(0xec),v8(0x5f)
1437: db v8(0x60),v8(0x51),v8(0x7f),v8(0xa9),v8(0x19),v8(0xb5),v8(0x4a),v8(0x0d)
1438: db v8(0x2d),v8(0xe5),v8(0x7a),v8(0x9f),v8(0x93),v8(0xc9),v8(0x9c),v8(0xef)
1439: db v8(0xa0),v8(0xe0),v8(0x3b),v8(0x4d),v8(0xae),v8(0x2a),v8(0xf5),v8(0xb0)
1440: db v8(0xc8),v8(0xeb),v8(0xbb),v8(0x3c),v8(0x83),v8(0x53),v8(0x99),v8(0x61)
1441: db v8(0x17),v8(0x2b),v8(0x04),v8(0x7e),v8(0xba),v8(0x77),v8(0xd6),v8(0x26)
1442: db v8(0xe1),v8(0x69),v8(0x14),v8(0x63),v8(0x55),v8(0x21),v8(0x0c),v8(0x7d)
1443:
1444: %endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.