1#! /usr/bin/env perl 2# Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 3# 4# Licensed under the Apache License 2.0 (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 &endbranch() 169 &movb(&HB("edx"), &BP(6,$in,"",0)); 170 &shl("edx",8); 171&set_label("ej6"); 172 &endbranch() 173 &movb(&HB("edx"), &BP(5,$in,"",0)); 174&set_label("ej5"); 175 &endbranch() 176 &movb(&LB("edx"), &BP(4,$in,"",0)); 177&set_label("ej4"); 178 &endbranch() 179 &mov("ecx", &DWP(0,$in,"",0)); 180 &jmp(&label("ejend")); 181&set_label("ej3"); 182 &endbranch() 183 &movb(&HB("ecx"), &BP(2,$in,"",0)); 184 &shl("ecx",8); 185&set_label("ej2"); 186 &endbranch() 187 &movb(&HB("ecx"), &BP(1,$in,"",0)); 188&set_label("ej1"); 189 &endbranch() 190 &movb(&LB("ecx"), &BP(0,$in,"",0)); 191&set_label("ejend"); 192 193 &xor("eax", "ecx"); 194 &xor("ebx", "edx"); 195 196 &bswap("eax") if $swap; 197 &bswap("ebx") if $swap; 198 199 &mov(&DWP($data_off,"esp","",0), "eax"); # put in array for call 200 &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 201 202 &call($enc_func); 203 204 &mov("eax", &DWP($data_off,"esp","",0)); 205 &mov("ebx", &DWP($data_off+4,"esp","",0)); 206 207 &bswap("eax") if $swap; 208 &bswap("ebx") if $swap; 209 210 &mov(&DWP(0,$out,"",0),"eax"); 211 &mov(&DWP(4,$out,"",0),"ebx"); 212 213 &jmp(&label("finish")); 214 215 ############################################################# 216 ############################################################# 217 &set_label("decrypt",1); 218 # decrypt start 219 &and($count,0xfffffff8); 220 # The next 2 instructions are only for if the jz is taken 221 &mov("eax", &DWP($data_off+8,"esp","",0)); # get iv[0] 222 &mov("ebx", &DWP($data_off+12,"esp","",0)); # get iv[1] 223 &jz(&label("decrypt_finish")); 224 225 &set_label("decrypt_loop"); 226 &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes 227 &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes 228 229 &bswap("eax") if $swap; 230 &bswap("ebx") if $swap; 231 232 &mov(&DWP($data_off,"esp","",0), "eax"); # put back 233 &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 234 235 &call($dec_func); 236 237 &mov("eax", &DWP($data_off,"esp","",0)); # get return 238 &mov("ebx", &DWP($data_off+4,"esp","",0)); # 239 240 &bswap("eax") if $swap; 241 &bswap("ebx") if $swap; 242 243 &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] 244 &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] 245 246 &xor("ecx", "eax"); 247 &xor("edx", "ebx"); 248 249 &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, 250 &mov("ebx", &DWP(4,$in,"",0)); # next iv actually 251 252 &mov(&DWP(0,$out,"",0),"ecx"); 253 &mov(&DWP(4,$out,"",0),"edx"); 254 255 &mov(&DWP($data_off+8,"esp","",0), "eax"); # save iv 256 &mov(&DWP($data_off+12,"esp","",0), "ebx"); # 257 258 &add($in, 8); 259 &add($out, 8); 260 261 &sub($count, 8); 262 &jnz(&label("decrypt_loop")); 263############################ ENDIT #######################3 264 &set_label("decrypt_finish"); 265 &mov($count, &wparam(2)); # length 266 &and($count, 7); 267 &jz(&label("finish")); 268 269 &mov("eax", &DWP(0,$in,"",0)); # load first 4 bytes 270 &mov("ebx", &DWP(4,$in,"",0)); # second 4 bytes 271 272 &bswap("eax") if $swap; 273 &bswap("ebx") if $swap; 274 275 &mov(&DWP($data_off,"esp","",0), "eax"); # put back 276 &mov(&DWP($data_off+4,"esp","",0), "ebx"); # 277 278 &call($dec_func); 279 280 &mov("eax", &DWP($data_off,"esp","",0)); # get return 281 &mov("ebx", &DWP($data_off+4,"esp","",0)); # 282 283 &bswap("eax") if $swap; 284 &bswap("ebx") if $swap; 285 286 &mov("ecx", &DWP($data_off+8,"esp","",0)); # get iv[0] 287 &mov("edx", &DWP($data_off+12,"esp","",0)); # get iv[1] 288 289 &xor("ecx", "eax"); 290 &xor("edx", "ebx"); 291 292 # this is for when we exit 293 &mov("eax", &DWP(0,$in,"",0)); # get old cipher text, 294 &mov("ebx", &DWP(4,$in,"",0)); # next iv actually 295 296&set_label("dj7"); 297 &rotr("edx", 16); 298 &movb(&BP(6,$out,"",0), &LB("edx")); 299 &shr("edx",16); 300&set_label("dj6"); 301 &movb(&BP(5,$out,"",0), &HB("edx")); 302&set_label("dj5"); 303 &movb(&BP(4,$out,"",0), &LB("edx")); 304&set_label("dj4"); 305 &mov(&DWP(0,$out,"",0), "ecx"); 306 &jmp(&label("djend")); 307&set_label("dj3"); 308 &rotr("ecx", 16); 309 &movb(&BP(2,$out,"",0), &LB("ecx")); 310 &shl("ecx",16); 311&set_label("dj2"); 312 &movb(&BP(1,$in,"",0), &HB("ecx")); 313&set_label("dj1"); 314 &movb(&BP(0,$in,"",0), &LB("ecx")); 315&set_label("djend"); 316 317 # final iv is still in eax:ebx 318 &jmp(&label("finish")); 319 320 321############################ FINISH #######################3 322 &set_label("finish",1); 323 &mov("ecx", &wparam($iv_off)); # Get iv ptr 324 325 ################################################# 326 $total=16+4; 327 $total+=4 if ($p1 > 0); 328 $total+=4 if ($p2 > 0); 329 $total+=4 if ($p3 > 0); 330 &add("esp",$total); 331 332 &mov(&DWP(0,"ecx","",0), "eax"); # save iv 333 &mov(&DWP(4,"ecx","",0), "ebx"); # save iv 334 335 &function_end_A($name); 336 337 &align(64); 338 &set_label("cbc_enc_jmp_table"); 339 &data_word("0"); 340 &data_word(&label("ej1")."-".&label("PIC_point")); 341 &data_word(&label("ej2")."-".&label("PIC_point")); 342 &data_word(&label("ej3")."-".&label("PIC_point")); 343 &data_word(&label("ej4")."-".&label("PIC_point")); 344 &data_word(&label("ej5")."-".&label("PIC_point")); 345 &data_word(&label("ej6")."-".&label("PIC_point")); 346 &data_word(&label("ej7")."-".&label("PIC_point")); 347 # not used 348 #&set_label("cbc_dec_jmp_table",1); 349 #&data_word("0"); 350 #&data_word(&label("dj1")."-".&label("PIC_point")); 351 #&data_word(&label("dj2")."-".&label("PIC_point")); 352 #&data_word(&label("dj3")."-".&label("PIC_point")); 353 #&data_word(&label("dj4")."-".&label("PIC_point")); 354 #&data_word(&label("dj5")."-".&label("PIC_point")); 355 #&data_word(&label("dj6")."-".&label("PIC_point")); 356 #&data_word(&label("dj7")."-".&label("PIC_point")); 357 &align(64); 358 359 &function_end_B($name); 360 361 } 362 3631; 364