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