aegis128-aesni-asm.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * AES-NI + SSE4.1 implementation of AEGIS-128
  4. *
  5. * Copyright (c) 2017-2018 Ondrej Mosnacek <omosnacek@gmail.com>
  6. * Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
  7. * Copyright 2024 Google LLC
  8. */
  9. #include <linux/linkage.h>
  10. #define STATE0 %xmm0
  11. #define STATE1 %xmm1
  12. #define STATE2 %xmm2
  13. #define STATE3 %xmm3
  14. #define STATE4 %xmm4
  15. #define KEY %xmm5
  16. #define MSG %xmm5
  17. #define T0 %xmm6
  18. #define T1 %xmm7
  19. .section .rodata.cst16.aegis128_const, "aM", @progbits, 32
  20. .align 16
  21. .Laegis128_const_0:
  22. .byte 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d
  23. .byte 0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62
  24. .Laegis128_const_1:
  25. .byte 0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1
  26. .byte 0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd
  27. .section .rodata.cst32.zeropad_mask, "aM", @progbits, 32
  28. .align 32
  29. .Lzeropad_mask:
  30. .octa 0xffffffffffffffffffffffffffffffff
  31. .octa 0
  32. .text
  33. /*
  34. * aegis128_update
  35. * input:
  36. * STATE[0-4] - input state
  37. * output:
  38. * STATE[0-4] - output state (shifted positions)
  39. * changed:
  40. * T0
  41. */
  42. .macro aegis128_update
  43. movdqa STATE4, T0
  44. aesenc STATE0, STATE4
  45. aesenc STATE1, STATE0
  46. aesenc STATE2, STATE1
  47. aesenc STATE3, STATE2
  48. aesenc T0, STATE3
  49. .endm
  50. /*
  51. * Load 1 <= LEN (%ecx) <= 15 bytes from the pointer SRC into the xmm register
  52. * MSG and zeroize any remaining bytes. Clobbers %rax, %rcx, and %r8.
  53. */
  54. .macro load_partial
  55. sub $8, %ecx /* LEN - 8 */
  56. jle .Lle8\@
  57. /* Load 9 <= LEN <= 15 bytes: */
  58. movq (SRC), MSG /* Load first 8 bytes */
  59. mov (SRC, %rcx), %rax /* Load last 8 bytes */
  60. neg %ecx
  61. shl $3, %ecx
  62. shr %cl, %rax /* Discard overlapping bytes */
  63. pinsrq $1, %rax, MSG
  64. jmp .Ldone\@
  65. .Lle8\@:
  66. add $4, %ecx /* LEN - 4 */
  67. jl .Llt4\@
  68. /* Load 4 <= LEN <= 8 bytes: */
  69. mov (SRC), %eax /* Load first 4 bytes */
  70. mov (SRC, %rcx), %r8d /* Load last 4 bytes */
  71. jmp .Lcombine\@
  72. .Llt4\@:
  73. /* Load 1 <= LEN <= 3 bytes: */
  74. add $2, %ecx /* LEN - 2 */
  75. movzbl (SRC), %eax /* Load first byte */
  76. jl .Lmovq\@
  77. movzwl (SRC, %rcx), %r8d /* Load last 2 bytes */
  78. .Lcombine\@:
  79. shl $3, %ecx
  80. shl %cl, %r8
  81. or %r8, %rax /* Combine the two parts */
  82. .Lmovq\@:
  83. movq %rax, MSG
  84. .Ldone\@:
  85. .endm
  86. /*
  87. * Store 1 <= LEN (%ecx) <= 15 bytes from the xmm register \msg to the pointer
  88. * DST. Clobbers %rax, %rcx, and %r8.
  89. */
  90. .macro store_partial msg
  91. sub $8, %ecx /* LEN - 8 */
  92. jl .Llt8\@
  93. /* Store 8 <= LEN <= 15 bytes: */
  94. pextrq $1, \msg, %rax
  95. mov %ecx, %r8d
  96. shl $3, %ecx
  97. ror %cl, %rax
  98. mov %rax, (DST, %r8) /* Store last LEN - 8 bytes */
  99. movq \msg, (DST) /* Store first 8 bytes */
  100. jmp .Ldone\@
  101. .Llt8\@:
  102. add $4, %ecx /* LEN - 4 */
  103. jl .Llt4\@
  104. /* Store 4 <= LEN <= 7 bytes: */
  105. pextrd $1, \msg, %eax
  106. mov %ecx, %r8d
  107. shl $3, %ecx
  108. ror %cl, %eax
  109. mov %eax, (DST, %r8) /* Store last LEN - 4 bytes */
  110. movd \msg, (DST) /* Store first 4 bytes */
  111. jmp .Ldone\@
  112. .Llt4\@:
  113. /* Store 1 <= LEN <= 3 bytes: */
  114. pextrb $0, \msg, 0(DST)
  115. cmp $-2, %ecx /* LEN - 4 == -2, i.e. LEN == 2? */
  116. jl .Ldone\@
  117. pextrb $1, \msg, 1(DST)
  118. je .Ldone\@
  119. pextrb $2, \msg, 2(DST)
  120. .Ldone\@:
  121. .endm
  122. /*
  123. * void aegis128_aesni_init(struct aegis_state *state,
  124. * const struct aegis_block *key,
  125. * const u8 iv[AEGIS128_NONCE_SIZE]);
  126. */
  127. SYM_FUNC_START(aegis128_aesni_init)
  128. .set STATEP, %rdi
  129. .set KEYP, %rsi
  130. .set IVP, %rdx
  131. /* load IV: */
  132. movdqu (IVP), T1
  133. /* load key: */
  134. movdqa (KEYP), KEY
  135. pxor KEY, T1
  136. movdqa T1, STATE0
  137. movdqa KEY, STATE3
  138. movdqa KEY, STATE4
  139. /* load the constants: */
  140. movdqa .Laegis128_const_0(%rip), STATE2
  141. movdqa .Laegis128_const_1(%rip), STATE1
  142. pxor STATE2, STATE3
  143. pxor STATE1, STATE4
  144. /* update 10 times with KEY / KEY xor IV: */
  145. aegis128_update; pxor KEY, STATE4
  146. aegis128_update; pxor T1, STATE3
  147. aegis128_update; pxor KEY, STATE2
  148. aegis128_update; pxor T1, STATE1
  149. aegis128_update; pxor KEY, STATE0
  150. aegis128_update; pxor T1, STATE4
  151. aegis128_update; pxor KEY, STATE3
  152. aegis128_update; pxor T1, STATE2
  153. aegis128_update; pxor KEY, STATE1
  154. aegis128_update; pxor T1, STATE0
  155. /* store the state: */
  156. movdqu STATE0, 0x00(STATEP)
  157. movdqu STATE1, 0x10(STATEP)
  158. movdqu STATE2, 0x20(STATEP)
  159. movdqu STATE3, 0x30(STATEP)
  160. movdqu STATE4, 0x40(STATEP)
  161. RET
  162. SYM_FUNC_END(aegis128_aesni_init)
  163. /*
  164. * void aegis128_aesni_ad(struct aegis_state *state, const u8 *data,
  165. * unsigned int len);
  166. *
  167. * len must be a multiple of 16.
  168. */
  169. SYM_FUNC_START(aegis128_aesni_ad)
  170. .set STATEP, %rdi
  171. .set SRC, %rsi
  172. .set LEN, %edx
  173. test LEN, LEN
  174. jz .Lad_out
  175. /* load the state: */
  176. movdqu 0x00(STATEP), STATE0
  177. movdqu 0x10(STATEP), STATE1
  178. movdqu 0x20(STATEP), STATE2
  179. movdqu 0x30(STATEP), STATE3
  180. movdqu 0x40(STATEP), STATE4
  181. .align 8
  182. .Lad_loop:
  183. movdqu 0x00(SRC), MSG
  184. aegis128_update
  185. pxor MSG, STATE4
  186. sub $0x10, LEN
  187. jz .Lad_out_1
  188. movdqu 0x10(SRC), MSG
  189. aegis128_update
  190. pxor MSG, STATE3
  191. sub $0x10, LEN
  192. jz .Lad_out_2
  193. movdqu 0x20(SRC), MSG
  194. aegis128_update
  195. pxor MSG, STATE2
  196. sub $0x10, LEN
  197. jz .Lad_out_3
  198. movdqu 0x30(SRC), MSG
  199. aegis128_update
  200. pxor MSG, STATE1
  201. sub $0x10, LEN
  202. jz .Lad_out_4
  203. movdqu 0x40(SRC), MSG
  204. aegis128_update
  205. pxor MSG, STATE0
  206. sub $0x10, LEN
  207. jz .Lad_out_0
  208. add $0x50, SRC
  209. jmp .Lad_loop
  210. /* store the state: */
  211. .Lad_out_0:
  212. movdqu STATE0, 0x00(STATEP)
  213. movdqu STATE1, 0x10(STATEP)
  214. movdqu STATE2, 0x20(STATEP)
  215. movdqu STATE3, 0x30(STATEP)
  216. movdqu STATE4, 0x40(STATEP)
  217. RET
  218. .Lad_out_1:
  219. movdqu STATE4, 0x00(STATEP)
  220. movdqu STATE0, 0x10(STATEP)
  221. movdqu STATE1, 0x20(STATEP)
  222. movdqu STATE2, 0x30(STATEP)
  223. movdqu STATE3, 0x40(STATEP)
  224. RET
  225. .Lad_out_2:
  226. movdqu STATE3, 0x00(STATEP)
  227. movdqu STATE4, 0x10(STATEP)
  228. movdqu STATE0, 0x20(STATEP)
  229. movdqu STATE1, 0x30(STATEP)
  230. movdqu STATE2, 0x40(STATEP)
  231. RET
  232. .Lad_out_3:
  233. movdqu STATE2, 0x00(STATEP)
  234. movdqu STATE3, 0x10(STATEP)
  235. movdqu STATE4, 0x20(STATEP)
  236. movdqu STATE0, 0x30(STATEP)
  237. movdqu STATE1, 0x40(STATEP)
  238. RET
  239. .Lad_out_4:
  240. movdqu STATE1, 0x00(STATEP)
  241. movdqu STATE2, 0x10(STATEP)
  242. movdqu STATE3, 0x20(STATEP)
  243. movdqu STATE4, 0x30(STATEP)
  244. movdqu STATE0, 0x40(STATEP)
  245. .Lad_out:
  246. RET
  247. SYM_FUNC_END(aegis128_aesni_ad)
  248. .macro encrypt_block s0 s1 s2 s3 s4 i
  249. movdqu (\i * 0x10)(SRC), MSG
  250. movdqa MSG, T0
  251. pxor \s1, T0
  252. pxor \s4, T0
  253. movdqa \s2, T1
  254. pand \s3, T1
  255. pxor T1, T0
  256. movdqu T0, (\i * 0x10)(DST)
  257. aegis128_update
  258. pxor MSG, \s4
  259. sub $0x10, LEN
  260. jz .Lenc_out_\i
  261. .endm
  262. /*
  263. * void aegis128_aesni_enc(struct aegis_state *state, const u8 *src, u8 *dst,
  264. * unsigned int len);
  265. *
  266. * len must be nonzero and a multiple of 16.
  267. */
  268. SYM_FUNC_START(aegis128_aesni_enc)
  269. .set STATEP, %rdi
  270. .set SRC, %rsi
  271. .set DST, %rdx
  272. .set LEN, %ecx
  273. /* load the state: */
  274. movdqu 0x00(STATEP), STATE0
  275. movdqu 0x10(STATEP), STATE1
  276. movdqu 0x20(STATEP), STATE2
  277. movdqu 0x30(STATEP), STATE3
  278. movdqu 0x40(STATEP), STATE4
  279. .align 8
  280. .Lenc_loop:
  281. encrypt_block STATE0 STATE1 STATE2 STATE3 STATE4 0
  282. encrypt_block STATE4 STATE0 STATE1 STATE2 STATE3 1
  283. encrypt_block STATE3 STATE4 STATE0 STATE1 STATE2 2
  284. encrypt_block STATE2 STATE3 STATE4 STATE0 STATE1 3
  285. encrypt_block STATE1 STATE2 STATE3 STATE4 STATE0 4
  286. add $0x50, SRC
  287. add $0x50, DST
  288. jmp .Lenc_loop
  289. /* store the state: */
  290. .Lenc_out_0:
  291. movdqu STATE4, 0x00(STATEP)
  292. movdqu STATE0, 0x10(STATEP)
  293. movdqu STATE1, 0x20(STATEP)
  294. movdqu STATE2, 0x30(STATEP)
  295. movdqu STATE3, 0x40(STATEP)
  296. RET
  297. .Lenc_out_1:
  298. movdqu STATE3, 0x00(STATEP)
  299. movdqu STATE4, 0x10(STATEP)
  300. movdqu STATE0, 0x20(STATEP)
  301. movdqu STATE1, 0x30(STATEP)
  302. movdqu STATE2, 0x40(STATEP)
  303. RET
  304. .Lenc_out_2:
  305. movdqu STATE2, 0x00(STATEP)
  306. movdqu STATE3, 0x10(STATEP)
  307. movdqu STATE4, 0x20(STATEP)
  308. movdqu STATE0, 0x30(STATEP)
  309. movdqu STATE1, 0x40(STATEP)
  310. RET
  311. .Lenc_out_3:
  312. movdqu STATE1, 0x00(STATEP)
  313. movdqu STATE2, 0x10(STATEP)
  314. movdqu STATE3, 0x20(STATEP)
  315. movdqu STATE4, 0x30(STATEP)
  316. movdqu STATE0, 0x40(STATEP)
  317. RET
  318. .Lenc_out_4:
  319. movdqu STATE0, 0x00(STATEP)
  320. movdqu STATE1, 0x10(STATEP)
  321. movdqu STATE2, 0x20(STATEP)
  322. movdqu STATE3, 0x30(STATEP)
  323. movdqu STATE4, 0x40(STATEP)
  324. .Lenc_out:
  325. RET
  326. SYM_FUNC_END(aegis128_aesni_enc)
  327. /*
  328. * void aegis128_aesni_enc_tail(struct aegis_state *state, const u8 *src,
  329. * u8 *dst, unsigned int len);
  330. */
  331. SYM_FUNC_START(aegis128_aesni_enc_tail)
  332. .set STATEP, %rdi
  333. .set SRC, %rsi
  334. .set DST, %rdx
  335. .set LEN, %ecx /* {load,store}_partial rely on this being %ecx */
  336. /* load the state: */
  337. movdqu 0x00(STATEP), STATE0
  338. movdqu 0x10(STATEP), STATE1
  339. movdqu 0x20(STATEP), STATE2
  340. movdqu 0x30(STATEP), STATE3
  341. movdqu 0x40(STATEP), STATE4
  342. /* encrypt message: */
  343. mov LEN, %r9d
  344. load_partial
  345. movdqa MSG, T0
  346. pxor STATE1, T0
  347. pxor STATE4, T0
  348. movdqa STATE2, T1
  349. pand STATE3, T1
  350. pxor T1, T0
  351. mov %r9d, LEN
  352. store_partial T0
  353. aegis128_update
  354. pxor MSG, STATE4
  355. /* store the state: */
  356. movdqu STATE4, 0x00(STATEP)
  357. movdqu STATE0, 0x10(STATEP)
  358. movdqu STATE1, 0x20(STATEP)
  359. movdqu STATE2, 0x30(STATEP)
  360. movdqu STATE3, 0x40(STATEP)
  361. RET
  362. SYM_FUNC_END(aegis128_aesni_enc_tail)
  363. .macro decrypt_block s0 s1 s2 s3 s4 i
  364. movdqu (\i * 0x10)(SRC), MSG
  365. pxor \s1, MSG
  366. pxor \s4, MSG
  367. movdqa \s2, T1
  368. pand \s3, T1
  369. pxor T1, MSG
  370. movdqu MSG, (\i * 0x10)(DST)
  371. aegis128_update
  372. pxor MSG, \s4
  373. sub $0x10, LEN
  374. jz .Ldec_out_\i
  375. .endm
  376. /*
  377. * void aegis128_aesni_dec(struct aegis_state *state, const u8 *src, u8 *dst,
  378. * unsigned int len);
  379. *
  380. * len must be nonzero and a multiple of 16.
  381. */
  382. SYM_FUNC_START(aegis128_aesni_dec)
  383. .set STATEP, %rdi
  384. .set SRC, %rsi
  385. .set DST, %rdx
  386. .set LEN, %ecx
  387. /* load the state: */
  388. movdqu 0x00(STATEP), STATE0
  389. movdqu 0x10(STATEP), STATE1
  390. movdqu 0x20(STATEP), STATE2
  391. movdqu 0x30(STATEP), STATE3
  392. movdqu 0x40(STATEP), STATE4
  393. .align 8
  394. .Ldec_loop:
  395. decrypt_block STATE0 STATE1 STATE2 STATE3 STATE4 0
  396. decrypt_block STATE4 STATE0 STATE1 STATE2 STATE3 1
  397. decrypt_block STATE3 STATE4 STATE0 STATE1 STATE2 2
  398. decrypt_block STATE2 STATE3 STATE4 STATE0 STATE1 3
  399. decrypt_block STATE1 STATE2 STATE3 STATE4 STATE0 4
  400. add $0x50, SRC
  401. add $0x50, DST
  402. jmp .Ldec_loop
  403. /* store the state: */
  404. .Ldec_out_0:
  405. movdqu STATE4, 0x00(STATEP)
  406. movdqu STATE0, 0x10(STATEP)
  407. movdqu STATE1, 0x20(STATEP)
  408. movdqu STATE2, 0x30(STATEP)
  409. movdqu STATE3, 0x40(STATEP)
  410. RET
  411. .Ldec_out_1:
  412. movdqu STATE3, 0x00(STATEP)
  413. movdqu STATE4, 0x10(STATEP)
  414. movdqu STATE0, 0x20(STATEP)
  415. movdqu STATE1, 0x30(STATEP)
  416. movdqu STATE2, 0x40(STATEP)
  417. RET
  418. .Ldec_out_2:
  419. movdqu STATE2, 0x00(STATEP)
  420. movdqu STATE3, 0x10(STATEP)
  421. movdqu STATE4, 0x20(STATEP)
  422. movdqu STATE0, 0x30(STATEP)
  423. movdqu STATE1, 0x40(STATEP)
  424. RET
  425. .Ldec_out_3:
  426. movdqu STATE1, 0x00(STATEP)
  427. movdqu STATE2, 0x10(STATEP)
  428. movdqu STATE3, 0x20(STATEP)
  429. movdqu STATE4, 0x30(STATEP)
  430. movdqu STATE0, 0x40(STATEP)
  431. RET
  432. .Ldec_out_4:
  433. movdqu STATE0, 0x00(STATEP)
  434. movdqu STATE1, 0x10(STATEP)
  435. movdqu STATE2, 0x20(STATEP)
  436. movdqu STATE3, 0x30(STATEP)
  437. movdqu STATE4, 0x40(STATEP)
  438. .Ldec_out:
  439. RET
  440. SYM_FUNC_END(aegis128_aesni_dec)
  441. /*
  442. * void aegis128_aesni_dec_tail(struct aegis_state *state, const u8 *src,
  443. * u8 *dst, unsigned int len);
  444. */
  445. SYM_FUNC_START(aegis128_aesni_dec_tail)
  446. .set STATEP, %rdi
  447. .set SRC, %rsi
  448. .set DST, %rdx
  449. .set LEN, %ecx /* {load,store}_partial rely on this being %ecx */
  450. /* load the state: */
  451. movdqu 0x00(STATEP), STATE0
  452. movdqu 0x10(STATEP), STATE1
  453. movdqu 0x20(STATEP), STATE2
  454. movdqu 0x30(STATEP), STATE3
  455. movdqu 0x40(STATEP), STATE4
  456. /* decrypt message: */
  457. mov LEN, %r9d
  458. load_partial
  459. pxor STATE1, MSG
  460. pxor STATE4, MSG
  461. movdqa STATE2, T1
  462. pand STATE3, T1
  463. pxor T1, MSG
  464. mov %r9d, LEN
  465. store_partial MSG
  466. /* mask with byte count: */
  467. lea .Lzeropad_mask+16(%rip), %rax
  468. sub %r9, %rax
  469. movdqu (%rax), T0
  470. pand T0, MSG
  471. aegis128_update
  472. pxor MSG, STATE4
  473. /* store the state: */
  474. movdqu STATE4, 0x00(STATEP)
  475. movdqu STATE0, 0x10(STATEP)
  476. movdqu STATE1, 0x20(STATEP)
  477. movdqu STATE2, 0x30(STATEP)
  478. movdqu STATE3, 0x40(STATEP)
  479. RET
  480. SYM_FUNC_END(aegis128_aesni_dec_tail)
  481. /*
  482. * void aegis128_aesni_final(struct aegis_state *state,
  483. * struct aegis_block *tag_xor,
  484. * unsigned int assoclen, unsigned int cryptlen);
  485. */
  486. SYM_FUNC_START(aegis128_aesni_final)
  487. .set STATEP, %rdi
  488. .set TAG_XOR, %rsi
  489. .set ASSOCLEN, %edx
  490. .set CRYPTLEN, %ecx
  491. /* load the state: */
  492. movdqu 0x00(STATEP), STATE0
  493. movdqu 0x10(STATEP), STATE1
  494. movdqu 0x20(STATEP), STATE2
  495. movdqu 0x30(STATEP), STATE3
  496. movdqu 0x40(STATEP), STATE4
  497. /* prepare length block: */
  498. movd ASSOCLEN, MSG
  499. pinsrd $2, CRYPTLEN, MSG
  500. psllq $3, MSG /* multiply by 8 (to get bit count) */
  501. pxor STATE3, MSG
  502. /* update state: */
  503. aegis128_update; pxor MSG, STATE4
  504. aegis128_update; pxor MSG, STATE3
  505. aegis128_update; pxor MSG, STATE2
  506. aegis128_update; pxor MSG, STATE1
  507. aegis128_update; pxor MSG, STATE0
  508. aegis128_update; pxor MSG, STATE4
  509. aegis128_update; pxor MSG, STATE3
  510. /* xor tag: */
  511. movdqu (TAG_XOR), MSG
  512. pxor STATE0, MSG
  513. pxor STATE1, MSG
  514. pxor STATE2, MSG
  515. pxor STATE3, MSG
  516. pxor STATE4, MSG
  517. movdqu MSG, (TAG_XOR)
  518. RET
  519. SYM_FUNC_END(aegis128_aesni_final)