sm4-armv8.pl 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. #! /usr/bin/env perl
  2. # Copyright 2022 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. # This module implements support for SM4 hw support on aarch64
  10. # Oct 2021
  11. #
  12. # $output is the last argument if it looks like a file (it has an extension)
  13. # $flavour is the first argument if it doesn't look like a file
  14. $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
  15. $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
  16. $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
  17. ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
  18. ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
  19. die "can't locate arm-xlate.pl";
  20. open OUT,"| \"$^X\" $xlate $flavour \"$output\""
  21. or die "can't call $xlate: $!";
  22. *STDOUT=*OUT;
  23. $prefix="sm4_v8";
  24. my @rks=map("v$_",(0..7));
  25. sub rev32() {
  26. my $dst = shift;
  27. my $src = shift;
  28. $code.=<<___;
  29. #ifndef __ARMEB__
  30. rev32 $dst.16b,$src.16b
  31. #endif
  32. ___
  33. }
  34. sub enc_blk () {
  35. my $data = shift;
  36. $code.=<<___;
  37. sm4e $data.4s,@rks[0].4s
  38. sm4e $data.4s,@rks[1].4s
  39. sm4e $data.4s,@rks[2].4s
  40. sm4e $data.4s,@rks[3].4s
  41. sm4e $data.4s,@rks[4].4s
  42. sm4e $data.4s,@rks[5].4s
  43. sm4e $data.4s,@rks[6].4s
  44. sm4e $data.4s,@rks[7].4s
  45. rev64 $data.4S,$data.4S
  46. ext $data.16b,$data.16b,$data.16b,#8
  47. ___
  48. }
  49. sub enc_4blks () {
  50. my $data0 = shift;
  51. my $data1 = shift;
  52. my $data2 = shift;
  53. my $data3 = shift;
  54. $code.=<<___;
  55. sm4e $data0.4s,@rks[0].4s
  56. sm4e $data1.4s,@rks[0].4s
  57. sm4e $data2.4s,@rks[0].4s
  58. sm4e $data3.4s,@rks[0].4s
  59. sm4e $data0.4s,@rks[1].4s
  60. sm4e $data1.4s,@rks[1].4s
  61. sm4e $data2.4s,@rks[1].4s
  62. sm4e $data3.4s,@rks[1].4s
  63. sm4e $data0.4s,@rks[2].4s
  64. sm4e $data1.4s,@rks[2].4s
  65. sm4e $data2.4s,@rks[2].4s
  66. sm4e $data3.4s,@rks[2].4s
  67. sm4e $data0.4s,@rks[3].4s
  68. sm4e $data1.4s,@rks[3].4s
  69. sm4e $data2.4s,@rks[3].4s
  70. sm4e $data3.4s,@rks[3].4s
  71. sm4e $data0.4s,@rks[4].4s
  72. sm4e $data1.4s,@rks[4].4s
  73. sm4e $data2.4s,@rks[4].4s
  74. sm4e $data3.4s,@rks[4].4s
  75. sm4e $data0.4s,@rks[5].4s
  76. sm4e $data1.4s,@rks[5].4s
  77. sm4e $data2.4s,@rks[5].4s
  78. sm4e $data3.4s,@rks[5].4s
  79. sm4e $data0.4s,@rks[6].4s
  80. sm4e $data1.4s,@rks[6].4s
  81. sm4e $data2.4s,@rks[6].4s
  82. sm4e $data3.4s,@rks[6].4s
  83. sm4e $data0.4s,@rks[7].4s
  84. rev64 $data0.4S,$data0.4S
  85. sm4e $data1.4s,@rks[7].4s
  86. ext $data0.16b,$data0.16b,$data0.16b,#8
  87. rev64 $data1.4S,$data1.4S
  88. sm4e $data2.4s,@rks[7].4s
  89. ext $data1.16b,$data1.16b,$data1.16b,#8
  90. rev64 $data2.4S,$data2.4S
  91. sm4e $data3.4s,@rks[7].4s
  92. ext $data2.16b,$data2.16b,$data2.16b,#8
  93. rev64 $data3.4S,$data3.4S
  94. ext $data3.16b,$data3.16b,$data3.16b,#8
  95. ___
  96. }
  97. $code=<<___;
  98. #include "arm_arch.h"
  99. .arch armv8-a+crypto
  100. .text
  101. ___
  102. {{{
  103. $code.=<<___;
  104. .align 6
  105. .Lck:
  106. .long 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269
  107. .long 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9
  108. .long 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249
  109. .long 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9
  110. .long 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229
  111. .long 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299
  112. .long 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209
  113. .long 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279
  114. .Lfk:
  115. .long 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc
  116. ___
  117. }}}
  118. {{{
  119. my ($key,$keys)=("x0","x1");
  120. my ($tmp)=("x2");
  121. my ($key0,$key1,$key2,$key3,$key4,$key5,$key6,$key7)=map("v$_",(0..7));
  122. my ($const0,$const1,$const2,$const3,$const4,$const5,$const6,$const7)=map("v$_",(16..23));
  123. my ($fkconst) = ("v24");
  124. $code.=<<___;
  125. .globl ${prefix}_set_encrypt_key
  126. .type ${prefix}_set_encrypt_key,%function
  127. .align 5
  128. ${prefix}_set_encrypt_key:
  129. AARCH64_VALID_CALL_TARGET
  130. ld1 {$key0.4s},[$key]
  131. adr $tmp,.Lfk
  132. ld1 {$fkconst.4s},[$tmp]
  133. adr $tmp,.Lck
  134. ld1 {$const0.4s,$const1.4s,$const2.4s,$const3.4s},[$tmp],64
  135. ___
  136. &rev32($key0, $key0);
  137. $code.=<<___;
  138. ld1 {$const4.4s,$const5.4s,$const6.4s,$const7.4s},[$tmp]
  139. eor $key0.16b,$key0.16b,$fkconst.16b;
  140. sm4ekey $key0.4S,$key0.4S,$const0.4S
  141. sm4ekey $key1.4S,$key0.4S,$const1.4S
  142. sm4ekey $key2.4S,$key1.4S,$const2.4S
  143. sm4ekey $key3.4S,$key2.4S,$const3.4S
  144. sm4ekey $key4.4S,$key3.4S,$const4.4S
  145. st1 {$key0.4s,$key1.4s,$key2.4s,$key3.4s},[$keys],64
  146. sm4ekey $key5.4S,$key4.4S,$const5.4S
  147. sm4ekey $key6.4S,$key5.4S,$const6.4S
  148. sm4ekey $key7.4S,$key6.4S,$const7.4S
  149. st1 {$key4.4s,$key5.4s,$key6.4s,$key7.4s},[$keys]
  150. ret
  151. .size ${prefix}_set_encrypt_key,.-${prefix}_set_encrypt_key
  152. ___
  153. }}}
  154. {{{
  155. my ($key,$keys)=("x0","x1");
  156. my ($tmp)=("x2");
  157. my ($key7,$key6,$key5,$key4,$key3,$key2,$key1,$key0)=map("v$_",(0..7));
  158. my ($const0,$const1,$const2,$const3,$const4,$const5,$const6,$const7)=map("v$_",(16..23));
  159. my ($fkconst) = ("v24");
  160. $code.=<<___;
  161. .globl ${prefix}_set_decrypt_key
  162. .type ${prefix}_set_decrypt_key,%function
  163. .align 5
  164. ${prefix}_set_decrypt_key:
  165. AARCH64_VALID_CALL_TARGET
  166. ld1 {$key0.4s},[$key]
  167. adr $tmp,.Lfk
  168. ld1 {$fkconst.4s},[$tmp]
  169. adr $tmp, .Lck
  170. ld1 {$const0.4s,$const1.4s,$const2.4s,$const3.4s},[$tmp],64
  171. ___
  172. &rev32($key0, $key0);
  173. $code.=<<___;
  174. ld1 {$const4.4s,$const5.4s,$const6.4s,$const7.4s},[$tmp]
  175. eor $key0.16b, $key0.16b,$fkconst.16b;
  176. sm4ekey $key0.4S,$key0.4S,$const0.4S
  177. sm4ekey $key1.4S,$key0.4S,$const1.4S
  178. sm4ekey $key2.4S,$key1.4S,$const2.4S
  179. rev64 $key0.4s,$key0.4s
  180. rev64 $key1.4s,$key1.4s
  181. ext $key0.16b,$key0.16b,$key0.16b,#8
  182. ext $key1.16b,$key1.16b,$key1.16b,#8
  183. sm4ekey $key3.4S,$key2.4S,$const3.4S
  184. sm4ekey $key4.4S,$key3.4S,$const4.4S
  185. rev64 $key2.4s,$key2.4s
  186. rev64 $key3.4s,$key3.4s
  187. ext $key2.16b,$key2.16b,$key2.16b,#8
  188. ext $key3.16b,$key3.16b,$key3.16b,#8
  189. sm4ekey $key5.4S,$key4.4S,$const5.4S
  190. sm4ekey $key6.4S,$key5.4S,$const6.4S
  191. rev64 $key4.4s,$key4.4s
  192. rev64 $key5.4s,$key5.4s
  193. ext $key4.16b,$key4.16b,$key4.16b,#8
  194. ext $key5.16b,$key5.16b,$key5.16b,#8
  195. sm4ekey $key7.4S,$key6.4S,$const7.4S
  196. rev64 $key6.4s, $key6.4s
  197. rev64 $key7.4s, $key7.4s
  198. ext $key6.16b,$key6.16b,$key6.16b,#8
  199. ext $key7.16b,$key7.16b,$key7.16b,#8
  200. st1 {$key7.4s,$key6.4s,$key5.4s,$key4.4s},[$keys],64
  201. st1 {$key3.4s,$key2.4s,$key1.4s,$key0.4s},[$keys]
  202. ret
  203. .size ${prefix}_set_decrypt_key,.-${prefix}_set_decrypt_key
  204. ___
  205. }}}
  206. {{{
  207. sub gen_block () {
  208. my $dir = shift;
  209. my ($inp,$out,$rk)=map("x$_",(0..2));
  210. my ($data)=("v16");
  211. $code.=<<___;
  212. .globl ${prefix}_${dir}crypt
  213. .type ${prefix}_${dir}crypt,%function
  214. .align 5
  215. ${prefix}_${dir}crypt:
  216. AARCH64_VALID_CALL_TARGET
  217. ld1 {$data.4s},[$inp]
  218. ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],64
  219. ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk]
  220. ___
  221. &rev32($data,$data);
  222. &enc_blk($data);
  223. &rev32($data,$data);
  224. $code.=<<___;
  225. st1 {$data.4s},[$out]
  226. ret
  227. .size ${prefix}_${dir}crypt,.-${prefix}_${dir}crypt
  228. ___
  229. }
  230. &gen_block("en");
  231. &gen_block("de");
  232. }}}
  233. {{{
  234. my ($inp,$out,$len,$rk)=map("x$_",(0..3));
  235. my ($enc) = ("w4");
  236. my @dat=map("v$_",(16..23));
  237. $code.=<<___;
  238. .globl ${prefix}_ecb_encrypt
  239. .type ${prefix}_ecb_encrypt,%function
  240. .align 5
  241. ${prefix}_ecb_encrypt:
  242. AARCH64_VALID_CALL_TARGET
  243. ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],#64
  244. ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk]
  245. 1:
  246. cmp $len,#64
  247. b.lt 1f
  248. ld1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp],#64
  249. cmp $len,#128
  250. b.lt 2f
  251. ld1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$inp],#64
  252. // 8 blocks
  253. ___
  254. &rev32(@dat[0],@dat[0]);
  255. &rev32(@dat[1],@dat[1]);
  256. &rev32(@dat[2],@dat[2]);
  257. &rev32(@dat[3],@dat[3]);
  258. &rev32(@dat[4],@dat[4]);
  259. &rev32(@dat[5],@dat[5]);
  260. &rev32(@dat[6],@dat[6]);
  261. &rev32(@dat[7],@dat[7]);
  262. &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
  263. &enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]);
  264. &rev32(@dat[0],@dat[0]);
  265. &rev32(@dat[1],@dat[1]);
  266. &rev32(@dat[2],@dat[2]);
  267. &rev32(@dat[3],@dat[3]);
  268. &rev32(@dat[4],@dat[4]);
  269. &rev32(@dat[5],@dat[5]);
  270. $code.=<<___;
  271. st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
  272. ___
  273. &rev32(@dat[6],@dat[6]);
  274. &rev32(@dat[7],@dat[7]);
  275. $code.=<<___;
  276. st1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64
  277. subs $len,$len,#128
  278. b.gt 1b
  279. ret
  280. // 4 blocks
  281. 2:
  282. ___
  283. &rev32(@dat[0],@dat[0]);
  284. &rev32(@dat[1],@dat[1]);
  285. &rev32(@dat[2],@dat[2]);
  286. &rev32(@dat[3],@dat[3]);
  287. &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
  288. &rev32(@dat[0],@dat[0]);
  289. &rev32(@dat[1],@dat[1]);
  290. &rev32(@dat[2],@dat[2]);
  291. &rev32(@dat[3],@dat[3]);
  292. $code.=<<___;
  293. st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
  294. subs $len,$len,#64
  295. b.gt 1b
  296. 1:
  297. subs $len,$len,#16
  298. b.lt 1f
  299. ld1 {@dat[0].4s},[$inp],#16
  300. ___
  301. &rev32(@dat[0],@dat[0]);
  302. &enc_blk(@dat[0]);
  303. &rev32(@dat[0],@dat[0]);
  304. $code.=<<___;
  305. st1 {@dat[0].4s},[$out],#16
  306. b.ne 1b
  307. 1:
  308. ret
  309. .size ${prefix}_ecb_encrypt,.-${prefix}_ecb_encrypt
  310. ___
  311. }}}
  312. {{{
  313. my ($inp,$out,$len,$rk,$ivp)=map("x$_",(0..4));
  314. my ($enc) = ("w5");
  315. my @dat=map("v$_",(16..23));
  316. my @in=map("v$_",(24..31));
  317. my ($ivec) = ("v8");
  318. $code.=<<___;
  319. .globl ${prefix}_cbc_encrypt
  320. .type ${prefix}_cbc_encrypt,%function
  321. .align 5
  322. ${prefix}_cbc_encrypt:
  323. AARCH64_VALID_CALL_TARGET
  324. stp d8,d9,[sp, #-16]!
  325. ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],#64
  326. ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk]
  327. ld1 {$ivec.4s},[$ivp]
  328. cmp $enc,#0
  329. b.eq .Ldec
  330. 1:
  331. cmp $len, #64
  332. b.lt 1f
  333. ld1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp],#64
  334. eor @dat[0].16b,@dat[0].16b,$ivec.16b
  335. ___
  336. &rev32(@dat[1],@dat[1]);
  337. &rev32(@dat[0],@dat[0]);
  338. &rev32(@dat[2],@dat[2]);
  339. &rev32(@dat[3],@dat[3]);
  340. &enc_blk(@dat[0]);
  341. $code.=<<___;
  342. eor @dat[1].16b,@dat[1].16b,@dat[0].16b
  343. ___
  344. &enc_blk(@dat[1]);
  345. &rev32(@dat[0],@dat[0]);
  346. $code.=<<___;
  347. eor @dat[2].16b,@dat[2].16b,@dat[1].16b
  348. ___
  349. &enc_blk(@dat[2]);
  350. &rev32(@dat[1],@dat[1]);
  351. $code.=<<___;
  352. eor @dat[3].16b,@dat[3].16b,@dat[2].16b
  353. ___
  354. &enc_blk(@dat[3]);
  355. &rev32(@dat[2],@dat[2]);
  356. &rev32(@dat[3],@dat[3]);
  357. $code.=<<___;
  358. mov $ivec.16b,@dat[3].16b
  359. st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
  360. subs $len,$len,#64
  361. b.ne 1b
  362. 1:
  363. subs $len,$len,#16
  364. b.lt 3f
  365. ld1 {@dat[0].4s},[$inp],#16
  366. eor $ivec.16b,$ivec.16b,@dat[0].16b
  367. ___
  368. &rev32($ivec,$ivec);
  369. &enc_blk($ivec);
  370. &rev32($ivec,$ivec);
  371. $code.=<<___;
  372. st1 {$ivec.16b},[$out],#16
  373. b.ne 1b
  374. b 3f
  375. .Ldec:
  376. 1:
  377. cmp $len, #64
  378. b.lt 1f
  379. ld1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$inp]
  380. ld1 {@in[0].4s,@in[1].4s,@in[2].4s,@in[3].4s},[$inp],#64
  381. cmp $len,#128
  382. b.lt 2f
  383. // 8 blocks mode
  384. ld1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$inp]
  385. ld1 {@in[4].4s,@in[5].4s,@in[6].4s,@in[7].4s},[$inp],#64
  386. ___
  387. &rev32(@dat[0],@dat[0]);
  388. &rev32(@dat[1],@dat[1]);
  389. &rev32(@dat[2],@dat[2]);
  390. &rev32(@dat[3],$dat[3]);
  391. &rev32(@dat[4],@dat[4]);
  392. &rev32(@dat[5],@dat[5]);
  393. &rev32(@dat[6],@dat[6]);
  394. &rev32(@dat[7],$dat[7]);
  395. &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
  396. &enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]);
  397. &rev32(@dat[0],@dat[0]);
  398. &rev32(@dat[1],@dat[1]);
  399. &rev32(@dat[2],@dat[2]);
  400. &rev32(@dat[3],@dat[3]);
  401. &rev32(@dat[4],@dat[4]);
  402. &rev32(@dat[5],@dat[5]);
  403. &rev32(@dat[6],@dat[6]);
  404. &rev32(@dat[7],@dat[7]);
  405. $code.=<<___;
  406. eor @dat[0].16b,@dat[0].16b,$ivec.16b
  407. eor @dat[1].16b,@dat[1].16b,@in[0].16b
  408. eor @dat[2].16b,@dat[2].16b,@in[1].16b
  409. mov $ivec.16b,@in[7].16b
  410. eor @dat[3].16b,$dat[3].16b,@in[2].16b
  411. eor @dat[4].16b,$dat[4].16b,@in[3].16b
  412. eor @dat[5].16b,$dat[5].16b,@in[4].16b
  413. eor @dat[6].16b,$dat[6].16b,@in[5].16b
  414. eor @dat[7].16b,$dat[7].16b,@in[6].16b
  415. st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
  416. st1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64
  417. subs $len,$len,128
  418. b.gt 1b
  419. b 3f
  420. // 4 blocks mode
  421. 2:
  422. ___
  423. &rev32(@dat[0],@dat[0]);
  424. &rev32(@dat[1],@dat[1]);
  425. &rev32(@dat[2],@dat[2]);
  426. &rev32(@dat[3],$dat[3]);
  427. &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
  428. &rev32(@dat[0],@dat[0]);
  429. &rev32(@dat[1],@dat[1]);
  430. &rev32(@dat[2],@dat[2]);
  431. &rev32(@dat[3],@dat[3]);
  432. $code.=<<___;
  433. eor @dat[0].16b,@dat[0].16b,$ivec.16b
  434. eor @dat[1].16b,@dat[1].16b,@in[0].16b
  435. mov $ivec.16b,@in[3].16b
  436. eor @dat[2].16b,@dat[2].16b,@in[1].16b
  437. eor @dat[3].16b,$dat[3].16b,@in[2].16b
  438. st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
  439. subs $len,$len,#64
  440. b.gt 1b
  441. 1:
  442. subs $len,$len,#16
  443. b.lt 3f
  444. ld1 {@dat[0].4s},[$inp],#16
  445. mov @in[0].16b,@dat[0].16b
  446. ___
  447. &rev32(@dat[0],@dat[0]);
  448. &enc_blk(@dat[0]);
  449. &rev32(@dat[0],@dat[0]);
  450. $code.=<<___;
  451. eor @dat[0].16b,@dat[0].16b,$ivec.16b
  452. mov $ivec.16b,@in[0].16b
  453. st1 {@dat[0].16b},[$out],#16
  454. b.ne 1b
  455. 3:
  456. // save back IV
  457. st1 {$ivec.16b},[$ivp]
  458. ldp d8,d9,[sp],#16
  459. ret
  460. .size ${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt
  461. ___
  462. }}}
  463. {{{
  464. my ($inp,$out,$len,$rk,$ivp)=map("x$_",(0..4));
  465. my ($ctr)=("w5");
  466. my @dat=map("v$_",(16..23));
  467. my @in=map("v$_",(24..31));
  468. my ($ivec)=("v8");
  469. $code.=<<___;
  470. .globl ${prefix}_ctr32_encrypt_blocks
  471. .type ${prefix}_ctr32_encrypt_blocks,%function
  472. .align 5
  473. ${prefix}_ctr32_encrypt_blocks:
  474. AARCH64_VALID_CALL_TARGET
  475. stp d8,d9,[sp, #-16]!
  476. ld1 {$ivec.4s},[$ivp]
  477. ld1 {@rks[0].4s,@rks[1].4s,@rks[2].4s,@rks[3].4s},[$rk],64
  478. ld1 {@rks[4].4s,@rks[5].4s,@rks[6].4s,@rks[7].4s},[$rk]
  479. ___
  480. &rev32($ivec,$ivec);
  481. $code.=<<___;
  482. mov $ctr,$ivec.s[3]
  483. 1:
  484. cmp $len,#4
  485. b.lt 1f
  486. ld1 {@in[0].4s,@in[1].4s,@in[2].4s,@in[3].4s},[$inp],#64
  487. mov @dat[0].16b,$ivec.16b
  488. mov @dat[1].16b,$ivec.16b
  489. mov @dat[2].16b,$ivec.16b
  490. mov @dat[3].16b,$ivec.16b
  491. add $ctr,$ctr,#1
  492. mov $dat[1].s[3],$ctr
  493. add $ctr,$ctr,#1
  494. mov @dat[2].s[3],$ctr
  495. add $ctr,$ctr,#1
  496. mov @dat[3].s[3],$ctr
  497. cmp $len,#8
  498. b.lt 2f
  499. ld1 {@in[4].4s,@in[5].4s,@in[6].4s,@in[7].4s},[$inp],#64
  500. mov @dat[4].16b,$ivec.16b
  501. mov @dat[5].16b,$ivec.16b
  502. mov @dat[6].16b,$ivec.16b
  503. mov @dat[7].16b,$ivec.16b
  504. add $ctr,$ctr,#1
  505. mov $dat[4].s[3],$ctr
  506. add $ctr,$ctr,#1
  507. mov @dat[5].s[3],$ctr
  508. add $ctr,$ctr,#1
  509. mov @dat[6].s[3],$ctr
  510. add $ctr,$ctr,#1
  511. mov @dat[7].s[3],$ctr
  512. ___
  513. &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
  514. &enc_4blks(@dat[4],@dat[5],@dat[6],@dat[7]);
  515. &rev32(@dat[0],@dat[0]);
  516. &rev32(@dat[1],@dat[1]);
  517. &rev32(@dat[2],@dat[2]);
  518. &rev32(@dat[3],@dat[3]);
  519. &rev32(@dat[4],@dat[4]);
  520. &rev32(@dat[5],@dat[5]);
  521. &rev32(@dat[6],@dat[6]);
  522. &rev32(@dat[7],@dat[7]);
  523. $code.=<<___;
  524. eor @dat[0].16b,@dat[0].16b,@in[0].16b
  525. eor @dat[1].16b,@dat[1].16b,@in[1].16b
  526. eor @dat[2].16b,@dat[2].16b,@in[2].16b
  527. eor @dat[3].16b,@dat[3].16b,@in[3].16b
  528. eor @dat[4].16b,@dat[4].16b,@in[4].16b
  529. eor @dat[5].16b,@dat[5].16b,@in[5].16b
  530. eor @dat[6].16b,@dat[6].16b,@in[6].16b
  531. eor @dat[7].16b,@dat[7].16b,@in[7].16b
  532. st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
  533. st1 {@dat[4].4s,@dat[5].4s,@dat[6].4s,@dat[7].4s},[$out],#64
  534. subs $len,$len,#8
  535. b.eq 3f
  536. add $ctr,$ctr,#1
  537. mov $ivec.s[3],$ctr
  538. b 1b
  539. 2:
  540. ___
  541. &enc_4blks(@dat[0],@dat[1],@dat[2],@dat[3]);
  542. &rev32(@dat[0],@dat[0]);
  543. &rev32(@dat[1],@dat[1]);
  544. &rev32(@dat[2],@dat[2]);
  545. &rev32(@dat[3],@dat[3]);
  546. $code.=<<___;
  547. eor @dat[0].16b,@dat[0].16b,@in[0].16b
  548. eor @dat[1].16b,@dat[1].16b,@in[1].16b
  549. eor @dat[2].16b,@dat[2].16b,@in[2].16b
  550. eor @dat[3].16b,@dat[3].16b,@in[3].16b
  551. st1 {@dat[0].4s,@dat[1].4s,@dat[2].4s,@dat[3].4s},[$out],#64
  552. subs $len,$len,#4
  553. b.eq 3f
  554. add $ctr,$ctr,#1
  555. mov $ivec.s[3],$ctr
  556. b 1b
  557. 1:
  558. subs $len,$len,#1
  559. b.lt 3f
  560. mov $dat[0].16b,$ivec.16b
  561. ld1 {@in[0].4s},[$inp],#16
  562. ___
  563. &enc_blk(@dat[0]);
  564. &rev32(@dat[0],@dat[0]);
  565. $code.=<<___;
  566. eor $dat[0].16b,$dat[0].16b,@in[0].16b
  567. st1 {$dat[0].4s},[$out],#16
  568. b.eq 3f
  569. add $ctr,$ctr,#1
  570. mov $ivec.s[3],$ctr
  571. b 1b
  572. 3:
  573. ldp d8,d9,[sp],#16
  574. ret
  575. .size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks
  576. ___
  577. }}}
  578. ########################################
  579. { my %opcode = (
  580. "sm4e" => 0xcec08400,
  581. "sm4ekey" => 0xce60c800);
  582. sub unsm4 {
  583. my ($mnemonic,$arg)=@_;
  584. $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o
  585. &&
  586. sprintf ".inst\t0x%08x\t//%s %s",
  587. $opcode{$mnemonic}|$1|($2<<5)|($3<<16),
  588. $mnemonic,$arg;
  589. }
  590. }
  591. open SELF,$0;
  592. while(<SELF>) {
  593. next if (/^#!/);
  594. last if (!s/^#/\/\// and !/^$/);
  595. print;
  596. }
  597. close SELF;
  598. foreach(split("\n",$code)) {
  599. s/\`([^\`]*)\`/eval($1)/ge;
  600. s/\b(sm4\w+)\s+([qv].*)/unsm4($1,$2)/ge;
  601. print $_,"\n";
  602. }
  603. close STDOUT or die "error closing STDOUT: $!";