"Fossies" - the Fresh Open Source Software Archive

Member "src/Crypto/Aes_x86.asm" (10 Oct 2018, 15529 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Generic Assembler source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    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 ;
   31 ; Adapted for TrueCrypt:
   32 ; - Compatibility with NASM and GCC
   33 ;
   34 
   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
  647 
  648 %ifidn __OUTPUT_FORMAT__,elf
  649 section .note.GNU-stack noalloc noexec nowrite progbits
  650 %endif
  651 %ifidn __OUTPUT_FORMAT__,elf32
  652 section .note.GNU-stack noalloc noexec nowrite progbits
  653 %endif
  654 %ifidn __OUTPUT_FORMAT__,elf64
  655 section .note.GNU-stack noalloc noexec nowrite progbits
  656 %endif
  657