1 #!/usr/local/bin/perl
   2 
   3 # void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
   4 # des_cblock (*input);
   5 # des_cblock (*output);
   6 # long length;
   7 # des_key_schedule schedule;
   8 # des_cblock (*ivec);
   9 # int enc;
  10 #
  11 # calls
  12 # des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
  13 #
  14 
  15 #&cbc("des_ncbc_encrypt","des_encrypt",0);
  16 #&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",
  17 #       1,4,5,3,5,-1);
  18 #&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",
  19 #       0,4,5,3,5,-1);
  20 #&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",
  21 #       0,6,7,3,4,5);
  22 #
  23 # When doing a cipher that needs bigendian order,
  24 # for encrypt, the iv is kept in bigendian form,
  25 # while for decrypt, it is kept in little endian.
  26 sub cbc
  27         {
  28         local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
  29         # name is the function name
  30         # enc_func and dec_func and the functions to call for encrypt/decrypt
  31         # swap is true if byte order needs to be reversed
  32         # iv_off is parameter number for the iv
  33         # enc_off is parameter number for the encrypt/decrypt flag
  34         # p1,p2,p3 are the offsets for parameters to be passed to the
  35         # underlying calls.
  36 
  37         &function_begin_B($name,"");
  38         &comment("");
  39 
  40         $in="esi";
  41         $out="edi";
  42         $count="ebp";
  43 
  44         &push("ebp");
  45         &push("ebx");
  46         &push("esi");
  47         &push("edi");
  48 
  49         $data_off=4;
  50         $data_off+=4 if ($p1 > 0);
  51         $data_off+=4 if ($p2 > 0);
  52         $data_off+=4 if ($p3 > 0);
  53 
  54         &mov($count,        &wparam(2));        # length
  55 
  56         &comment("getting iv ptr from parameter $iv_off");
  57         &mov("ebx", &wparam($iv_off));  # Get iv ptr
  58 
  59         &mov($in,   &DWP(0,"ebx","",0));#       iv[0]
  60         &mov($out,  &DWP(4,"ebx","",0));#       iv[1]
  61 
  62         &push($out);
  63         &push($in);
  64         &push($out);        # used in decrypt for iv[1]
  65         &push($in); # used in decrypt for iv[0]
  66 
  67         &mov("ebx", "esp");         # This is the address of tin[2]
  68 
  69         &mov($in,   &wparam(0));        # in
  70         &mov($out,  &wparam(1));        # out
  71 
  72         # We have loaded them all, how lets push things
  73         &comment("getting encrypt flag from parameter $enc_off");
  74         &mov("ecx", &wparam($enc_off)); # Get enc flag
  75         if ($p3 > 0)
  76                 {
  77                 &comment("get and push parameter $p3");
  78                 if ($enc_off != $p3)
  79                         { &mov("eax",       &wparam($p3)); &push("eax"); }
  80                 else    { &push("ecx"); }
  81                 }
  82         if ($p2 > 0)
  83                 {
  84                 &comment("get and push parameter $p2");
  85                 if ($enc_off != $p2)
  86                         { &mov("eax",       &wparam($p2)); &push("eax"); }
  87                 else    { &push("ecx"); }
  88                 }
  89         if ($p1 > 0)
  90                 {
  91                 &comment("get and push parameter $p1");
  92                 if ($enc_off != $p1)
  93                         { &mov("eax",       &wparam($p1)); &push("eax"); }
  94                 else    { &push("ecx"); }
  95                 }
  96         &push("ebx");               # push data/iv
  97 
  98         &cmp("ecx",0);
  99         &jz(&label("decrypt"));
 100 
 101         &and($count,0xfffffff8);
 102         &mov("eax", &DWP($data_off,"esp","",0));        # load iv[0]
 103         &mov("ebx", &DWP($data_off+4,"esp","",0));      # load iv[1]
 104 
 105         &jz(&label("encrypt_finish"));
 106 
 107         #############################################################
 108 
 109         &set_label("encrypt_loop");
 110         # encrypt start
 111         # "eax" and "ebx" hold iv (or the last cipher text)
 112 
 113         &mov("ecx", &DWP(0,$in,"",0));  # load first 4 bytes
 114         &mov("edx", &DWP(4,$in,"",0));  # second 4 bytes
 115 
 116         &xor("eax", "ecx");
 117         &xor("ebx", "edx");
 118 
 119         &bswap("eax")       if $swap;
 120         &bswap("ebx")       if $swap;
 121 
 122         &mov(&DWP($data_off,"esp","",0),        "eax"); # put in array for call
 123         &mov(&DWP($data_off+4,"esp","",0),      "ebx"); #
 124 
 125         &call($enc_func);
 126 
 127         &mov("eax", &DWP($data_off,"esp","",0));
 128         &mov("ebx", &DWP($data_off+4,"esp","",0));
 129 
 130         &bswap("eax")       if $swap;
 131         &bswap("ebx")       if $swap;
 132 
 133         &mov(&DWP(0,$out,"",0),"eax");
 134         &mov(&DWP(4,$out,"",0),"ebx");
 135 
 136         # eax and ebx are the next iv.
 137 
 138         &add($in,   8);
 139         &add($out,  8);
 140 
 141         &sub($count,        8);
 142         &jnz(&label("encrypt_loop"));
 143 
 144 ###################################################################3
 145         &set_label("encrypt_finish");
 146         &mov($count,        &wparam(2));        # length
 147         &and($count,        7);
 148         &jz(&label("finish"));
 149         &call(&label("PIC_point"));
 150 &set_label("PIC_point");
 151         &blindpop("edx");
 152         &lea("ecx",&DWP(&label("cbc_enc_jmp_table")."-".&label("PIC_point"),"edx"));
 153         &mov($count,&DWP(0,"ecx",$count,4));
 154         &add($count,"edx");
 155         &xor("ecx","ecx");
 156         &xor("edx","edx");
 157         #&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4));
 158         &jmp_ptr($count);
 159 
 160 &set_label("ej7");
 161         &movb(&HB("edx"),       &BP(6,$in,"",0));
 162         &shl("edx",8);
 163 &set_label("ej6");
 164         &movb(&HB("edx"),       &BP(5,$in,"",0));
 165 &set_label("ej5");
 166         &movb(&LB("edx"),       &BP(4,$in,"",0));
 167 &set_label("ej4");
 168         &mov("ecx",         &DWP(0,$in,"",0));
 169         &jmp(&label("ejend"));
 170 &set_label("ej3");
 171         &movb(&HB("ecx"),       &BP(2,$in,"",0));
 172         &shl("ecx",8);
 173 &set_label("ej2");
 174         &movb(&HB("ecx"),       &BP(1,$in,"",0));
 175 &set_label("ej1");
 176         &movb(&LB("ecx"),       &BP(0,$in,"",0));
 177 &set_label("ejend");
 178 
 179         &xor("eax", "ecx");
 180         &xor("ebx", "edx");
 181 
 182         &bswap("eax")       if $swap;
 183         &bswap("ebx")       if $swap;
 184 
 185         &mov(&DWP($data_off,"esp","",0),        "eax"); # put in array for call
 186         &mov(&DWP($data_off+4,"esp","",0),      "ebx"); #
 187 
 188         &call($enc_func);
 189 
 190         &mov("eax", &DWP($data_off,"esp","",0));
 191         &mov("ebx", &DWP($data_off+4,"esp","",0));
 192 
 193         &bswap("eax")       if $swap;
 194         &bswap("ebx")       if $swap;
 195 
 196         &mov(&DWP(0,$out,"",0),"eax");
 197         &mov(&DWP(4,$out,"",0),"ebx");
 198 
 199         &jmp(&label("finish"));
 200 
 201         #############################################################
 202         #############################################################
 203         &set_label("decrypt",1);
 204         # decrypt start
 205         &and($count,0xfffffff8);
 206         # The next 2 instructions are only for if the jz is taken
 207         &mov("eax", &DWP($data_off+8,"esp","",0));      # get iv[0]
 208         &mov("ebx", &DWP($data_off+12,"esp","",0));     # get iv[1]
 209         &jz(&label("decrypt_finish"));
 210 
 211         &set_label("decrypt_loop");
 212         &mov("eax", &DWP(0,$in,"",0));  # load first 4 bytes
 213         &mov("ebx", &DWP(4,$in,"",0));  # second 4 bytes
 214 
 215         &bswap("eax")       if $swap;
 216         &bswap("ebx")       if $swap;
 217 
 218         &mov(&DWP($data_off,"esp","",0),        "eax"); # put back
 219         &mov(&DWP($data_off+4,"esp","",0),      "ebx"); #
 220 
 221         &call($dec_func);
 222 
 223         &mov("eax", &DWP($data_off,"esp","",0));        # get return
 224         &mov("ebx", &DWP($data_off+4,"esp","",0));      #
 225 
 226         &bswap("eax")       if $swap;
 227         &bswap("ebx")       if $swap;
 228 
 229         &mov("ecx", &DWP($data_off+8,"esp","",0));      # get iv[0]
 230         &mov("edx", &DWP($data_off+12,"esp","",0));     # get iv[1]
 231 
 232         &xor("ecx", "eax");
 233         &xor("edx", "ebx");
 234 
 235         &mov("eax", &DWP(0,$in,"",0));  # get old cipher text,
 236         &mov("ebx", &DWP(4,$in,"",0));  # next iv actually
 237 
 238         &mov(&DWP(0,$out,"",0),"ecx");
 239         &mov(&DWP(4,$out,"",0),"edx");
 240 
 241         &mov(&DWP($data_off+8,"esp","",0),      "eax"); # save iv
 242         &mov(&DWP($data_off+12,"esp","",0),     "ebx"); #
 243 
 244         &add($in,   8);
 245         &add($out,  8);
 246 
 247         &sub($count,        8);
 248         &jnz(&label("decrypt_loop"));
 249 ############################ ENDIT #######################3
 250         &set_label("decrypt_finish");
 251         &mov($count,        &wparam(2));        # length
 252         &and($count,        7);
 253         &jz(&label("finish"));
 254 
 255         &mov("eax", &DWP(0,$in,"",0));  # load first 4 bytes
 256         &mov("ebx", &DWP(4,$in,"",0));  # second 4 bytes
 257 
 258         &bswap("eax")       if $swap;
 259         &bswap("ebx")       if $swap;
 260 
 261         &mov(&DWP($data_off,"esp","",0),        "eax"); # put back
 262         &mov(&DWP($data_off+4,"esp","",0),      "ebx"); #
 263 
 264         &call($dec_func);
 265 
 266         &mov("eax", &DWP($data_off,"esp","",0));        # get return
 267         &mov("ebx", &DWP($data_off+4,"esp","",0));      #
 268 
 269         &bswap("eax")       if $swap;
 270         &bswap("ebx")       if $swap;
 271 
 272         &mov("ecx", &DWP($data_off+8,"esp","",0));      # get iv[0]
 273         &mov("edx", &DWP($data_off+12,"esp","",0));     # get iv[1]
 274 
 275         &xor("ecx", "eax");
 276         &xor("edx", "ebx");
 277 
 278         # this is for when we exit
 279         &mov("eax", &DWP(0,$in,"",0));  # get old cipher text,
 280         &mov("ebx", &DWP(4,$in,"",0));  # next iv actually
 281 
 282 &set_label("dj7");
 283         &rotr("edx",        16);
 284         &movb(&BP(6,$out,"",0), &LB("edx"));
 285         &shr("edx",16);
 286 &set_label("dj6");
 287         &movb(&BP(5,$out,"",0), &HB("edx"));
 288 &set_label("dj5");
 289         &movb(&BP(4,$out,"",0), &LB("edx"));
 290 &set_label("dj4");
 291         &mov(&DWP(0,$out,"",0), "ecx");
 292         &jmp(&label("djend"));
 293 &set_label("dj3");
 294         &rotr("ecx",        16);
 295         &movb(&BP(2,$out,"",0), &LB("ecx"));
 296         &shl("ecx",16);
 297 &set_label("dj2");
 298         &movb(&BP(1,$in,"",0),  &HB("ecx"));
 299 &set_label("dj1");
 300         &movb(&BP(0,$in,"",0),  &LB("ecx"));
 301 &set_label("djend");
 302 
 303         # final iv is still in eax:ebx
 304         &jmp(&label("finish"));
 305 
 306 
 307 ############################ FINISH #######################3
 308         &set_label("finish",1);
 309         &mov("ecx", &wparam($iv_off));  # Get iv ptr
 310 
 311         #################################################
 312         $total=16+4;
 313         $total+=4 if ($p1 > 0);
 314         $total+=4 if ($p2 > 0);
 315         $total+=4 if ($p3 > 0);
 316         &add("esp",$total);
 317 
 318         &mov(&DWP(0,"ecx","",0),        "eax"); # save iv
 319         &mov(&DWP(4,"ecx","",0),        "ebx"); # save iv
 320 
 321         &function_end_A($name);
 322 
 323         &align(64);
 324         &set_label("cbc_enc_jmp_table");
 325         &data_word("0");
 326         &data_word(&label("ej1")."-".&label("PIC_point"));
 327         &data_word(&label("ej2")."-".&label("PIC_point"));
 328         &data_word(&label("ej3")."-".&label("PIC_point"));
 329         &data_word(&label("ej4")."-".&label("PIC_point"));
 330         &data_word(&label("ej5")."-".&label("PIC_point"));
 331         &data_word(&label("ej6")."-".&label("PIC_point"));
 332         &data_word(&label("ej7")."-".&label("PIC_point"));
 333         # not used
 334         #&set_label("cbc_dec_jmp_table",1);
 335         #&data_word("0");
 336         #&data_word(&label("dj1")."-".&label("PIC_point"));
 337         #&data_word(&label("dj2")."-".&label("PIC_point"));
 338         #&data_word(&label("dj3")."-".&label("PIC_point"));
 339         #&data_word(&label("dj4")."-".&label("PIC_point"));
 340         #&data_word(&label("dj5")."-".&label("PIC_point"));
 341         #&data_word(&label("dj6")."-".&label("PIC_point"));
 342         #&data_word(&label("dj7")."-".&label("PIC_point"));
 343         &align(64);
 344 
 345         &function_end_B($name);
 346 
 347         }
 348 
 349 1;