1 #!/usr/local/bin/perl
   2 
   3 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
   4 push(@INC,"${dir}","${dir}../../perlasm");
   5 require "x86asm.pl";
   6 require "cbc.pl";
   7 
   8 &asm_init($ARGV[0],"bf-586.pl",$ARGV[$#ARGV] eq "386");
   9 
  10 $BF_ROUNDS=16;
  11 $BF_OFF=($BF_ROUNDS+2)*4;
  12 $L="edi";
  13 $R="esi";
  14 $P="ebp";
  15 $tmp1="eax";
  16 $tmp2="ebx";
  17 $tmp3="ecx";
  18 $tmp4="edx";
  19 
  20 &BF_encrypt("BF_encrypt",1);
  21 &BF_encrypt("BF_decrypt",0);
  22 &cbc("BF_cbc_encrypt","BF_encrypt","BF_decrypt",1,4,5,3,-1,-1);
  23 &asm_finish();
  24 
  25 sub BF_encrypt
  26         {
  27         local($name,$enc)=@_;
  28 
  29         &function_begin_B($name,"");
  30 
  31         &comment("");
  32 
  33         &push("ebp");
  34         &push("ebx");
  35         &mov($tmp2,&wparam(0));
  36         &mov($P,&wparam(1));
  37         &push("esi");
  38         &push("edi");
  39 
  40         &comment("Load the 2 words");
  41         &mov($L,&DWP(0,$tmp2,"",0));
  42         &mov($R,&DWP(4,$tmp2,"",0));
  43 
  44         &xor(       $tmp1,  $tmp1);
  45 
  46         # encrypting part
  47 
  48         if ($enc)
  49                 {
  50                  &mov($tmp2,&DWP(0,$P,"",0));
  51                 &xor(       $tmp3,  $tmp3);
  52 
  53                 &xor($L,$tmp2);
  54                 for ($i=0; $i<$BF_ROUNDS; $i+=2)
  55                         {
  56                         &comment("");
  57                         &comment("Round $i");
  58                         &BF_ENCRYPT($i+1,$R,$L,$P,$tmp1,$tmp2,$tmp3,$tmp4,1);
  59 
  60                         &comment("");
  61                         &comment("Round ".sprintf("%d",$i+1));
  62                         &BF_ENCRYPT($i+2,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,1);
  63                         }
  64                 # &mov($tmp1,&wparam(0)); In last loop
  65                 &mov($tmp4,&DWP(($BF_ROUNDS+1)*4,$P,"",0));
  66                 }
  67         else
  68                 {
  69                  &mov($tmp2,&DWP(($BF_ROUNDS+1)*4,$P,"",0));
  70                 &xor(       $tmp3,  $tmp3);
  71 
  72                 &xor($L,$tmp2);
  73                 for ($i=$BF_ROUNDS; $i>0; $i-=2)
  74                         {
  75                         &comment("");
  76                         &comment("Round $i");
  77                         &BF_ENCRYPT($i,$R,$L,$P,$tmp1,$tmp2,$tmp3,$tmp4,0);
  78                         &comment("");
  79                         &comment("Round ".sprintf("%d",$i-1));
  80                         &BF_ENCRYPT($i-1,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,0);
  81                         }
  82                 # &mov($tmp1,&wparam(0)); In last loop
  83                 &mov($tmp4,&DWP(0,$P,"",0));
  84                 }
  85 
  86         &xor($R,$tmp4);
  87         &mov(&DWP(4,$tmp1,"",0),$L);
  88 
  89         &mov(&DWP(0,$tmp1,"",0),$R);
  90         &function_end($name);
  91         }
  92 
  93 sub BF_ENCRYPT
  94         {
  95         local($i,$L,$R,$P,$tmp1,$tmp2,$tmp3,$tmp4,$enc)=@_;
  96 
  97         &mov(       $tmp4,          &DWP(&n2a($i*4),$P,"",0)); # for next round
  98 
  99         &mov(       $tmp2,          $R);
 100         &xor(       $L,             $tmp4);
 101 
 102         &shr(       $tmp2,          16);
 103         &mov(       $tmp4,          $R);
 104 
 105         &movb(      &LB($tmp1), &HB($tmp2));        # A
 106         &and(       $tmp2,          0xff);          # B
 107 
 108         &movb(      &LB($tmp3), &HB($tmp4));        # C
 109         &and(       $tmp4,          0xff);          # D
 110 
 111         &mov(       $tmp1,          &DWP(&n2a($BF_OFF+0x0000),$P,$tmp1,4));
 112         &mov(       $tmp2,          &DWP(&n2a($BF_OFF+0x0400),$P,$tmp2,4));
 113 
 114         &add(       $tmp2,          $tmp1);
 115         &mov(       $tmp1,          &DWP(&n2a($BF_OFF+0x0800),$P,$tmp3,4));
 116 
 117         &xor(       $tmp2,          $tmp1);
 118         &mov(       $tmp4,          &DWP(&n2a($BF_OFF+0x0C00),$P,$tmp4,4));
 119 
 120         &add(       $tmp2,          $tmp4);
 121         if (($enc && ($i != 16)) || ((!$enc) && ($i != 1)))
 122                 { &xor(     $tmp1,          $tmp1); }
 123         else
 124                 {
 125                 &comment("Load parameter 0 ($i) enc=$enc");
 126                 &mov($tmp1,&wparam(0));
 127                 } # In last loop
 128 
 129         &xor(       $L,             $tmp2);
 130         # delay
 131         }
 132 
 133 sub n2a
 134         {
 135         sprintf("%d",$_[0]);
 136         }