1913ec974Sbeck#!/usr/local/bin/perl 25b37fcf3Sryker 35b37fcf3Sryker# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc) 45b37fcf3Sryker# des_cblock (*input); 55b37fcf3Sryker# des_cblock (*output); 65b37fcf3Sryker# long length; 75b37fcf3Sryker# des_key_schedule schedule; 85b37fcf3Sryker# des_cblock (*ivec); 95b37fcf3Sryker# int enc; 105b37fcf3Sryker# 115b37fcf3Sryker# calls 125b37fcf3Sryker# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); 135b37fcf3Sryker# 145b37fcf3Sryker 155b37fcf3Sryker#&cbc("des_ncbc_encrypt","des_encrypt",0); 165b37fcf3Sryker#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt", 175b37fcf3Sryker# 1,4,5,3,5,-1); 185b37fcf3Sryker#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt", 195b37fcf3Sryker# 0,4,5,3,5,-1); 205b37fcf3Sryker#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3", 215b37fcf3Sryker# 0,6,7,3,4,5); 225b37fcf3Sryker# 235b37fcf3Sryker# When doing a cipher that needs bigendian order, 245b37fcf3Sryker# for encrypt, the iv is kept in bigendian form, 255b37fcf3Sryker# while for decrypt, it is kept in little endian. 265b37fcf3Srykersub cbc 275b37fcf3Sryker { 285b37fcf3Sryker local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_; 295b37fcf3Sryker # name is the function name 305b37fcf3Sryker # enc_func and dec_func and the functions to call for encrypt/decrypt 315b37fcf3Sryker # swap is true if byte order needs to be reversed 325b37fcf3Sryker # iv_off is parameter number for the iv 335b37fcf3Sryker # enc_off is parameter number for the encrypt/decrypt flag 345b37fcf3Sryker # p1,p2,p3 are the offsets for parameters to be passed to the 355b37fcf3Sryker # underlying calls. 365b37fcf3Sryker 37*0bd8ca4aSmiod&static_label("cbc_enc_jmp_table_".$name); 38*0bd8ca4aSmiod&static_label("ej1_".$name); 39*0bd8ca4aSmiod&static_label("ej2_".$name); 40*0bd8ca4aSmiod&static_label("ej3_".$name); 41*0bd8ca4aSmiod&static_label("ej4_".$name); 42*0bd8ca4aSmiod&static_label("ej5_".$name); 43*0bd8ca4aSmiod&static_label("ej6_".$name); 44*0bd8ca4aSmiod&static_label("ej7_".$name); 45*0bd8ca4aSmiod 465b37fcf3Sryker &function_begin_B($name,""); 475b37fcf3Sryker &comment(""); 485b37fcf3Sryker 495b37fcf3Sryker $in="esi"; 505b37fcf3Sryker $out="edi"; 515b37fcf3Sryker $count="ebp"; 525b37fcf3Sryker 535b37fcf3Sryker &push("ebp"); 545b37fcf3Sryker &push("ebx"); 555b37fcf3Sryker &push("esi"); 565b37fcf3Sryker &push("edi"); 575b37fcf3Sryker 585b37fcf3Sryker $data_off=4; 595b37fcf3Sryker $data_off+=4 if ($p1 > 0); 605b37fcf3Sryker $data_off+=4 if ($p2 > 0); 615b37fcf3Sryker $data_off+=4 if ($p3 > 0); 625b37fcf3Sryker 635b37fcf3Sryker &mov($count, &wparam(2)); # length 645b37fcf3Sryker 655b37fcf3Sryker &comment("getting iv ptr from parameter $iv_off"); 665b37fcf3Sryker &mov("ebx", &wparam($iv_off)); # Get iv ptr 675b37fcf3Sryker 685b37fcf3Sryker &mov($in, &DWP(0,"ebx","",0));# iv[0] 695b37fcf3Sryker &mov($out, &DWP(4,"ebx","",0));# iv[1] 705b37fcf3Sryker 715b37fcf3Sryker &push($out); 725b37fcf3Sryker &push($in); 735b37fcf3Sryker &push($out); # used in decrypt for iv[1] 745b37fcf3Sryker &push($in); # used in decrypt for iv[0] 755b37fcf3Sryker 765b37fcf3Sryker &mov("ebx", "esp"); # This is the address of tin[2] 775b37fcf3Sryker 785b37fcf3Sryker &mov($in, &wparam(0)); # in 795b37fcf3Sryker &mov($out, &wparam(1)); # out 805b37fcf3Sryker 815b37fcf3Sryker # We have loaded them all, how lets push things 825b37fcf3Sryker &comment("getting encrypt flag from parameter $enc_off"); 835b37fcf3Sryker &mov("ecx", &wparam($enc_off)); # Get enc flag 845b37fcf3Sryker if ($p3 > 0) 855b37fcf3Sryker { 865b37fcf3Sryker &comment("get and push parameter $p3"); 875b37fcf3Sryker if ($enc_off != $p3) 885b37fcf3Sryker { &mov("eax", &wparam($p3)); &push("eax"); } 895b37fcf3Sryker else { &push("ecx"); } 905b37fcf3Sryker } 915b37fcf3Sryker if ($p2 > 0) 925b37fcf3Sryker { 935b37fcf3Sryker &comment("get and push parameter $p2"); 945b37fcf3Sryker if ($enc_off != $p2) 955b37fcf3Sryker { &mov("eax", &wparam($p2)); &push("eax"); } 965b37fcf3Sryker else { &push("ecx"); } 975b37fcf3Sryker } 985b37fcf3Sryker if ($p1 > 0) 995b37fcf3Sryker { 1005b37fcf3Sryker &comment("get and push parameter $p1"); 1015b37fcf3Sryker if ($enc_off != $p1) 1025b37fcf3Sryker { &mov("eax", &wparam($p1)); &push("eax"); } 1035b37fcf3Sryker else { &push("ecx"); } 1045b37fcf3Sryker } 1055b37fcf3Sryker &push("ebx"); # push data/iv 1065b37fcf3Sryker 1075b37fcf3Sryker &cmp("ecx",0); 1085b37fcf3Sryker &jz(&label("decrypt")); 1095b37fcf3Sryker 1105b37fcf3Sryker &and($count,0xfffffff8); 1115b37fcf3Sryker &mov("eax", &DWP($data_off,"esp","",0)); # load iv[0] 1125b37fcf3Sryker &mov("ebx", &DWP($data_off+4,"esp","",0)); # load iv[1] 1135b37fcf3Sryker 1145b37fcf3Sryker &jz(&label("encrypt_finish")); 1155b37fcf3Sryker 1165b37fcf3Sryker ############################################################# 1175b37fcf3Sryker 1185b37fcf3Sryker &set_label("encrypt_loop"); 1195b37fcf3Sryker # encrypt start 1205b37fcf3Sryker # "eax" and "ebx" hold iv (or the last cipher text) 1215b37fcf3Sryker 1225b37fcf3Sryker &mov("ecx", &DWP(0,$in,"",0)); # load first 4 bytes 1235b37fcf3Sryker &mov("edx", &DWP(4,$in,"",0)); # second 4 bytes 1245b37fcf3Sryker 1255b37fcf3Sryker &xor("eax", "ecx"); 1265b37fcf3Sryker &xor("ebx", "edx"); 1275b37fcf3Sryker 1285b37fcf3Sryker &bswap("eax") if $swap; 1295b37fcf3Sryker &bswap("ebx") if $swap; 1305b37fcf3Sryker 1315b37fcf3Sryker &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call 1325b37fcf3Sryker &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 1335b37fcf3Sryker 1345b37fcf3Sryker &call($enc_func); 1355b37fcf3Sryker 1365b37fcf3Sryker &mov("eax", &DWP($data_off,"esp","",0)); 1375b37fcf3Sryker &mov("ebx", &DWP($data_off+4,"esp","",0)); 1385b37fcf3Sryker 1395b37fcf3Sryker &bswap("eax") if $swap; 1405b37fcf3Sryker &bswap("ebx") if $swap; 1415b37fcf3Sryker 1425b37fcf3Sryker &mov(&DWP(0,$out,"",0),"eax"); 1435b37fcf3Sryker &mov(&DWP(4,$out,"",0),"ebx"); 1445b37fcf3Sryker 1455b37fcf3Sryker # eax and ebx are the next iv. 1465b37fcf3Sryker 1475b37fcf3Sryker &add($in, 8); 1485b37fcf3Sryker &add($out, 8); 1495b37fcf3Sryker 1505b37fcf3Sryker &sub($count, 8); 1515b37fcf3Sryker &jnz(&label("encrypt_loop")); 1525b37fcf3Sryker 1535b37fcf3Sryker###################################################################3 1545b37fcf3Sryker &set_label("encrypt_finish"); 1555b37fcf3Sryker &mov($count, &wparam(2)); # length 1565b37fcf3Sryker &and($count, 7); 1575b37fcf3Sryker &jz(&label("finish")); 158*0bd8ca4aSmiod 159*0bd8ca4aSmiod &picsetup("edx"); 160*0bd8ca4aSmiod &picsymbol("ecx", &label("cbc_enc_jmp_table_".$name), "edx") 16197222eddSmiod &mov($count,&DWP(0,"ecx",$count,4)); 162*0bd8ca4aSmiod &picadjust($count, "edx"); 163*0bd8ca4aSmiod 1645b37fcf3Sryker &xor("ecx","ecx"); 1655b37fcf3Sryker &xor("edx","edx"); 1665b37fcf3Sryker &jmp_ptr($count); 1675b37fcf3Sryker 168*0bd8ca4aSmiod&set_label("ej7_".$name); 1695b37fcf3Sryker &movb(&HB("edx"), &BP(6,$in,"",0)); 1705b37fcf3Sryker &shl("edx",8); 171*0bd8ca4aSmiod&set_label("ej6_".$name); 1725b37fcf3Sryker &movb(&HB("edx"), &BP(5,$in,"",0)); 173*0bd8ca4aSmiod&set_label("ej5_".$name); 1745b37fcf3Sryker &movb(&LB("edx"), &BP(4,$in,"",0)); 175*0bd8ca4aSmiod&set_label("ej4_".$name); 1765b37fcf3Sryker &mov("ecx", &DWP(0,$in,"",0)); 1775b37fcf3Sryker &jmp(&label("ejend")); 178*0bd8ca4aSmiod&set_label("ej3_".$name); 1795b37fcf3Sryker &movb(&HB("ecx"), &BP(2,$in,"",0)); 1805b37fcf3Sryker &shl("ecx",8); 181*0bd8ca4aSmiod&set_label("ej2_".$name); 1825b37fcf3Sryker &movb(&HB("ecx"), &BP(1,$in,"",0)); 183*0bd8ca4aSmiod&set_label("ej1_".$name); 1845b37fcf3Sryker &movb(&LB("ecx"), &BP(0,$in,"",0)); 1855b37fcf3Sryker&set_label("ejend"); 1865b37fcf3Sryker 1875b37fcf3Sryker &xor("eax", "ecx"); 1885b37fcf3Sryker &xor("ebx", "edx"); 1895b37fcf3Sryker 1905b37fcf3Sryker &bswap("eax") if $swap; 1915b37fcf3Sryker &bswap("ebx") if $swap; 1925b37fcf3Sryker 1935b37fcf3Sryker &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call 1945b37fcf3Sryker &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 1955b37fcf3Sryker 1965b37fcf3Sryker &call($enc_func); 1975b37fcf3Sryker 1985b37fcf3Sryker &mov("eax", &DWP($data_off,"esp","",0)); 1995b37fcf3Sryker &mov("ebx", &DWP($data_off+4,"esp","",0)); 2005b37fcf3Sryker 2015b37fcf3Sryker &bswap("eax") if $swap; 2025b37fcf3Sryker &bswap("ebx") if $swap; 2035b37fcf3Sryker 2045b37fcf3Sryker &mov(&DWP(0,$out,"",0),"eax"); 2055b37fcf3Sryker &mov(&DWP(4,$out,"",0),"ebx"); 2065b37fcf3Sryker 2075b37fcf3Sryker &jmp(&label("finish")); 2085b37fcf3Sryker 2095b37fcf3Sryker ############################################################# 2105b37fcf3Sryker ############################################################# 2115b37fcf3Sryker &set_label("decrypt",1); 2125b37fcf3Sryker # decrypt start 2135b37fcf3Sryker &and($count,0xfffffff8); 2145b37fcf3Sryker # The next 2 instructions are only for if the jz is taken 2155b37fcf3Sryker &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0] 2165b37fcf3Sryker &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1] 2175b37fcf3Sryker &jz(&label("decrypt_finish")); 2185b37fcf3Sryker 2195b37fcf3Sryker &set_label("decrypt_loop"); 2205b37fcf3Sryker &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes 2215b37fcf3Sryker &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes 2225b37fcf3Sryker 2235b37fcf3Sryker &bswap("eax") if $swap; 2245b37fcf3Sryker &bswap("ebx") if $swap; 2255b37fcf3Sryker 2265b37fcf3Sryker &mov(&DWP($data_off,"esp","",0), "eax"); # put back 2275b37fcf3Sryker &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 2285b37fcf3Sryker 2295b37fcf3Sryker &call($dec_func); 2305b37fcf3Sryker 2315b37fcf3Sryker &mov("eax", &DWP($data_off,"esp","",0)); # get return 2325b37fcf3Sryker &mov("ebx", &DWP($data_off+4,"esp","",0)); # 2335b37fcf3Sryker 2345b37fcf3Sryker &bswap("eax") if $swap; 2355b37fcf3Sryker &bswap("ebx") if $swap; 2365b37fcf3Sryker 2375b37fcf3Sryker &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] 2385b37fcf3Sryker &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] 2395b37fcf3Sryker 2405b37fcf3Sryker &xor("ecx", "eax"); 2415b37fcf3Sryker &xor("edx", "ebx"); 2425b37fcf3Sryker 2435b37fcf3Sryker &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, 2445b37fcf3Sryker &mov("ebx", &DWP(4,$in,"",0)); # next iv actually 2455b37fcf3Sryker 2465b37fcf3Sryker &mov(&DWP(0,$out,"",0),"ecx"); 2475b37fcf3Sryker &mov(&DWP(4,$out,"",0),"edx"); 2485b37fcf3Sryker 2495b37fcf3Sryker &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv 2505b37fcf3Sryker &mov(&DWP($data_off+12,"esp","",0), "ebx"); # 2515b37fcf3Sryker 2525b37fcf3Sryker &add($in, 8); 2535b37fcf3Sryker &add($out, 8); 2545b37fcf3Sryker 2555b37fcf3Sryker &sub($count, 8); 2565b37fcf3Sryker &jnz(&label("decrypt_loop")); 2575b37fcf3Sryker############################ ENDIT #######################3 2585b37fcf3Sryker &set_label("decrypt_finish"); 2595b37fcf3Sryker &mov($count, &wparam(2)); # length 2605b37fcf3Sryker &and($count, 7); 2615b37fcf3Sryker &jz(&label("finish")); 2625b37fcf3Sryker 2635b37fcf3Sryker &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes 2645b37fcf3Sryker &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes 2655b37fcf3Sryker 2665b37fcf3Sryker &bswap("eax") if $swap; 2675b37fcf3Sryker &bswap("ebx") if $swap; 2685b37fcf3Sryker 2695b37fcf3Sryker &mov(&DWP($data_off,"esp","",0), "eax"); # put back 2705b37fcf3Sryker &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 2715b37fcf3Sryker 2725b37fcf3Sryker &call($dec_func); 2735b37fcf3Sryker 2745b37fcf3Sryker &mov("eax", &DWP($data_off,"esp","",0)); # get return 2755b37fcf3Sryker &mov("ebx", &DWP($data_off+4,"esp","",0)); # 2765b37fcf3Sryker 2775b37fcf3Sryker &bswap("eax") if $swap; 2785b37fcf3Sryker &bswap("ebx") if $swap; 2795b37fcf3Sryker 2805b37fcf3Sryker &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] 2815b37fcf3Sryker &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] 2825b37fcf3Sryker 2835b37fcf3Sryker &xor("ecx", "eax"); 2845b37fcf3Sryker &xor("edx", "ebx"); 2855b37fcf3Sryker 2865b37fcf3Sryker # this is for when we exit 2875b37fcf3Sryker &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, 2885b37fcf3Sryker &mov("ebx", &DWP(4,$in,"",0)); # next iv actually 2895b37fcf3Sryker 2905b37fcf3Sryker &rotr("edx", 16); 2915b37fcf3Sryker &movb(&BP(6,$out,"",0), &LB("edx")); 2925b37fcf3Sryker &shr("edx",16); 2935b37fcf3Sryker &movb(&BP(5,$out,"",0), &HB("edx")); 2945b37fcf3Sryker &movb(&BP(4,$out,"",0), &LB("edx")); 2955b37fcf3Sryker &mov(&DWP(0,$out,"",0), "ecx"); 2965b37fcf3Sryker 2975b37fcf3Sryker # final iv is still in eax:ebx 2985b37fcf3Sryker 2995b37fcf3Sryker############################ FINISH #######################3 3005b37fcf3Sryker &set_label("finish",1); 3015b37fcf3Sryker &mov("ecx", &wparam($iv_off)); # Get iv ptr 3025b37fcf3Sryker 3035b37fcf3Sryker ################################################# 3045b37fcf3Sryker $total=16+4; 3055b37fcf3Sryker $total+=4 if ($p1 > 0); 3065b37fcf3Sryker $total+=4 if ($p2 > 0); 3075b37fcf3Sryker $total+=4 if ($p3 > 0); 3085b37fcf3Sryker &add("esp",$total); 3095b37fcf3Sryker 3105b37fcf3Sryker &mov(&DWP(0,"ecx","",0), "eax"); # save iv 3115b37fcf3Sryker &mov(&DWP(4,"ecx","",0), "ebx"); # save iv 3125b37fcf3Sryker 3135b37fcf3Sryker &function_end_A($name); 3145b37fcf3Sryker &function_end_B($name); 3155b37fcf3Sryker 316*0bd8ca4aSmiod &rodataseg(); 317*0bd8ca4aSmiod &align(64); 318*0bd8ca4aSmiod &set_label("cbc_enc_jmp_table_".$name); 319*0bd8ca4aSmiod &data_word("0"); 320*0bd8ca4aSmiod &data_word(&code_sym(&label("ej1_".$name))); 321*0bd8ca4aSmiod &data_word(&code_sym(&label("ej2_".$name))); 322*0bd8ca4aSmiod &data_word(&code_sym(&label("ej3_".$name))); 323*0bd8ca4aSmiod &data_word(&code_sym(&label("ej4_".$name))); 324*0bd8ca4aSmiod &data_word(&code_sym(&label("ej5_".$name))); 325*0bd8ca4aSmiod &data_word(&code_sym(&label("ej6_".$name))); 326*0bd8ca4aSmiod &data_word(&code_sym(&label("ej7_".$name))); 327*0bd8ca4aSmiod &previous(); 328*0bd8ca4aSmiod 3295b37fcf3Sryker } 3305b37fcf3Sryker 3315b37fcf3Sryker1; 332