morus1280-avx2-asm.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*
  2. * AVX2 implementation of MORUS-1280
  3. *
  4. * Copyright (c) 2017-2018 Ondrej Mosnacek <omosnacek@gmail.com>
  5. * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License version 2 as published
  9. * by the Free Software Foundation.
  10. */
  11. #include <linux/linkage.h>
  12. #include <asm/frame.h>
  13. #define SHUFFLE_MASK(i0, i1, i2, i3) \
  14. (i0 | (i1 << 2) | (i2 << 4) | (i3 << 6))
  15. #define MASK1 SHUFFLE_MASK(3, 0, 1, 2)
  16. #define MASK2 SHUFFLE_MASK(2, 3, 0, 1)
  17. #define MASK3 SHUFFLE_MASK(1, 2, 3, 0)
  18. #define STATE0 %ymm0
  19. #define STATE0_LOW %xmm0
  20. #define STATE1 %ymm1
  21. #define STATE2 %ymm2
  22. #define STATE3 %ymm3
  23. #define STATE4 %ymm4
  24. #define KEY %ymm5
  25. #define MSG %ymm5
  26. #define MSG_LOW %xmm5
  27. #define T0 %ymm6
  28. #define T0_LOW %xmm6
  29. #define T1 %ymm7
  30. .section .rodata.cst32.morus1280_const, "aM", @progbits, 32
  31. .align 32
  32. .Lmorus1280_const:
  33. .byte 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d
  34. .byte 0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62
  35. .byte 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1
  36. .byte 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd
  37. .section .rodata.cst32.morus1280_counter, "aM", @progbits, 32
  38. .align 32
  39. .Lmorus1280_counter:
  40. .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
  41. .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
  42. .byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
  43. .byte 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
  44. .text
  45. .macro morus1280_round s0, s1, s2, s3, s4, b, w
  46. vpand \s1, \s2, T0
  47. vpxor T0, \s0, \s0
  48. vpxor \s3, \s0, \s0
  49. vpsllq $\b, \s0, T0
  50. vpsrlq $(64 - \b), \s0, \s0
  51. vpxor T0, \s0, \s0
  52. vpermq $\w, \s3, \s3
  53. .endm
  54. /*
  55. * __morus1280_update: internal ABI
  56. * input:
  57. * STATE[0-4] - input state
  58. * MSG - message block
  59. * output:
  60. * STATE[0-4] - output state
  61. * changed:
  62. * T0
  63. */
  64. __morus1280_update:
  65. morus1280_round STATE0, STATE1, STATE2, STATE3, STATE4, 13, MASK1
  66. vpxor MSG, STATE1, STATE1
  67. morus1280_round STATE1, STATE2, STATE3, STATE4, STATE0, 46, MASK2
  68. vpxor MSG, STATE2, STATE2
  69. morus1280_round STATE2, STATE3, STATE4, STATE0, STATE1, 38, MASK3
  70. vpxor MSG, STATE3, STATE3
  71. morus1280_round STATE3, STATE4, STATE0, STATE1, STATE2, 7, MASK2
  72. vpxor MSG, STATE4, STATE4
  73. morus1280_round STATE4, STATE0, STATE1, STATE2, STATE3, 4, MASK1
  74. ret
  75. ENDPROC(__morus1280_update)
  76. /*
  77. * __morus1280_update_zero: internal ABI
  78. * input:
  79. * STATE[0-4] - input state
  80. * output:
  81. * STATE[0-4] - output state
  82. * changed:
  83. * T0
  84. */
  85. __morus1280_update_zero:
  86. morus1280_round STATE0, STATE1, STATE2, STATE3, STATE4, 13, MASK1
  87. morus1280_round STATE1, STATE2, STATE3, STATE4, STATE0, 46, MASK2
  88. morus1280_round STATE2, STATE3, STATE4, STATE0, STATE1, 38, MASK3
  89. morus1280_round STATE3, STATE4, STATE0, STATE1, STATE2, 7, MASK2
  90. morus1280_round STATE4, STATE0, STATE1, STATE2, STATE3, 4, MASK1
  91. ret
  92. ENDPROC(__morus1280_update_zero)
  93. /*
  94. * __load_partial: internal ABI
  95. * input:
  96. * %rsi - src
  97. * %rcx - bytes
  98. * output:
  99. * MSG - message block
  100. * changed:
  101. * %r8
  102. * %r9
  103. */
  104. __load_partial:
  105. xor %r9d, %r9d
  106. vpxor MSG, MSG, MSG
  107. mov %rcx, %r8
  108. and $0x1, %r8
  109. jz .Lld_partial_1
  110. mov %rcx, %r8
  111. and $0x1E, %r8
  112. add %rsi, %r8
  113. mov (%r8), %r9b
  114. .Lld_partial_1:
  115. mov %rcx, %r8
  116. and $0x2, %r8
  117. jz .Lld_partial_2
  118. mov %rcx, %r8
  119. and $0x1C, %r8
  120. add %rsi, %r8
  121. shl $16, %r9
  122. mov (%r8), %r9w
  123. .Lld_partial_2:
  124. mov %rcx, %r8
  125. and $0x4, %r8
  126. jz .Lld_partial_4
  127. mov %rcx, %r8
  128. and $0x18, %r8
  129. add %rsi, %r8
  130. shl $32, %r9
  131. mov (%r8), %r8d
  132. xor %r8, %r9
  133. .Lld_partial_4:
  134. movq %r9, MSG_LOW
  135. mov %rcx, %r8
  136. and $0x8, %r8
  137. jz .Lld_partial_8
  138. mov %rcx, %r8
  139. and $0x10, %r8
  140. add %rsi, %r8
  141. pshufd $MASK2, MSG_LOW, MSG_LOW
  142. pinsrq $0, (%r8), MSG_LOW
  143. .Lld_partial_8:
  144. mov %rcx, %r8
  145. and $0x10, %r8
  146. jz .Lld_partial_16
  147. vpermq $MASK2, MSG, MSG
  148. movdqu (%rsi), MSG_LOW
  149. .Lld_partial_16:
  150. ret
  151. ENDPROC(__load_partial)
  152. /*
  153. * __store_partial: internal ABI
  154. * input:
  155. * %rdx - dst
  156. * %rcx - bytes
  157. * output:
  158. * T0 - message block
  159. * changed:
  160. * %r8
  161. * %r9
  162. * %r10
  163. */
  164. __store_partial:
  165. mov %rcx, %r8
  166. mov %rdx, %r9
  167. cmp $16, %r8
  168. jl .Lst_partial_16
  169. movdqu T0_LOW, (%r9)
  170. vpermq $MASK2, T0, T0
  171. sub $16, %r8
  172. add $16, %r9
  173. .Lst_partial_16:
  174. movq T0_LOW, %r10
  175. cmp $8, %r8
  176. jl .Lst_partial_8
  177. mov %r10, (%r9)
  178. pextrq $1, T0_LOW, %r10
  179. sub $8, %r8
  180. add $8, %r9
  181. .Lst_partial_8:
  182. cmp $4, %r8
  183. jl .Lst_partial_4
  184. mov %r10d, (%r9)
  185. shr $32, %r10
  186. sub $4, %r8
  187. add $4, %r9
  188. .Lst_partial_4:
  189. cmp $2, %r8
  190. jl .Lst_partial_2
  191. mov %r10w, (%r9)
  192. shr $16, %r10
  193. sub $2, %r8
  194. add $2, %r9
  195. .Lst_partial_2:
  196. cmp $1, %r8
  197. jl .Lst_partial_1
  198. mov %r10b, (%r9)
  199. .Lst_partial_1:
  200. ret
  201. ENDPROC(__store_partial)
  202. /*
  203. * void crypto_morus1280_avx2_init(void *state, const void *key,
  204. * const void *iv);
  205. */
  206. ENTRY(crypto_morus1280_avx2_init)
  207. FRAME_BEGIN
  208. /* load IV: */
  209. vpxor STATE0, STATE0, STATE0
  210. movdqu (%rdx), STATE0_LOW
  211. /* load key: */
  212. vmovdqu (%rsi), KEY
  213. vmovdqa KEY, STATE1
  214. /* load all ones: */
  215. vpcmpeqd STATE2, STATE2, STATE2
  216. /* load all zeros: */
  217. vpxor STATE3, STATE3, STATE3
  218. /* load the constant: */
  219. vmovdqa .Lmorus1280_const, STATE4
  220. /* update 16 times with zero: */
  221. call __morus1280_update_zero
  222. call __morus1280_update_zero
  223. call __morus1280_update_zero
  224. call __morus1280_update_zero
  225. call __morus1280_update_zero
  226. call __morus1280_update_zero
  227. call __morus1280_update_zero
  228. call __morus1280_update_zero
  229. call __morus1280_update_zero
  230. call __morus1280_update_zero
  231. call __morus1280_update_zero
  232. call __morus1280_update_zero
  233. call __morus1280_update_zero
  234. call __morus1280_update_zero
  235. call __morus1280_update_zero
  236. call __morus1280_update_zero
  237. /* xor-in the key again after updates: */
  238. vpxor KEY, STATE1, STATE1
  239. /* store the state: */
  240. vmovdqu STATE0, (0 * 32)(%rdi)
  241. vmovdqu STATE1, (1 * 32)(%rdi)
  242. vmovdqu STATE2, (2 * 32)(%rdi)
  243. vmovdqu STATE3, (3 * 32)(%rdi)
  244. vmovdqu STATE4, (4 * 32)(%rdi)
  245. FRAME_END
  246. ret
  247. ENDPROC(crypto_morus1280_avx2_init)
  248. /*
  249. * void crypto_morus1280_avx2_ad(void *state, const void *data,
  250. * unsigned int length);
  251. */
  252. ENTRY(crypto_morus1280_avx2_ad)
  253. FRAME_BEGIN
  254. cmp $32, %rdx
  255. jb .Lad_out
  256. /* load the state: */
  257. vmovdqu (0 * 32)(%rdi), STATE0
  258. vmovdqu (1 * 32)(%rdi), STATE1
  259. vmovdqu (2 * 32)(%rdi), STATE2
  260. vmovdqu (3 * 32)(%rdi), STATE3
  261. vmovdqu (4 * 32)(%rdi), STATE4
  262. mov %rsi, %r8
  263. and $0x1F, %r8
  264. jnz .Lad_u_loop
  265. .align 4
  266. .Lad_a_loop:
  267. vmovdqa (%rsi), MSG
  268. call __morus1280_update
  269. sub $32, %rdx
  270. add $32, %rsi
  271. cmp $32, %rdx
  272. jge .Lad_a_loop
  273. jmp .Lad_cont
  274. .align 4
  275. .Lad_u_loop:
  276. vmovdqu (%rsi), MSG
  277. call __morus1280_update
  278. sub $32, %rdx
  279. add $32, %rsi
  280. cmp $32, %rdx
  281. jge .Lad_u_loop
  282. .Lad_cont:
  283. /* store the state: */
  284. vmovdqu STATE0, (0 * 32)(%rdi)
  285. vmovdqu STATE1, (1 * 32)(%rdi)
  286. vmovdqu STATE2, (2 * 32)(%rdi)
  287. vmovdqu STATE3, (3 * 32)(%rdi)
  288. vmovdqu STATE4, (4 * 32)(%rdi)
  289. .Lad_out:
  290. FRAME_END
  291. ret
  292. ENDPROC(crypto_morus1280_avx2_ad)
  293. /*
  294. * void crypto_morus1280_avx2_enc(void *state, const void *src, void *dst,
  295. * unsigned int length);
  296. */
  297. ENTRY(crypto_morus1280_avx2_enc)
  298. FRAME_BEGIN
  299. cmp $32, %rcx
  300. jb .Lenc_out
  301. /* load the state: */
  302. vmovdqu (0 * 32)(%rdi), STATE0
  303. vmovdqu (1 * 32)(%rdi), STATE1
  304. vmovdqu (2 * 32)(%rdi), STATE2
  305. vmovdqu (3 * 32)(%rdi), STATE3
  306. vmovdqu (4 * 32)(%rdi), STATE4
  307. mov %rsi, %r8
  308. or %rdx, %r8
  309. and $0x1F, %r8
  310. jnz .Lenc_u_loop
  311. .align 4
  312. .Lenc_a_loop:
  313. vmovdqa (%rsi), MSG
  314. vmovdqa MSG, T0
  315. vpxor STATE0, T0, T0
  316. vpermq $MASK3, STATE1, T1
  317. vpxor T1, T0, T0
  318. vpand STATE2, STATE3, T1
  319. vpxor T1, T0, T0
  320. vmovdqa T0, (%rdx)
  321. call __morus1280_update
  322. sub $32, %rcx
  323. add $32, %rsi
  324. add $32, %rdx
  325. cmp $32, %rcx
  326. jge .Lenc_a_loop
  327. jmp .Lenc_cont
  328. .align 4
  329. .Lenc_u_loop:
  330. vmovdqu (%rsi), MSG
  331. vmovdqa MSG, T0
  332. vpxor STATE0, T0, T0
  333. vpermq $MASK3, STATE1, T1
  334. vpxor T1, T0, T0
  335. vpand STATE2, STATE3, T1
  336. vpxor T1, T0, T0
  337. vmovdqu T0, (%rdx)
  338. call __morus1280_update
  339. sub $32, %rcx
  340. add $32, %rsi
  341. add $32, %rdx
  342. cmp $32, %rcx
  343. jge .Lenc_u_loop
  344. .Lenc_cont:
  345. /* store the state: */
  346. vmovdqu STATE0, (0 * 32)(%rdi)
  347. vmovdqu STATE1, (1 * 32)(%rdi)
  348. vmovdqu STATE2, (2 * 32)(%rdi)
  349. vmovdqu STATE3, (3 * 32)(%rdi)
  350. vmovdqu STATE4, (4 * 32)(%rdi)
  351. .Lenc_out:
  352. FRAME_END
  353. ret
  354. ENDPROC(crypto_morus1280_avx2_enc)
  355. /*
  356. * void crypto_morus1280_avx2_enc_tail(void *state, const void *src, void *dst,
  357. * unsigned int length);
  358. */
  359. ENTRY(crypto_morus1280_avx2_enc_tail)
  360. FRAME_BEGIN
  361. /* load the state: */
  362. vmovdqu (0 * 32)(%rdi), STATE0
  363. vmovdqu (1 * 32)(%rdi), STATE1
  364. vmovdqu (2 * 32)(%rdi), STATE2
  365. vmovdqu (3 * 32)(%rdi), STATE3
  366. vmovdqu (4 * 32)(%rdi), STATE4
  367. /* encrypt message: */
  368. call __load_partial
  369. vmovdqa MSG, T0
  370. vpxor STATE0, T0, T0
  371. vpermq $MASK3, STATE1, T1
  372. vpxor T1, T0, T0
  373. vpand STATE2, STATE3, T1
  374. vpxor T1, T0, T0
  375. call __store_partial
  376. call __morus1280_update
  377. /* store the state: */
  378. vmovdqu STATE0, (0 * 32)(%rdi)
  379. vmovdqu STATE1, (1 * 32)(%rdi)
  380. vmovdqu STATE2, (2 * 32)(%rdi)
  381. vmovdqu STATE3, (3 * 32)(%rdi)
  382. vmovdqu STATE4, (4 * 32)(%rdi)
  383. FRAME_END
  384. ret
  385. ENDPROC(crypto_morus1280_avx2_enc_tail)
  386. /*
  387. * void crypto_morus1280_avx2_dec(void *state, const void *src, void *dst,
  388. * unsigned int length);
  389. */
  390. ENTRY(crypto_morus1280_avx2_dec)
  391. FRAME_BEGIN
  392. cmp $32, %rcx
  393. jb .Ldec_out
  394. /* load the state: */
  395. vmovdqu (0 * 32)(%rdi), STATE0
  396. vmovdqu (1 * 32)(%rdi), STATE1
  397. vmovdqu (2 * 32)(%rdi), STATE2
  398. vmovdqu (3 * 32)(%rdi), STATE3
  399. vmovdqu (4 * 32)(%rdi), STATE4
  400. mov %rsi, %r8
  401. or %rdx, %r8
  402. and $0x1F, %r8
  403. jnz .Ldec_u_loop
  404. .align 4
  405. .Ldec_a_loop:
  406. vmovdqa (%rsi), MSG
  407. vpxor STATE0, MSG, MSG
  408. vpermq $MASK3, STATE1, T0
  409. vpxor T0, MSG, MSG
  410. vpand STATE2, STATE3, T0
  411. vpxor T0, MSG, MSG
  412. vmovdqa MSG, (%rdx)
  413. call __morus1280_update
  414. sub $32, %rcx
  415. add $32, %rsi
  416. add $32, %rdx
  417. cmp $32, %rcx
  418. jge .Ldec_a_loop
  419. jmp .Ldec_cont
  420. .align 4
  421. .Ldec_u_loop:
  422. vmovdqu (%rsi), MSG
  423. vpxor STATE0, MSG, MSG
  424. vpermq $MASK3, STATE1, T0
  425. vpxor T0, MSG, MSG
  426. vpand STATE2, STATE3, T0
  427. vpxor T0, MSG, MSG
  428. vmovdqu MSG, (%rdx)
  429. call __morus1280_update
  430. sub $32, %rcx
  431. add $32, %rsi
  432. add $32, %rdx
  433. cmp $32, %rcx
  434. jge .Ldec_u_loop
  435. .Ldec_cont:
  436. /* store the state: */
  437. vmovdqu STATE0, (0 * 32)(%rdi)
  438. vmovdqu STATE1, (1 * 32)(%rdi)
  439. vmovdqu STATE2, (2 * 32)(%rdi)
  440. vmovdqu STATE3, (3 * 32)(%rdi)
  441. vmovdqu STATE4, (4 * 32)(%rdi)
  442. .Ldec_out:
  443. FRAME_END
  444. ret
  445. ENDPROC(crypto_morus1280_avx2_dec)
  446. /*
  447. * void crypto_morus1280_avx2_dec_tail(void *state, const void *src, void *dst,
  448. * unsigned int length);
  449. */
  450. ENTRY(crypto_morus1280_avx2_dec_tail)
  451. FRAME_BEGIN
  452. /* load the state: */
  453. vmovdqu (0 * 32)(%rdi), STATE0
  454. vmovdqu (1 * 32)(%rdi), STATE1
  455. vmovdqu (2 * 32)(%rdi), STATE2
  456. vmovdqu (3 * 32)(%rdi), STATE3
  457. vmovdqu (4 * 32)(%rdi), STATE4
  458. /* decrypt message: */
  459. call __load_partial
  460. vpxor STATE0, MSG, MSG
  461. vpermq $MASK3, STATE1, T0
  462. vpxor T0, MSG, MSG
  463. vpand STATE2, STATE3, T0
  464. vpxor T0, MSG, MSG
  465. vmovdqa MSG, T0
  466. call __store_partial
  467. /* mask with byte count: */
  468. movq %rcx, T0_LOW
  469. vpbroadcastb T0_LOW, T0
  470. vmovdqa .Lmorus1280_counter, T1
  471. vpcmpgtb T1, T0, T0
  472. vpand T0, MSG, MSG
  473. call __morus1280_update
  474. /* store the state: */
  475. vmovdqu STATE0, (0 * 32)(%rdi)
  476. vmovdqu STATE1, (1 * 32)(%rdi)
  477. vmovdqu STATE2, (2 * 32)(%rdi)
  478. vmovdqu STATE3, (3 * 32)(%rdi)
  479. vmovdqu STATE4, (4 * 32)(%rdi)
  480. FRAME_END
  481. ret
  482. ENDPROC(crypto_morus1280_avx2_dec_tail)
  483. /*
  484. * void crypto_morus1280_avx2_final(void *state, void *tag_xor,
  485. * u64 assoclen, u64 cryptlen);
  486. */
  487. ENTRY(crypto_morus1280_avx2_final)
  488. FRAME_BEGIN
  489. /* load the state: */
  490. vmovdqu (0 * 32)(%rdi), STATE0
  491. vmovdqu (1 * 32)(%rdi), STATE1
  492. vmovdqu (2 * 32)(%rdi), STATE2
  493. vmovdqu (3 * 32)(%rdi), STATE3
  494. vmovdqu (4 * 32)(%rdi), STATE4
  495. /* xor state[0] into state[4]: */
  496. vpxor STATE0, STATE4, STATE4
  497. /* prepare length block: */
  498. vpxor MSG, MSG, MSG
  499. vpinsrq $0, %rdx, MSG_LOW, MSG_LOW
  500. vpinsrq $1, %rcx, MSG_LOW, MSG_LOW
  501. vpsllq $3, MSG, MSG /* multiply by 8 (to get bit count) */
  502. /* update state: */
  503. call __morus1280_update
  504. call __morus1280_update
  505. call __morus1280_update
  506. call __morus1280_update
  507. call __morus1280_update
  508. call __morus1280_update
  509. call __morus1280_update
  510. call __morus1280_update
  511. call __morus1280_update
  512. call __morus1280_update
  513. /* xor tag: */
  514. vmovdqu (%rsi), MSG
  515. vpxor STATE0, MSG, MSG
  516. vpermq $MASK3, STATE1, T0
  517. vpxor T0, MSG, MSG
  518. vpand STATE2, STATE3, T0
  519. vpxor T0, MSG, MSG
  520. vmovdqu MSG, (%rsi)
  521. FRAME_END
  522. ret
  523. ENDPROC(crypto_morus1280_avx2_final)