sub cbc
{
local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
&function_begin_B($name,"");
&comment("");
$in="esi";
$out="edi";
$count="ebp";
&push("ebp");
&push("ebx");
&push("esi");
&push("edi");
$data_off=4;
$data_off+=4 if ($p1 > 0);
$data_off+=4 if ($p2 > 0);
$data_off+=4 if ($p3 > 0);
&mov($count, &wparam(2));
&comment("getting iv ptr from parameter $iv_off");
&mov("ebx", &wparam($iv_off));
&mov($in, &DWP(0,"ebx","",0)); &mov($out, &DWP(4,"ebx","",0));
&push($out);
&push($in);
&push($out); &push($in);
&mov("ebx", "esp");
&mov($in, &wparam(0)); &mov($out, &wparam(1));
&comment("getting encrypt flag from parameter $enc_off");
&mov("ecx", &wparam($enc_off)); if ($p3 > 0)
{
&comment("get and push parameter $p3");
if ($enc_off != $p3)
{ &mov("eax", &wparam($p3)); &push("eax"); }
else { &push("ecx"); }
}
if ($p2 > 0)
{
&comment("get and push parameter $p2");
if ($enc_off != $p2)
{ &mov("eax", &wparam($p2)); &push("eax"); }
else { &push("ecx"); }
}
if ($p1 > 0)
{
&comment("get and push parameter $p1");
if ($enc_off != $p1)
{ &mov("eax", &wparam($p1)); &push("eax"); }
else { &push("ecx"); }
}
&push("ebx");
&cmp("ecx",0);
&jz(&label("decrypt"));
&and($count,0xfffffff8);
&mov("eax", &DWP($data_off,"esp","",0)); &mov("ebx", &DWP($data_off+4,"esp","",0));
&jz(&label("encrypt_finish"));
&set_label("encrypt_loop");
&mov("ecx", &DWP(0,$in,"",0)); &mov("edx", &DWP(4,$in,"",0));
&xor("eax", "ecx");
&xor("ebx", "edx");
&bswap("eax") if $swap;
&bswap("ebx") if $swap;
&mov(&DWP($data_off,"esp","",0), "eax"); &mov(&DWP($data_off+4,"esp","",0), "ebx");
&call($enc_func);
&mov("eax", &DWP($data_off,"esp","",0));
&mov("ebx", &DWP($data_off+4,"esp","",0));
&bswap("eax") if $swap;
&bswap("ebx") if $swap;
&mov(&DWP(0,$out,"",0),"eax");
&mov(&DWP(4,$out,"",0),"ebx");
&add($in, 8);
&add($out, 8);
&sub($count, 8);
&jnz(&label("encrypt_loop"));
&set_label("encrypt_finish");
&mov($count, &wparam(2)); &and($count, 7);
&jz(&label("finish"));
&call(&label("PIC_point"));
&set_label("PIC_point");
&blindpop("edx");
&lea("ecx",&DWP(&label("cbc_enc_jmp_table")."-".&label("PIC_point"),"edx"));
&mov($count,&DWP(0,"ecx",$count,4))
&add($count,"edx");
&xor("ecx","ecx");
&xor("edx","edx");
&jmp_ptr($count);
&set_label("ej7");
&movb(&HB("edx"), &BP(6,$in,"",0));
&shl("edx",8);
&set_label("ej6");
&movb(&HB("edx"), &BP(5,$in,"",0));
&set_label("ej5");
&movb(&LB("edx"), &BP(4,$in,"",0));
&set_label("ej4");
&mov("ecx", &DWP(0,$in,"",0));
&jmp(&label("ejend"));
&set_label("ej3");
&movb(&HB("ecx"), &BP(2,$in,"",0));
&shl("ecx",8);
&set_label("ej2");
&movb(&HB("ecx"), &BP(1,$in,"",0));
&set_label("ej1");
&movb(&LB("ecx"), &BP(0,$in,"",0));
&set_label("ejend");
&xor("eax", "ecx");
&xor("ebx", "edx");
&bswap("eax") if $swap;
&bswap("ebx") if $swap;
&mov(&DWP($data_off,"esp","",0), "eax"); &mov(&DWP($data_off+4,"esp","",0), "ebx");
&call($enc_func);
&mov("eax", &DWP($data_off,"esp","",0));
&mov("ebx", &DWP($data_off+4,"esp","",0));
&bswap("eax") if $swap;
&bswap("ebx") if $swap;
&mov(&DWP(0,$out,"",0),"eax");
&mov(&DWP(4,$out,"",0),"ebx");
&jmp(&label("finish"));
&set_label("decrypt",1);
&and($count,0xfffffff8);
&mov("eax", &DWP($data_off+8,"esp","",0)); &mov("ebx", &DWP($data_off+12,"esp","",0)); &jz(&label("decrypt_finish"));
&set_label("decrypt_loop");
&mov("eax", &DWP(0,$in,"",0)); &mov("ebx", &DWP(4,$in,"",0));
&bswap("eax") if $swap;
&bswap("ebx") if $swap;
&mov(&DWP($data_off,"esp","",0), "eax"); &mov(&DWP($data_off+4,"esp","",0), "ebx");
&call($dec_func);
&mov("eax", &DWP($data_off,"esp","",0)); &mov("ebx", &DWP($data_off+4,"esp","",0));
&bswap("eax") if $swap;
&bswap("ebx") if $swap;
&mov("ecx", &DWP($data_off+8,"esp","",0)); &mov("edx", &DWP($data_off+12,"esp","",0));
&xor("ecx", "eax");
&xor("edx", "ebx");
&mov("eax", &DWP(0,$in,"",0)); &mov("ebx", &DWP(4,$in,"",0));
&mov(&DWP(0,$out,"",0),"ecx");
&mov(&DWP(4,$out,"",0),"edx");
&mov(&DWP($data_off+8,"esp","",0), "eax"); &mov(&DWP($data_off+12,"esp","",0), "ebx");
&add($in, 8);
&add($out, 8);
&sub($count, 8);
&jnz(&label("decrypt_loop"));
&set_label("decrypt_finish");
&mov($count, &wparam(2)); &and($count, 7);
&jz(&label("finish"));
&mov("eax", &DWP(0,$in,"",0)); &mov("ebx", &DWP(4,$in,"",0));
&bswap("eax") if $swap;
&bswap("ebx") if $swap;
&mov(&DWP($data_off,"esp","",0), "eax"); &mov(&DWP($data_off+4,"esp","",0), "ebx");
&call($dec_func);
&mov("eax", &DWP($data_off,"esp","",0)); &mov("ebx", &DWP($data_off+4,"esp","",0));
&bswap("eax") if $swap;
&bswap("ebx") if $swap;
&mov("ecx", &DWP($data_off+8,"esp","",0)); &mov("edx", &DWP($data_off+12,"esp","",0));
&xor("ecx", "eax");
&xor("edx", "ebx");
&mov("eax", &DWP(0,$in,"",0)); &mov("ebx", &DWP(4,$in,"",0));
&set_label("dj7");
&rotr("edx", 16);
&movb(&BP(6,$out,"",0), &LB("edx"));
&shr("edx",16);
&set_label("dj6");
&movb(&BP(5,$out,"",0), &HB("edx"));
&set_label("dj5");
&movb(&BP(4,$out,"",0), &LB("edx"));
&set_label("dj4");
&mov(&DWP(0,$out,"",0), "ecx");
&jmp(&label("djend"));
&set_label("dj3");
&rotr("ecx", 16);
&movb(&BP(2,$out,"",0), &LB("ecx"));
&shl("ecx",16);
&set_label("dj2");
&movb(&BP(1,$in,"",0), &HB("ecx"));
&set_label("dj1");
&movb(&BP(0,$in,"",0), &LB("ecx"));
&set_label("djend");
&jmp(&label("finish"));
&set_label("finish",1);
&mov("ecx", &wparam($iv_off));
$total=16+4;
$total+=4 if ($p1 > 0);
$total+=4 if ($p2 > 0);
$total+=4 if ($p3 > 0);
&add("esp",$total);
&mov(&DWP(0,"ecx","",0), "eax"); &mov(&DWP(4,"ecx","",0), "ebx");
&function_end_A($name);
&align(64);
&set_label("cbc_enc_jmp_table");
&data_word("0");
&data_word(&label("ej1")."-".&label("PIC_point"));
&data_word(&label("ej2")."-".&label("PIC_point"));
&data_word(&label("ej3")."-".&label("PIC_point"));
&data_word(&label("ej4")."-".&label("PIC_point"));
&data_word(&label("ej5")."-".&label("PIC_point"));
&data_word(&label("ej6")."-".&label("PIC_point"));
&data_word(&label("ej7")."-".&label("PIC_point"));
&align(64);
&function_end_B($name);
}
1;