1 #!/usr/local/bin/perl
   2 #
   3 # The inner loop instruction sequence and the IP/FP modifications are from
   4 # Svend Olaf Mikkelsen <svolaf@inet.uni-c.dk>
   5 # I've added the stuff needed for crypt() but I've not worried about making
   6 # things perfect.
   7 #
   8 
   9 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
  10 push(@INC,"${dir}","${dir}../../perlasm");
  11 require "x86asm.pl";
  12 
  13 &asm_init($ARGV[0],"crypt586.pl");
  14 
  15 $L="edi";
  16 $R="esi";
  17 
  18 &external_label("DES_SPtrans");
  19 &fcrypt_body("fcrypt_body");
  20 &asm_finish();
  21 
  22 sub fcrypt_body
  23         {
  24         local($name,$do_ip)=@_;
  25 
  26         &function_begin($name);
  27 
  28         &comment("");
  29         &comment("Load the 2 words");
  30         $trans="ebp";
  31 
  32         &xor(       $L,     $L);
  33         &xor(       $R,     $R);
  34 
  35         # PIC-ification:-)
  36         &picmeup("edx","DES_SPtrans");
  37         #if ($cpp)      { &picmeup("edx","DES_SPtrans");   }
  38         #else           { &lea("edx",&DWP("DES_SPtrans")); }
  39         &push("edx");       # becomes &swtmp(1)
  40         #
  41         &mov($trans,&wparam(1)); # reloaded with DES_SPtrans in D_ENCRYPT
  42 
  43         &push(&DWC(25)); # add a variable
  44 
  45         &set_label("start");
  46         for ($i=0; $i<16; $i+=2)
  47                 {
  48                 &comment("");
  49                 &comment("Round $i");
  50                 &D_ENCRYPT($i,$L,$R,$i*2,$trans,"eax","ebx","ecx","edx");
  51 
  52                 &comment("");
  53                 &comment("Round ".sprintf("%d",$i+1));
  54                 &D_ENCRYPT($i+1,$R,$L,($i+1)*2,$trans,"eax","ebx","ecx","edx");
  55                 }
  56          &mov("ebx",        &swtmp(0));
  57         &mov("eax", $L);
  58          &dec("ebx");
  59         &mov($L,    $R);
  60          &mov($R,   "eax");
  61         &mov(&swtmp(0), "ebx");
  62          &jnz(&label("start"));
  63 
  64         &comment("");
  65         &comment("FP");
  66         &mov("edx",&wparam(0));
  67 
  68         &FP_new($R,$L,"eax",3);
  69         &mov(&DWP(0,"edx","",0),"eax");
  70         &mov(&DWP(4,"edx","",0),$L);
  71 
  72         &add("esp",8);      # remove variables
  73 
  74         &function_end($name);
  75         }
  76 
  77 sub D_ENCRYPT
  78         {
  79         local($r,$L,$R,$S,$trans,$u,$tmp1,$tmp2,$t)=@_;
  80 
  81         &mov(       $u,             &wparam(2));                        # 2
  82         &mov(       $t,             $R);
  83         &shr(       $t,             16);                            # 1
  84         &mov(       $tmp2,          &wparam(3));                        # 2
  85         &xor(       $t,             $R);                            # 1
  86 
  87         &and(       $u,             $t);                            # 2
  88         &and(       $t,             $tmp2);                         # 2
  89 
  90         &mov(       $tmp1,          $u);
  91         &shl(       $tmp1,          16);                            # 1
  92         &mov(       $tmp2,          $t);
  93         &shl(       $tmp2,          16);                            # 1
  94         &xor(       $u,             $tmp1);                         # 2
  95         &xor(       $t,             $tmp2);                         # 2
  96         &mov(       $tmp1,          &DWP(&n2a($S*4),$trans,"",0));  # 2
  97         &xor(       $u,             $tmp1);
  98         &mov(       $tmp2,          &DWP(&n2a(($S+1)*4),$trans,"",0));      # 2
  99         &xor(       $u,             $R);
 100         &xor(       $t,             $R);
 101         &xor(       $t,             $tmp2);
 102 
 103         &and(       $u,             "0xfcfcfcfc"    );              # 2
 104         &xor(       $tmp1,          $tmp1);                         # 1
 105         &and(       $t,             "0xcfcfcfcf"    );              # 2
 106         &xor(       $tmp2,          $tmp2);
 107         &movb(      &LB($tmp1), &LB($u)     );
 108         &movb(      &LB($tmp2), &HB($u)     );
 109         &rotr(      $t,             4               );
 110         &mov(       $trans,         &swtmp(1));
 111         &xor(       $L,             &DWP("     ",$trans,$tmp1,0));
 112         &movb(      &LB($tmp1), &LB($t)     );
 113         &xor(       $L,             &DWP("0x200",$trans,$tmp2,0));
 114         &movb(      &LB($tmp2), &HB($t)     );
 115         &shr(       $u,             16);
 116         &xor(       $L,             &DWP("0x100",$trans,$tmp1,0));
 117         &movb(      &LB($tmp1), &HB($u)     );
 118         &shr(       $t,             16);
 119         &xor(       $L,             &DWP("0x300",$trans,$tmp2,0));
 120         &movb(      &LB($tmp2), &HB($t)     );
 121         &and(       $u,             "0xff"  );
 122         &and(       $t,             "0xff"  );
 123         &mov(       $tmp1,          &DWP("0x600",$trans,$tmp1,0));
 124         &xor(       $L,             $tmp1);
 125         &mov(       $tmp1,          &DWP("0x700",$trans,$tmp2,0));
 126         &xor(       $L,             $tmp1);
 127         &mov(       $tmp1,          &DWP("0x400",$trans,$u,0));
 128         &xor(       $L,             $tmp1);
 129         &mov(       $tmp1,          &DWP("0x500",$trans,$t,0));
 130         &xor(       $L,             $tmp1);
 131         &mov(       $trans,         &wparam(1));
 132         }
 133 
 134 sub n2a
 135         {
 136         sprintf("%d",$_[0]);
 137         }
 138 
 139 # now has a side affect of rotating $a by $shift
 140 sub R_PERM_OP
 141         {
 142         local($a,$b,$tt,$shift,$mask,$last)=@_;
 143 
 144         &rotl(      $a,             $shift          ) if ($shift != 0);
 145         &mov(       $tt,            $a              );
 146         &xor(       $a,             $b              );
 147         &and(       $a,             $mask           );
 148         if ($notlast eq $b)
 149                 {
 150                 &xor(       $b,             $a              );
 151                 &xor(       $tt,            $a              );
 152                 }
 153         else
 154                 {
 155                 &xor(       $tt,            $a              );
 156                 &xor(       $b,             $a              );
 157                 }
 158         &comment("");
 159         }
 160 
 161 sub IP_new
 162         {
 163         local($l,$r,$tt,$lr)=@_;
 164 
 165         &R_PERM_OP($l,$r,$tt, 4,"0xf0f0f0f0",$l);
 166         &R_PERM_OP($r,$tt,$l,20,"0xfff0000f",$l);
 167         &R_PERM_OP($l,$tt,$r,14,"0x33333333",$r);
 168         &R_PERM_OP($tt,$r,$l,22,"0x03fc03fc",$r);
 169         &R_PERM_OP($l,$r,$tt, 9,"0xaaaaaaaa",$r);
 170 
 171         if ($lr != 3)
 172                 {
 173                 if (($lr-3) < 0)
 174                         { &rotr($tt,        3-$lr); }
 175                 else    { &rotl($tt,        $lr-3); }
 176                 }
 177         if ($lr != 2)
 178                 {
 179                 if (($lr-2) < 0)
 180                         { &rotr($r, 2-$lr); }
 181                 else    { &rotl($r, $lr-2); }
 182                 }
 183         }
 184 
 185 sub FP_new
 186         {
 187         local($l,$r,$tt,$lr)=@_;
 188 
 189         if ($lr != 2)
 190                 {
 191                 if (($lr-2) < 0)
 192                         { &rotl($r, 2-$lr); }
 193                 else    { &rotr($r, $lr-2); }
 194                 }
 195         if ($lr != 3)
 196                 {
 197                 if (($lr-3) < 0)
 198                         { &rotl($l, 3-$lr); }
 199                 else    { &rotr($l, $lr-3); }
 200                 }
 201 
 202         &R_PERM_OP($l,$r,$tt, 0,"0xaaaaaaaa",$r);
 203         &R_PERM_OP($tt,$r,$l,23,"0x03fc03fc",$r);
 204         &R_PERM_OP($l,$r,$tt,10,"0x33333333",$l);
 205         &R_PERM_OP($r,$tt,$l,18,"0xfff0000f",$l);
 206         &R_PERM_OP($l,$tt,$r,12,"0xf0f0f0f0",$r);
 207         &rotr($tt   , 4);
 208         }