|
|
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.