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. 26sub 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&static_label("cbc_enc_jmp_table_".$name); 38&static_label("ej1_".$name); 39&static_label("ej2_".$name); 40&static_label("ej3_".$name); 41&static_label("ej4_".$name); 42&static_label("ej5_".$name); 43&static_label("ej6_".$name); 44&static_label("ej7_".$name); 45 46 &function_begin_B($name,""); 47 &comment(""); 48 49 $in="esi"; 50 $out="edi"; 51 $count="ebp"; 52 53 &push("ebp"); 54 &push("ebx"); 55 &push("esi"); 56 &push("edi"); 57 58 $data_off=4; 59 $data_off+=4 if ($p1 > 0); 60 $data_off+=4 if ($p2 > 0); 61 $data_off+=4 if ($p3 > 0); 62 63 &mov($count, &wparam(2)); # length 64 65 &comment("getting iv ptr from parameter $iv_off"); 66 &mov("ebx", &wparam($iv_off)); # Get iv ptr 67 68 &mov($in, &DWP(0,"ebx","",0));# iv[0] 69 &mov($out, &DWP(4,"ebx","",0));# iv[1] 70 71 &push($out); 72 &push($in); 73 &push($out); # used in decrypt for iv[1] 74 &push($in); # used in decrypt for iv[0] 75 76 &mov("ebx", "esp"); # This is the address of tin[2] 77 78 &mov($in, &wparam(0)); # in 79 &mov($out, &wparam(1)); # out 80 81 # We have loaded them all, how lets push things 82 &comment("getting encrypt flag from parameter $enc_off"); 83 &mov("ecx", &wparam($enc_off)); # Get enc flag 84 if ($p3 > 0) 85 { 86 &comment("get and push parameter $p3"); 87 if ($enc_off != $p3) 88 { &mov("eax", &wparam($p3)); &push("eax"); } 89 else { &push("ecx"); } 90 } 91 if ($p2 > 0) 92 { 93 &comment("get and push parameter $p2"); 94 if ($enc_off != $p2) 95 { &mov("eax", &wparam($p2)); &push("eax"); } 96 else { &push("ecx"); } 97 } 98 if ($p1 > 0) 99 { 100 &comment("get and push parameter $p1"); 101 if ($enc_off != $p1) 102 { &mov("eax", &wparam($p1)); &push("eax"); } 103 else { &push("ecx"); } 104 } 105 &push("ebx"); # push data/iv 106 107 &cmp("ecx",0); 108 &jz(&label("decrypt")); 109 110 &and($count,0xfffffff8); 111 &mov("eax", &DWP($data_off,"esp","",0)); # load iv[0] 112 &mov("ebx", &DWP($data_off+4,"esp","",0)); # load iv[1] 113 114 &jz(&label("encrypt_finish")); 115 116 ############################################################# 117 118 &set_label("encrypt_loop"); 119 # encrypt start 120 # "eax" and "ebx" hold iv (or the last cipher text) 121 122 &mov("ecx", &DWP(0,$in,"",0)); # load first 4 bytes 123 &mov("edx", &DWP(4,$in,"",0)); # second 4 bytes 124 125 &xor("eax", "ecx"); 126 &xor("ebx", "edx"); 127 128 &bswap("eax") if $swap; 129 &bswap("ebx") if $swap; 130 131 &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call 132 &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 133 134 &call($enc_func); 135 136 &mov("eax", &DWP($data_off,"esp","",0)); 137 &mov("ebx", &DWP($data_off+4,"esp","",0)); 138 139 &bswap("eax") if $swap; 140 &bswap("ebx") if $swap; 141 142 &mov(&DWP(0,$out,"",0),"eax"); 143 &mov(&DWP(4,$out,"",0),"ebx"); 144 145 # eax and ebx are the next iv. 146 147 &add($in, 8); 148 &add($out, 8); 149 150 &sub($count, 8); 151 &jnz(&label("encrypt_loop")); 152 153###################################################################3 154 &set_label("encrypt_finish"); 155 &mov($count, &wparam(2)); # length 156 &and($count, 7); 157 &jz(&label("finish")); 158 159 &picsetup("edx"); 160 &picsymbol("ecx", &label("cbc_enc_jmp_table_".$name), "edx") 161 &mov($count,&DWP(0,"ecx",$count,4)); 162 &picadjust($count, "edx"); 163 164 &xor("ecx","ecx"); 165 &xor("edx","edx"); 166 &jmp_ptr($count); 167 168&set_label("ej7_".$name); 169 &movb(&HB("edx"), &BP(6,$in,"",0)); 170 &shl("edx",8); 171&set_label("ej6_".$name); 172 &movb(&HB("edx"), &BP(5,$in,"",0)); 173&set_label("ej5_".$name); 174 &movb(&LB("edx"), &BP(4,$in,"",0)); 175&set_label("ej4_".$name); 176 &mov("ecx", &DWP(0,$in,"",0)); 177 &jmp(&label("ejend")); 178&set_label("ej3_".$name); 179 &movb(&HB("ecx"), &BP(2,$in,"",0)); 180 &shl("ecx",8); 181&set_label("ej2_".$name); 182 &movb(&HB("ecx"), &BP(1,$in,"",0)); 183&set_label("ej1_".$name); 184 &movb(&LB("ecx"), &BP(0,$in,"",0)); 185&set_label("ejend"); 186 187 &xor("eax", "ecx"); 188 &xor("ebx", "edx"); 189 190 &bswap("eax") if $swap; 191 &bswap("ebx") if $swap; 192 193 &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call 194 &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 195 196 &call($enc_func); 197 198 &mov("eax", &DWP($data_off,"esp","",0)); 199 &mov("ebx", &DWP($data_off+4,"esp","",0)); 200 201 &bswap("eax") if $swap; 202 &bswap("ebx") if $swap; 203 204 &mov(&DWP(0,$out,"",0),"eax"); 205 &mov(&DWP(4,$out,"",0),"ebx"); 206 207 &jmp(&label("finish")); 208 209 ############################################################# 210 ############################################################# 211 &set_label("decrypt",1); 212 # decrypt start 213 &and($count,0xfffffff8); 214 # The next 2 instructions are only for if the jz is taken 215 &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0] 216 &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1] 217 &jz(&label("decrypt_finish")); 218 219 &set_label("decrypt_loop"); 220 &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes 221 &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes 222 223 &bswap("eax") if $swap; 224 &bswap("ebx") if $swap; 225 226 &mov(&DWP($data_off,"esp","",0), "eax"); # put back 227 &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 228 229 &call($dec_func); 230 231 &mov("eax", &DWP($data_off,"esp","",0)); # get return 232 &mov("ebx", &DWP($data_off+4,"esp","",0)); # 233 234 &bswap("eax") if $swap; 235 &bswap("ebx") if $swap; 236 237 &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] 238 &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] 239 240 &xor("ecx", "eax"); 241 &xor("edx", "ebx"); 242 243 &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, 244 &mov("ebx", &DWP(4,$in,"",0)); # next iv actually 245 246 &mov(&DWP(0,$out,"",0),"ecx"); 247 &mov(&DWP(4,$out,"",0),"edx"); 248 249 &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv 250 &mov(&DWP($data_off+12,"esp","",0), "ebx"); # 251 252 &add($in, 8); 253 &add($out, 8); 254 255 &sub($count, 8); 256 &jnz(&label("decrypt_loop")); 257############################ ENDIT #######################3 258 &set_label("decrypt_finish"); 259 &mov($count, &wparam(2)); # length 260 &and($count, 7); 261 &jz(&label("finish")); 262 263 &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes 264 &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes 265 266 &bswap("eax") if $swap; 267 &bswap("ebx") if $swap; 268 269 &mov(&DWP($data_off,"esp","",0), "eax"); # put back 270 &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 271 272 &call($dec_func); 273 274 &mov("eax", &DWP($data_off,"esp","",0)); # get return 275 &mov("ebx", &DWP($data_off+4,"esp","",0)); # 276 277 &bswap("eax") if $swap; 278 &bswap("ebx") if $swap; 279 280 &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] 281 &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] 282 283 &xor("ecx", "eax"); 284 &xor("edx", "ebx"); 285 286 # this is for when we exit 287 &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, 288 &mov("ebx", &DWP(4,$in,"",0)); # next iv actually 289 290 &rotr("edx", 16); 291 &movb(&BP(6,$out,"",0), &LB("edx")); 292 &shr("edx",16); 293 &movb(&BP(5,$out,"",0), &HB("edx")); 294 &movb(&BP(4,$out,"",0), &LB("edx")); 295 &mov(&DWP(0,$out,"",0), "ecx"); 296 297 # final iv is still in eax:ebx 298 299############################ FINISH #######################3 300 &set_label("finish",1); 301 &mov("ecx", &wparam($iv_off)); # Get iv ptr 302 303 ################################################# 304 $total=16+4; 305 $total+=4 if ($p1 > 0); 306 $total+=4 if ($p2 > 0); 307 $total+=4 if ($p3 > 0); 308 &add("esp",$total); 309 310 &mov(&DWP(0,"ecx","",0), "eax"); # save iv 311 &mov(&DWP(4,"ecx","",0), "ebx"); # save iv 312 313 &function_end_A($name); 314 &function_end_B($name); 315 316 &rodataseg(); 317 &align(64); 318 &set_label("cbc_enc_jmp_table_".$name); 319 &data_word("0"); 320 &data_word(&code_sym(&label("ej1_".$name))); 321 &data_word(&code_sym(&label("ej2_".$name))); 322 &data_word(&code_sym(&label("ej3_".$name))); 323 &data_word(&code_sym(&label("ej4_".$name))); 324 &data_word(&code_sym(&label("ej5_".$name))); 325 &data_word(&code_sym(&label("ej6_".$name))); 326 &data_word(&code_sym(&label("ej7_".$name))); 327 &previous(); 328 329 } 330 3311; 332