speck-neon-core.S 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * NEON-accelerated implementation of Speck128-XTS and Speck64-XTS
  4. *
  5. * Copyright (c) 2018 Google, Inc
  6. *
  7. * Author: Eric Biggers <ebiggers@google.com>
  8. */
  9. #include <linux/linkage.h>
  10. .text
  11. .fpu neon
  12. // arguments
  13. ROUND_KEYS .req r0 // const {u64,u32} *round_keys
  14. NROUNDS .req r1 // int nrounds
  15. DST .req r2 // void *dst
  16. SRC .req r3 // const void *src
  17. NBYTES .req r4 // unsigned int nbytes
  18. TWEAK .req r5 // void *tweak
  19. // registers which hold the data being encrypted/decrypted
  20. X0 .req q0
  21. X0_L .req d0
  22. X0_H .req d1
  23. Y0 .req q1
  24. Y0_H .req d3
  25. X1 .req q2
  26. X1_L .req d4
  27. X1_H .req d5
  28. Y1 .req q3
  29. Y1_H .req d7
  30. X2 .req q4
  31. X2_L .req d8
  32. X2_H .req d9
  33. Y2 .req q5
  34. Y2_H .req d11
  35. X3 .req q6
  36. X3_L .req d12
  37. X3_H .req d13
  38. Y3 .req q7
  39. Y3_H .req d15
  40. // the round key, duplicated in all lanes
  41. ROUND_KEY .req q8
  42. ROUND_KEY_L .req d16
  43. ROUND_KEY_H .req d17
  44. // index vector for vtbl-based 8-bit rotates
  45. ROTATE_TABLE .req d18
  46. // multiplication table for updating XTS tweaks
  47. GF128MUL_TABLE .req d19
  48. GF64MUL_TABLE .req d19
  49. // current XTS tweak value(s)
  50. TWEAKV .req q10
  51. TWEAKV_L .req d20
  52. TWEAKV_H .req d21
  53. TMP0 .req q12
  54. TMP0_L .req d24
  55. TMP0_H .req d25
  56. TMP1 .req q13
  57. TMP2 .req q14
  58. TMP3 .req q15
  59. .align 4
  60. .Lror64_8_table:
  61. .byte 1, 2, 3, 4, 5, 6, 7, 0
  62. .Lror32_8_table:
  63. .byte 1, 2, 3, 0, 5, 6, 7, 4
  64. .Lrol64_8_table:
  65. .byte 7, 0, 1, 2, 3, 4, 5, 6
  66. .Lrol32_8_table:
  67. .byte 3, 0, 1, 2, 7, 4, 5, 6
  68. .Lgf128mul_table:
  69. .byte 0, 0x87
  70. .fill 14
  71. .Lgf64mul_table:
  72. .byte 0, 0x1b, (0x1b << 1), (0x1b << 1) ^ 0x1b
  73. .fill 12
  74. /*
  75. * _speck_round_128bytes() - Speck encryption round on 128 bytes at a time
  76. *
  77. * Do one Speck encryption round on the 128 bytes (8 blocks for Speck128, 16 for
  78. * Speck64) stored in X0-X3 and Y0-Y3, using the round key stored in all lanes
  79. * of ROUND_KEY. 'n' is the lane size: 64 for Speck128, or 32 for Speck64.
  80. *
  81. * The 8-bit rotates are implemented using vtbl instead of vshr + vsli because
  82. * the vtbl approach is faster on some processors and the same speed on others.
  83. */
  84. .macro _speck_round_128bytes n
  85. // x = ror(x, 8)
  86. vtbl.8 X0_L, {X0_L}, ROTATE_TABLE
  87. vtbl.8 X0_H, {X0_H}, ROTATE_TABLE
  88. vtbl.8 X1_L, {X1_L}, ROTATE_TABLE
  89. vtbl.8 X1_H, {X1_H}, ROTATE_TABLE
  90. vtbl.8 X2_L, {X2_L}, ROTATE_TABLE
  91. vtbl.8 X2_H, {X2_H}, ROTATE_TABLE
  92. vtbl.8 X3_L, {X3_L}, ROTATE_TABLE
  93. vtbl.8 X3_H, {X3_H}, ROTATE_TABLE
  94. // x += y
  95. vadd.u\n X0, Y0
  96. vadd.u\n X1, Y1
  97. vadd.u\n X2, Y2
  98. vadd.u\n X3, Y3
  99. // x ^= k
  100. veor X0, ROUND_KEY
  101. veor X1, ROUND_KEY
  102. veor X2, ROUND_KEY
  103. veor X3, ROUND_KEY
  104. // y = rol(y, 3)
  105. vshl.u\n TMP0, Y0, #3
  106. vshl.u\n TMP1, Y1, #3
  107. vshl.u\n TMP2, Y2, #3
  108. vshl.u\n TMP3, Y3, #3
  109. vsri.u\n TMP0, Y0, #(\n - 3)
  110. vsri.u\n TMP1, Y1, #(\n - 3)
  111. vsri.u\n TMP2, Y2, #(\n - 3)
  112. vsri.u\n TMP3, Y3, #(\n - 3)
  113. // y ^= x
  114. veor Y0, TMP0, X0
  115. veor Y1, TMP1, X1
  116. veor Y2, TMP2, X2
  117. veor Y3, TMP3, X3
  118. .endm
  119. /*
  120. * _speck_unround_128bytes() - Speck decryption round on 128 bytes at a time
  121. *
  122. * This is the inverse of _speck_round_128bytes().
  123. */
  124. .macro _speck_unround_128bytes n
  125. // y ^= x
  126. veor TMP0, Y0, X0
  127. veor TMP1, Y1, X1
  128. veor TMP2, Y2, X2
  129. veor TMP3, Y3, X3
  130. // y = ror(y, 3)
  131. vshr.u\n Y0, TMP0, #3
  132. vshr.u\n Y1, TMP1, #3
  133. vshr.u\n Y2, TMP2, #3
  134. vshr.u\n Y3, TMP3, #3
  135. vsli.u\n Y0, TMP0, #(\n - 3)
  136. vsli.u\n Y1, TMP1, #(\n - 3)
  137. vsli.u\n Y2, TMP2, #(\n - 3)
  138. vsli.u\n Y3, TMP3, #(\n - 3)
  139. // x ^= k
  140. veor X0, ROUND_KEY
  141. veor X1, ROUND_KEY
  142. veor X2, ROUND_KEY
  143. veor X3, ROUND_KEY
  144. // x -= y
  145. vsub.u\n X0, Y0
  146. vsub.u\n X1, Y1
  147. vsub.u\n X2, Y2
  148. vsub.u\n X3, Y3
  149. // x = rol(x, 8);
  150. vtbl.8 X0_L, {X0_L}, ROTATE_TABLE
  151. vtbl.8 X0_H, {X0_H}, ROTATE_TABLE
  152. vtbl.8 X1_L, {X1_L}, ROTATE_TABLE
  153. vtbl.8 X1_H, {X1_H}, ROTATE_TABLE
  154. vtbl.8 X2_L, {X2_L}, ROTATE_TABLE
  155. vtbl.8 X2_H, {X2_H}, ROTATE_TABLE
  156. vtbl.8 X3_L, {X3_L}, ROTATE_TABLE
  157. vtbl.8 X3_H, {X3_H}, ROTATE_TABLE
  158. .endm
  159. .macro _xts128_precrypt_one dst_reg, tweak_buf, tmp
  160. // Load the next source block
  161. vld1.8 {\dst_reg}, [SRC]!
  162. // Save the current tweak in the tweak buffer
  163. vst1.8 {TWEAKV}, [\tweak_buf:128]!
  164. // XOR the next source block with the current tweak
  165. veor \dst_reg, TWEAKV
  166. /*
  167. * Calculate the next tweak by multiplying the current one by x,
  168. * modulo p(x) = x^128 + x^7 + x^2 + x + 1.
  169. */
  170. vshr.u64 \tmp, TWEAKV, #63
  171. vshl.u64 TWEAKV, #1
  172. veor TWEAKV_H, \tmp\()_L
  173. vtbl.8 \tmp\()_H, {GF128MUL_TABLE}, \tmp\()_H
  174. veor TWEAKV_L, \tmp\()_H
  175. .endm
  176. .macro _xts64_precrypt_two dst_reg, tweak_buf, tmp
  177. // Load the next two source blocks
  178. vld1.8 {\dst_reg}, [SRC]!
  179. // Save the current two tweaks in the tweak buffer
  180. vst1.8 {TWEAKV}, [\tweak_buf:128]!
  181. // XOR the next two source blocks with the current two tweaks
  182. veor \dst_reg, TWEAKV
  183. /*
  184. * Calculate the next two tweaks by multiplying the current ones by x^2,
  185. * modulo p(x) = x^64 + x^4 + x^3 + x + 1.
  186. */
  187. vshr.u64 \tmp, TWEAKV, #62
  188. vshl.u64 TWEAKV, #2
  189. vtbl.8 \tmp\()_L, {GF64MUL_TABLE}, \tmp\()_L
  190. vtbl.8 \tmp\()_H, {GF64MUL_TABLE}, \tmp\()_H
  191. veor TWEAKV, \tmp
  192. .endm
  193. /*
  194. * _speck_xts_crypt() - Speck-XTS encryption/decryption
  195. *
  196. * Encrypt or decrypt NBYTES bytes of data from the SRC buffer to the DST buffer
  197. * using Speck-XTS, specifically the variant with a block size of '2n' and round
  198. * count given by NROUNDS. The expanded round keys are given in ROUND_KEYS, and
  199. * the current XTS tweak value is given in TWEAK. It's assumed that NBYTES is a
  200. * nonzero multiple of 128.
  201. */
  202. .macro _speck_xts_crypt n, decrypting
  203. push {r4-r7}
  204. mov r7, sp
  205. /*
  206. * The first four parameters were passed in registers r0-r3. Load the
  207. * additional parameters, which were passed on the stack.
  208. */
  209. ldr NBYTES, [sp, #16]
  210. ldr TWEAK, [sp, #20]
  211. /*
  212. * If decrypting, modify the ROUND_KEYS parameter to point to the last
  213. * round key rather than the first, since for decryption the round keys
  214. * are used in reverse order.
  215. */
  216. .if \decrypting
  217. .if \n == 64
  218. add ROUND_KEYS, ROUND_KEYS, NROUNDS, lsl #3
  219. sub ROUND_KEYS, #8
  220. .else
  221. add ROUND_KEYS, ROUND_KEYS, NROUNDS, lsl #2
  222. sub ROUND_KEYS, #4
  223. .endif
  224. .endif
  225. // Load the index vector for vtbl-based 8-bit rotates
  226. .if \decrypting
  227. ldr r12, =.Lrol\n\()_8_table
  228. .else
  229. ldr r12, =.Lror\n\()_8_table
  230. .endif
  231. vld1.8 {ROTATE_TABLE}, [r12:64]
  232. // One-time XTS preparation
  233. /*
  234. * Allocate stack space to store 128 bytes worth of tweaks. For
  235. * performance, this space is aligned to a 16-byte boundary so that we
  236. * can use the load/store instructions that declare 16-byte alignment.
  237. */
  238. sub sp, #128
  239. bic sp, #0xf
  240. .if \n == 64
  241. // Load first tweak
  242. vld1.8 {TWEAKV}, [TWEAK]
  243. // Load GF(2^128) multiplication table
  244. ldr r12, =.Lgf128mul_table
  245. vld1.8 {GF128MUL_TABLE}, [r12:64]
  246. .else
  247. // Load first tweak
  248. vld1.8 {TWEAKV_L}, [TWEAK]
  249. // Load GF(2^64) multiplication table
  250. ldr r12, =.Lgf64mul_table
  251. vld1.8 {GF64MUL_TABLE}, [r12:64]
  252. // Calculate second tweak, packing it together with the first
  253. vshr.u64 TMP0_L, TWEAKV_L, #63
  254. vtbl.u8 TMP0_L, {GF64MUL_TABLE}, TMP0_L
  255. vshl.u64 TWEAKV_H, TWEAKV_L, #1
  256. veor TWEAKV_H, TMP0_L
  257. .endif
  258. .Lnext_128bytes_\@:
  259. /*
  260. * Load the source blocks into {X,Y}[0-3], XOR them with their XTS tweak
  261. * values, and save the tweaks on the stack for later. Then
  262. * de-interleave the 'x' and 'y' elements of each block, i.e. make it so
  263. * that the X[0-3] registers contain only the second halves of blocks,
  264. * and the Y[0-3] registers contain only the first halves of blocks.
  265. * (Speck uses the order (y, x) rather than the more intuitive (x, y).)
  266. */
  267. mov r12, sp
  268. .if \n == 64
  269. _xts128_precrypt_one X0, r12, TMP0
  270. _xts128_precrypt_one Y0, r12, TMP0
  271. _xts128_precrypt_one X1, r12, TMP0
  272. _xts128_precrypt_one Y1, r12, TMP0
  273. _xts128_precrypt_one X2, r12, TMP0
  274. _xts128_precrypt_one Y2, r12, TMP0
  275. _xts128_precrypt_one X3, r12, TMP0
  276. _xts128_precrypt_one Y3, r12, TMP0
  277. vswp X0_L, Y0_H
  278. vswp X1_L, Y1_H
  279. vswp X2_L, Y2_H
  280. vswp X3_L, Y3_H
  281. .else
  282. _xts64_precrypt_two X0, r12, TMP0
  283. _xts64_precrypt_two Y0, r12, TMP0
  284. _xts64_precrypt_two X1, r12, TMP0
  285. _xts64_precrypt_two Y1, r12, TMP0
  286. _xts64_precrypt_two X2, r12, TMP0
  287. _xts64_precrypt_two Y2, r12, TMP0
  288. _xts64_precrypt_two X3, r12, TMP0
  289. _xts64_precrypt_two Y3, r12, TMP0
  290. vuzp.32 Y0, X0
  291. vuzp.32 Y1, X1
  292. vuzp.32 Y2, X2
  293. vuzp.32 Y3, X3
  294. .endif
  295. // Do the cipher rounds
  296. mov r12, ROUND_KEYS
  297. mov r6, NROUNDS
  298. .Lnext_round_\@:
  299. .if \decrypting
  300. .if \n == 64
  301. vld1.64 ROUND_KEY_L, [r12]
  302. sub r12, #8
  303. vmov ROUND_KEY_H, ROUND_KEY_L
  304. .else
  305. vld1.32 {ROUND_KEY_L[],ROUND_KEY_H[]}, [r12]
  306. sub r12, #4
  307. .endif
  308. _speck_unround_128bytes \n
  309. .else
  310. .if \n == 64
  311. vld1.64 ROUND_KEY_L, [r12]!
  312. vmov ROUND_KEY_H, ROUND_KEY_L
  313. .else
  314. vld1.32 {ROUND_KEY_L[],ROUND_KEY_H[]}, [r12]!
  315. .endif
  316. _speck_round_128bytes \n
  317. .endif
  318. subs r6, r6, #1
  319. bne .Lnext_round_\@
  320. // Re-interleave the 'x' and 'y' elements of each block
  321. .if \n == 64
  322. vswp X0_L, Y0_H
  323. vswp X1_L, Y1_H
  324. vswp X2_L, Y2_H
  325. vswp X3_L, Y3_H
  326. .else
  327. vzip.32 Y0, X0
  328. vzip.32 Y1, X1
  329. vzip.32 Y2, X2
  330. vzip.32 Y3, X3
  331. .endif
  332. // XOR the encrypted/decrypted blocks with the tweaks we saved earlier
  333. mov r12, sp
  334. vld1.8 {TMP0, TMP1}, [r12:128]!
  335. vld1.8 {TMP2, TMP3}, [r12:128]!
  336. veor X0, TMP0
  337. veor Y0, TMP1
  338. veor X1, TMP2
  339. veor Y1, TMP3
  340. vld1.8 {TMP0, TMP1}, [r12:128]!
  341. vld1.8 {TMP2, TMP3}, [r12:128]!
  342. veor X2, TMP0
  343. veor Y2, TMP1
  344. veor X3, TMP2
  345. veor Y3, TMP3
  346. // Store the ciphertext in the destination buffer
  347. vst1.8 {X0, Y0}, [DST]!
  348. vst1.8 {X1, Y1}, [DST]!
  349. vst1.8 {X2, Y2}, [DST]!
  350. vst1.8 {X3, Y3}, [DST]!
  351. // Continue if there are more 128-byte chunks remaining, else return
  352. subs NBYTES, #128
  353. bne .Lnext_128bytes_\@
  354. // Store the next tweak
  355. .if \n == 64
  356. vst1.8 {TWEAKV}, [TWEAK]
  357. .else
  358. vst1.8 {TWEAKV_L}, [TWEAK]
  359. .endif
  360. mov sp, r7
  361. pop {r4-r7}
  362. bx lr
  363. .endm
  364. ENTRY(speck128_xts_encrypt_neon)
  365. _speck_xts_crypt n=64, decrypting=0
  366. ENDPROC(speck128_xts_encrypt_neon)
  367. ENTRY(speck128_xts_decrypt_neon)
  368. _speck_xts_crypt n=64, decrypting=1
  369. ENDPROC(speck128_xts_decrypt_neon)
  370. ENTRY(speck64_xts_encrypt_neon)
  371. _speck_xts_crypt n=32, decrypting=0
  372. ENDPROC(speck64_xts_encrypt_neon)
  373. ENTRY(speck64_xts_decrypt_neon)
  374. _speck_xts_crypt n=32, decrypting=1
  375. ENDPROC(speck64_xts_decrypt_neon)