GNU Linux-libre 5.19-rc6-gnu
[releases.git] / arch / x86 / crypto / aes_ctrby8_avx-x86_64.S
1 /* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */
2 /*
3  * AES CTR mode by8 optimization with AVX instructions. (x86_64)
4  *
5  * Copyright(c) 2014 Intel Corporation.
6  *
7  * Contact Information:
8  * James Guilford <james.guilford@intel.com>
9  * Sean Gulley <sean.m.gulley@intel.com>
10  * Chandramouli Narayanan <mouli@linux.intel.com>
11  */
12 /*
13  * This is AES128/192/256 CTR mode optimization implementation. It requires
14  * the support of Intel(R) AESNI and AVX instructions.
15  *
16  * This work was inspired by the AES CTR mode optimization published
17  * in Intel Optimized IPSEC Cryptographic library.
18  * Additional information on it can be found at:
19  *    https://github.com/intel/intel-ipsec-mb
20  */
21
22 #include <linux/linkage.h>
23
24 #define VMOVDQ          vmovdqu
25
26 #define xdata0          %xmm0
27 #define xdata1          %xmm1
28 #define xdata2          %xmm2
29 #define xdata3          %xmm3
30 #define xdata4          %xmm4
31 #define xdata5          %xmm5
32 #define xdata6          %xmm6
33 #define xdata7          %xmm7
34 #define xcounter        %xmm8
35 #define xbyteswap       %xmm9
36 #define xkey0           %xmm10
37 #define xkey4           %xmm11
38 #define xkey8           %xmm12
39 #define xkey12          %xmm13
40 #define xkeyA           %xmm14
41 #define xkeyB           %xmm15
42
43 #define p_in            %rdi
44 #define p_iv            %rsi
45 #define p_keys          %rdx
46 #define p_out           %rcx
47 #define num_bytes       %r8
48
49 #define tmp             %r10
50 #define DDQ_DATA        0
51 #define XDATA           1
52 #define KEY_128         1
53 #define KEY_192         2
54 #define KEY_256         3
55
56 .section .rodata
57 .align 16
58
59 byteswap_const:
60         .octa 0x000102030405060708090A0B0C0D0E0F
61 ddq_low_msk:
62         .octa 0x0000000000000000FFFFFFFFFFFFFFFF
63 ddq_high_add_1:
64         .octa 0x00000000000000010000000000000000
65 ddq_add_1:
66         .octa 0x00000000000000000000000000000001
67 ddq_add_2:
68         .octa 0x00000000000000000000000000000002
69 ddq_add_3:
70         .octa 0x00000000000000000000000000000003
71 ddq_add_4:
72         .octa 0x00000000000000000000000000000004
73 ddq_add_5:
74         .octa 0x00000000000000000000000000000005
75 ddq_add_6:
76         .octa 0x00000000000000000000000000000006
77 ddq_add_7:
78         .octa 0x00000000000000000000000000000007
79 ddq_add_8:
80         .octa 0x00000000000000000000000000000008
81
82 .text
83
84 /* generate a unique variable for ddq_add_x */
85
86 /* generate a unique variable for xmm register */
87 .macro setxdata n
88         var_xdata = %xmm\n
89 .endm
90
91 /* club the numeric 'id' to the symbol 'name' */
92
93 .macro club name, id
94 .altmacro
95         .if \name == XDATA
96                 setxdata %\id
97         .endif
98 .noaltmacro
99 .endm
100
101 /*
102  * do_aes num_in_par load_keys key_len
103  * This increments p_in, but not p_out
104  */
105 .macro do_aes b, k, key_len
106         .set by, \b
107         .set load_keys, \k
108         .set klen, \key_len
109
110         .if (load_keys)
111                 vmovdqa 0*16(p_keys), xkey0
112         .endif
113
114         vpshufb xbyteswap, xcounter, xdata0
115
116         .set i, 1
117         .rept (by - 1)
118                 club XDATA, i
119                 vpaddq  (ddq_add_1 + 16 * (i - 1))(%rip), xcounter, var_xdata
120                 vptest  ddq_low_msk(%rip), var_xdata
121                 jnz 1f
122                 vpaddq  ddq_high_add_1(%rip), var_xdata, var_xdata
123                 vpaddq  ddq_high_add_1(%rip), xcounter, xcounter
124                 1:
125                 vpshufb xbyteswap, var_xdata, var_xdata
126                 .set i, (i +1)
127         .endr
128
129         vmovdqa 1*16(p_keys), xkeyA
130
131         vpxor   xkey0, xdata0, xdata0
132         vpaddq  (ddq_add_1 + 16 * (by - 1))(%rip), xcounter, xcounter
133         vptest  ddq_low_msk(%rip), xcounter
134         jnz     1f
135         vpaddq  ddq_high_add_1(%rip), xcounter, xcounter
136         1:
137
138         .set i, 1
139         .rept (by - 1)
140                 club XDATA, i
141                 vpxor   xkey0, var_xdata, var_xdata
142                 .set i, (i +1)
143         .endr
144
145         vmovdqa 2*16(p_keys), xkeyB
146
147         .set i, 0
148         .rept by
149                 club XDATA, i
150                 vaesenc xkeyA, var_xdata, var_xdata             /* key 1 */
151                 .set i, (i +1)
152         .endr
153
154         .if (klen == KEY_128)
155                 .if (load_keys)
156                         vmovdqa 3*16(p_keys), xkey4
157                 .endif
158         .else
159                 vmovdqa 3*16(p_keys), xkeyA
160         .endif
161
162         .set i, 0
163         .rept by
164                 club XDATA, i
165                 vaesenc xkeyB, var_xdata, var_xdata             /* key 2 */
166                 .set i, (i +1)
167         .endr
168
169         add     $(16*by), p_in
170
171         .if (klen == KEY_128)
172                 vmovdqa 4*16(p_keys), xkeyB
173         .else
174                 .if (load_keys)
175                         vmovdqa 4*16(p_keys), xkey4
176                 .endif
177         .endif
178
179         .set i, 0
180         .rept by
181                 club XDATA, i
182                 /* key 3 */
183                 .if (klen == KEY_128)
184                         vaesenc xkey4, var_xdata, var_xdata
185                 .else
186                         vaesenc xkeyA, var_xdata, var_xdata
187                 .endif
188                 .set i, (i +1)
189         .endr
190
191         vmovdqa 5*16(p_keys), xkeyA
192
193         .set i, 0
194         .rept by
195                 club XDATA, i
196                 /* key 4 */
197                 .if (klen == KEY_128)
198                         vaesenc xkeyB, var_xdata, var_xdata
199                 .else
200                         vaesenc xkey4, var_xdata, var_xdata
201                 .endif
202                 .set i, (i +1)
203         .endr
204
205         .if (klen == KEY_128)
206                 .if (load_keys)
207                         vmovdqa 6*16(p_keys), xkey8
208                 .endif
209         .else
210                 vmovdqa 6*16(p_keys), xkeyB
211         .endif
212
213         .set i, 0
214         .rept by
215                 club XDATA, i
216                 vaesenc xkeyA, var_xdata, var_xdata             /* key 5 */
217                 .set i, (i +1)
218         .endr
219
220         vmovdqa 7*16(p_keys), xkeyA
221
222         .set i, 0
223         .rept by
224                 club XDATA, i
225                 /* key 6 */
226                 .if (klen == KEY_128)
227                         vaesenc xkey8, var_xdata, var_xdata
228                 .else
229                         vaesenc xkeyB, var_xdata, var_xdata
230                 .endif
231                 .set i, (i +1)
232         .endr
233
234         .if (klen == KEY_128)
235                 vmovdqa 8*16(p_keys), xkeyB
236         .else
237                 .if (load_keys)
238                         vmovdqa 8*16(p_keys), xkey8
239                 .endif
240         .endif
241
242         .set i, 0
243         .rept by
244                 club XDATA, i
245                 vaesenc xkeyA, var_xdata, var_xdata             /* key 7 */
246                 .set i, (i +1)
247         .endr
248
249         .if (klen == KEY_128)
250                 .if (load_keys)
251                         vmovdqa 9*16(p_keys), xkey12
252                 .endif
253         .else
254                 vmovdqa 9*16(p_keys), xkeyA
255         .endif
256
257         .set i, 0
258         .rept by
259                 club XDATA, i
260                 /* key 8 */
261                 .if (klen == KEY_128)
262                         vaesenc xkeyB, var_xdata, var_xdata
263                 .else
264                         vaesenc xkey8, var_xdata, var_xdata
265                 .endif
266                 .set i, (i +1)
267         .endr
268
269         vmovdqa 10*16(p_keys), xkeyB
270
271         .set i, 0
272         .rept by
273                 club XDATA, i
274                 /* key 9 */
275                 .if (klen == KEY_128)
276                         vaesenc xkey12, var_xdata, var_xdata
277                 .else
278                         vaesenc xkeyA, var_xdata, var_xdata
279                 .endif
280                 .set i, (i +1)
281         .endr
282
283         .if (klen != KEY_128)
284                 vmovdqa 11*16(p_keys), xkeyA
285         .endif
286
287         .set i, 0
288         .rept by
289                 club XDATA, i
290                 /* key 10 */
291                 .if (klen == KEY_128)
292                         vaesenclast     xkeyB, var_xdata, var_xdata
293                 .else
294                         vaesenc xkeyB, var_xdata, var_xdata
295                 .endif
296                 .set i, (i +1)
297         .endr
298
299         .if (klen != KEY_128)
300                 .if (load_keys)
301                         vmovdqa 12*16(p_keys), xkey12
302                 .endif
303
304                 .set i, 0
305                 .rept by
306                         club XDATA, i
307                         vaesenc xkeyA, var_xdata, var_xdata     /* key 11 */
308                         .set i, (i +1)
309                 .endr
310
311                 .if (klen == KEY_256)
312                         vmovdqa 13*16(p_keys), xkeyA
313                 .endif
314
315                 .set i, 0
316                 .rept by
317                         club XDATA, i
318                         .if (klen == KEY_256)
319                                 /* key 12 */
320                                 vaesenc xkey12, var_xdata, var_xdata
321                         .else
322                                 vaesenclast xkey12, var_xdata, var_xdata
323                         .endif
324                         .set i, (i +1)
325                 .endr
326
327                 .if (klen == KEY_256)
328                         vmovdqa 14*16(p_keys), xkeyB
329
330                         .set i, 0
331                         .rept by
332                                 club XDATA, i
333                                 /* key 13 */
334                                 vaesenc xkeyA, var_xdata, var_xdata
335                                 .set i, (i +1)
336                         .endr
337
338                         .set i, 0
339                         .rept by
340                                 club XDATA, i
341                                 /* key 14 */
342                                 vaesenclast     xkeyB, var_xdata, var_xdata
343                                 .set i, (i +1)
344                         .endr
345                 .endif
346         .endif
347
348         .set i, 0
349         .rept (by / 2)
350                 .set j, (i+1)
351                 VMOVDQ  (i*16 - 16*by)(p_in), xkeyA
352                 VMOVDQ  (j*16 - 16*by)(p_in), xkeyB
353                 club XDATA, i
354                 vpxor   xkeyA, var_xdata, var_xdata
355                 club XDATA, j
356                 vpxor   xkeyB, var_xdata, var_xdata
357                 .set i, (i+2)
358         .endr
359
360         .if (i < by)
361                 VMOVDQ  (i*16 - 16*by)(p_in), xkeyA
362                 club XDATA, i
363                 vpxor   xkeyA, var_xdata, var_xdata
364         .endif
365
366         .set i, 0
367         .rept by
368                 club XDATA, i
369                 VMOVDQ  var_xdata, i*16(p_out)
370                 .set i, (i+1)
371         .endr
372 .endm
373
374 .macro do_aes_load val, key_len
375         do_aes \val, 1, \key_len
376 .endm
377
378 .macro do_aes_noload val, key_len
379         do_aes \val, 0, \key_len
380 .endm
381
382 /* main body of aes ctr load */
383
384 .macro do_aes_ctrmain key_len
385         cmp     $16, num_bytes
386         jb      .Ldo_return2\key_len
387
388         vmovdqa byteswap_const(%rip), xbyteswap
389         vmovdqu (p_iv), xcounter
390         vpshufb xbyteswap, xcounter, xcounter
391
392         mov     num_bytes, tmp
393         and     $(7*16), tmp
394         jz      .Lmult_of_8_blks\key_len
395
396         /* 1 <= tmp <= 7 */
397         cmp     $(4*16), tmp
398         jg      .Lgt4\key_len
399         je      .Leq4\key_len
400
401 .Llt4\key_len:
402         cmp     $(2*16), tmp
403         jg      .Leq3\key_len
404         je      .Leq2\key_len
405
406 .Leq1\key_len:
407         do_aes_load     1, \key_len
408         add     $(1*16), p_out
409         and     $(~7*16), num_bytes
410         jz      .Ldo_return2\key_len
411         jmp     .Lmain_loop2\key_len
412
413 .Leq2\key_len:
414         do_aes_load     2, \key_len
415         add     $(2*16), p_out
416         and     $(~7*16), num_bytes
417         jz      .Ldo_return2\key_len
418         jmp     .Lmain_loop2\key_len
419
420
421 .Leq3\key_len:
422         do_aes_load     3, \key_len
423         add     $(3*16), p_out
424         and     $(~7*16), num_bytes
425         jz      .Ldo_return2\key_len
426         jmp     .Lmain_loop2\key_len
427
428 .Leq4\key_len:
429         do_aes_load     4, \key_len
430         add     $(4*16), p_out
431         and     $(~7*16), num_bytes
432         jz      .Ldo_return2\key_len
433         jmp     .Lmain_loop2\key_len
434
435 .Lgt4\key_len:
436         cmp     $(6*16), tmp
437         jg      .Leq7\key_len
438         je      .Leq6\key_len
439
440 .Leq5\key_len:
441         do_aes_load     5, \key_len
442         add     $(5*16), p_out
443         and     $(~7*16), num_bytes
444         jz      .Ldo_return2\key_len
445         jmp     .Lmain_loop2\key_len
446
447 .Leq6\key_len:
448         do_aes_load     6, \key_len
449         add     $(6*16), p_out
450         and     $(~7*16), num_bytes
451         jz      .Ldo_return2\key_len
452         jmp     .Lmain_loop2\key_len
453
454 .Leq7\key_len:
455         do_aes_load     7, \key_len
456         add     $(7*16), p_out
457         and     $(~7*16), num_bytes
458         jz      .Ldo_return2\key_len
459         jmp     .Lmain_loop2\key_len
460
461 .Lmult_of_8_blks\key_len:
462         .if (\key_len != KEY_128)
463                 vmovdqa 0*16(p_keys), xkey0
464                 vmovdqa 4*16(p_keys), xkey4
465                 vmovdqa 8*16(p_keys), xkey8
466                 vmovdqa 12*16(p_keys), xkey12
467         .else
468                 vmovdqa 0*16(p_keys), xkey0
469                 vmovdqa 3*16(p_keys), xkey4
470                 vmovdqa 6*16(p_keys), xkey8
471                 vmovdqa 9*16(p_keys), xkey12
472         .endif
473 .align 16
474 .Lmain_loop2\key_len:
475         /* num_bytes is a multiple of 8 and >0 */
476         do_aes_noload   8, \key_len
477         add     $(8*16), p_out
478         sub     $(8*16), num_bytes
479         jne     .Lmain_loop2\key_len
480
481 .Ldo_return2\key_len:
482         /* return updated IV */
483         vpshufb xbyteswap, xcounter, xcounter
484         vmovdqu xcounter, (p_iv)
485         RET
486 .endm
487
488 /*
489  * routine to do AES128 CTR enc/decrypt "by8"
490  * XMM registers are clobbered.
491  * Saving/restoring must be done at a higher level
492  * aes_ctr_enc_128_avx_by8(void *in, void *iv, void *keys, void *out,
493  *                      unsigned int num_bytes)
494  */
495 SYM_FUNC_START(aes_ctr_enc_128_avx_by8)
496         /* call the aes main loop */
497         do_aes_ctrmain KEY_128
498
499 SYM_FUNC_END(aes_ctr_enc_128_avx_by8)
500
501 /*
502  * routine to do AES192 CTR enc/decrypt "by8"
503  * XMM registers are clobbered.
504  * Saving/restoring must be done at a higher level
505  * aes_ctr_enc_192_avx_by8(void *in, void *iv, void *keys, void *out,
506  *                      unsigned int num_bytes)
507  */
508 SYM_FUNC_START(aes_ctr_enc_192_avx_by8)
509         /* call the aes main loop */
510         do_aes_ctrmain KEY_192
511
512 SYM_FUNC_END(aes_ctr_enc_192_avx_by8)
513
514 /*
515  * routine to do AES256 CTR enc/decrypt "by8"
516  * XMM registers are clobbered.
517  * Saving/restoring must be done at a higher level
518  * aes_ctr_enc_256_avx_by8(void *in, void *iv, void *keys, void *out,
519  *                      unsigned int num_bytes)
520  */
521 SYM_FUNC_START(aes_ctr_enc_256_avx_by8)
522         /* call the aes main loop */
523         do_aes_ctrmain KEY_256
524
525 SYM_FUNC_END(aes_ctr_enc_256_avx_by8)