cbc.pl 9.3 KB

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