GNU Linux-libre 4.19.314-gnu1
[releases.git] / arch / arm / crypto / chacha20-neon-core.S
1 /*
2  * ChaCha20 256-bit cipher algorithm, RFC7539, ARM NEON functions
3  *
4  * Copyright (C) 2016 Linaro, Ltd. <ard.biesheuvel@linaro.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * Based on:
11  * ChaCha20 256-bit cipher algorithm, RFC7539, x64 SSE3 functions
12  *
13  * Copyright (C) 2015 Martin Willi
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  */
20
21 #include <linux/linkage.h>
22
23         .text
24         .fpu            neon
25         .align          5
26
27 ENTRY(chacha20_block_xor_neon)
28         // r0: Input state matrix, s
29         // r1: 1 data block output, o
30         // r2: 1 data block input, i
31
32         //
33         // This function encrypts one ChaCha20 block by loading the state matrix
34         // in four NEON registers. It performs matrix operation on four words in
35         // parallel, but requireds shuffling to rearrange the words after each
36         // round.
37         //
38
39         // x0..3 = s0..3
40         add             ip, r0, #0x20
41         vld1.32         {q0-q1}, [r0]
42         vld1.32         {q2-q3}, [ip]
43
44         vmov            q8, q0
45         vmov            q9, q1
46         vmov            q10, q2
47         vmov            q11, q3
48
49         mov             r3, #10
50
51 .Ldoubleround:
52         // x0 += x1, x3 = rotl32(x3 ^ x0, 16)
53         vadd.i32        q0, q0, q1
54         veor            q3, q3, q0
55         vrev32.16       q3, q3
56
57         // x2 += x3, x1 = rotl32(x1 ^ x2, 12)
58         vadd.i32        q2, q2, q3
59         veor            q4, q1, q2
60         vshl.u32        q1, q4, #12
61         vsri.u32        q1, q4, #20
62
63         // x0 += x1, x3 = rotl32(x3 ^ x0, 8)
64         vadd.i32        q0, q0, q1
65         veor            q4, q3, q0
66         vshl.u32        q3, q4, #8
67         vsri.u32        q3, q4, #24
68
69         // x2 += x3, x1 = rotl32(x1 ^ x2, 7)
70         vadd.i32        q2, q2, q3
71         veor            q4, q1, q2
72         vshl.u32        q1, q4, #7
73         vsri.u32        q1, q4, #25
74
75         // x1 = shuffle32(x1, MASK(0, 3, 2, 1))
76         vext.8          q1, q1, q1, #4
77         // x2 = shuffle32(x2, MASK(1, 0, 3, 2))
78         vext.8          q2, q2, q2, #8
79         // x3 = shuffle32(x3, MASK(2, 1, 0, 3))
80         vext.8          q3, q3, q3, #12
81
82         // x0 += x1, x3 = rotl32(x3 ^ x0, 16)
83         vadd.i32        q0, q0, q1
84         veor            q3, q3, q0
85         vrev32.16       q3, q3
86
87         // x2 += x3, x1 = rotl32(x1 ^ x2, 12)
88         vadd.i32        q2, q2, q3
89         veor            q4, q1, q2
90         vshl.u32        q1, q4, #12
91         vsri.u32        q1, q4, #20
92
93         // x0 += x1, x3 = rotl32(x3 ^ x0, 8)
94         vadd.i32        q0, q0, q1
95         veor            q4, q3, q0
96         vshl.u32        q3, q4, #8
97         vsri.u32        q3, q4, #24
98
99         // x2 += x3, x1 = rotl32(x1 ^ x2, 7)
100         vadd.i32        q2, q2, q3
101         veor            q4, q1, q2
102         vshl.u32        q1, q4, #7
103         vsri.u32        q1, q4, #25
104
105         // x1 = shuffle32(x1, MASK(2, 1, 0, 3))
106         vext.8          q1, q1, q1, #12
107         // x2 = shuffle32(x2, MASK(1, 0, 3, 2))
108         vext.8          q2, q2, q2, #8
109         // x3 = shuffle32(x3, MASK(0, 3, 2, 1))
110         vext.8          q3, q3, q3, #4
111
112         subs            r3, r3, #1
113         bne             .Ldoubleround
114
115         add             ip, r2, #0x20
116         vld1.8          {q4-q5}, [r2]
117         vld1.8          {q6-q7}, [ip]
118
119         // o0 = i0 ^ (x0 + s0)
120         vadd.i32        q0, q0, q8
121         veor            q0, q0, q4
122
123         // o1 = i1 ^ (x1 + s1)
124         vadd.i32        q1, q1, q9
125         veor            q1, q1, q5
126
127         // o2 = i2 ^ (x2 + s2)
128         vadd.i32        q2, q2, q10
129         veor            q2, q2, q6
130
131         // o3 = i3 ^ (x3 + s3)
132         vadd.i32        q3, q3, q11
133         veor            q3, q3, q7
134
135         add             ip, r1, #0x20
136         vst1.8          {q0-q1}, [r1]
137         vst1.8          {q2-q3}, [ip]
138
139         bx              lr
140 ENDPROC(chacha20_block_xor_neon)
141
142         .align          5
143 ENTRY(chacha20_4block_xor_neon)
144         push            {r4-r6, lr}
145         mov             ip, sp                  // preserve the stack pointer
146         sub             r3, sp, #0x20           // allocate a 32 byte buffer
147         bic             r3, r3, #0x1f           // aligned to 32 bytes
148         mov             sp, r3
149
150         // r0: Input state matrix, s
151         // r1: 4 data blocks output, o
152         // r2: 4 data blocks input, i
153
154         //
155         // This function encrypts four consecutive ChaCha20 blocks by loading
156         // the state matrix in NEON registers four times. The algorithm performs
157         // each operation on the corresponding word of each state matrix, hence
158         // requires no word shuffling. For final XORing step we transpose the
159         // matrix by interleaving 32- and then 64-bit words, which allows us to
160         // do XOR in NEON registers.
161         //
162
163         // x0..15[0-3] = s0..3[0..3]
164         add             r3, r0, #0x20
165         vld1.32         {q0-q1}, [r0]
166         vld1.32         {q2-q3}, [r3]
167
168         adr             r3, CTRINC
169         vdup.32         q15, d7[1]
170         vdup.32         q14, d7[0]
171         vld1.32         {q11}, [r3, :128]
172         vdup.32         q13, d6[1]
173         vdup.32         q12, d6[0]
174         vadd.i32        q12, q12, q11           // x12 += counter values 0-3
175         vdup.32         q11, d5[1]
176         vdup.32         q10, d5[0]
177         vdup.32         q9, d4[1]
178         vdup.32         q8, d4[0]
179         vdup.32         q7, d3[1]
180         vdup.32         q6, d3[0]
181         vdup.32         q5, d2[1]
182         vdup.32         q4, d2[0]
183         vdup.32         q3, d1[1]
184         vdup.32         q2, d1[0]
185         vdup.32         q1, d0[1]
186         vdup.32         q0, d0[0]
187
188         mov             r3, #10
189
190 .Ldoubleround4:
191         // x0 += x4, x12 = rotl32(x12 ^ x0, 16)
192         // x1 += x5, x13 = rotl32(x13 ^ x1, 16)
193         // x2 += x6, x14 = rotl32(x14 ^ x2, 16)
194         // x3 += x7, x15 = rotl32(x15 ^ x3, 16)
195         vadd.i32        q0, q0, q4
196         vadd.i32        q1, q1, q5
197         vadd.i32        q2, q2, q6
198         vadd.i32        q3, q3, q7
199
200         veor            q12, q12, q0
201         veor            q13, q13, q1
202         veor            q14, q14, q2
203         veor            q15, q15, q3
204
205         vrev32.16       q12, q12
206         vrev32.16       q13, q13
207         vrev32.16       q14, q14
208         vrev32.16       q15, q15
209
210         // x8 += x12, x4 = rotl32(x4 ^ x8, 12)
211         // x9 += x13, x5 = rotl32(x5 ^ x9, 12)
212         // x10 += x14, x6 = rotl32(x6 ^ x10, 12)
213         // x11 += x15, x7 = rotl32(x7 ^ x11, 12)
214         vadd.i32        q8, q8, q12
215         vadd.i32        q9, q9, q13
216         vadd.i32        q10, q10, q14
217         vadd.i32        q11, q11, q15
218
219         vst1.32         {q8-q9}, [sp, :256]
220
221         veor            q8, q4, q8
222         veor            q9, q5, q9
223         vshl.u32        q4, q8, #12
224         vshl.u32        q5, q9, #12
225         vsri.u32        q4, q8, #20
226         vsri.u32        q5, q9, #20
227
228         veor            q8, q6, q10
229         veor            q9, q7, q11
230         vshl.u32        q6, q8, #12
231         vshl.u32        q7, q9, #12
232         vsri.u32        q6, q8, #20
233         vsri.u32        q7, q9, #20
234
235         // x0 += x4, x12 = rotl32(x12 ^ x0, 8)
236         // x1 += x5, x13 = rotl32(x13 ^ x1, 8)
237         // x2 += x6, x14 = rotl32(x14 ^ x2, 8)
238         // x3 += x7, x15 = rotl32(x15 ^ x3, 8)
239         vadd.i32        q0, q0, q4
240         vadd.i32        q1, q1, q5
241         vadd.i32        q2, q2, q6
242         vadd.i32        q3, q3, q7
243
244         veor            q8, q12, q0
245         veor            q9, q13, q1
246         vshl.u32        q12, q8, #8
247         vshl.u32        q13, q9, #8
248         vsri.u32        q12, q8, #24
249         vsri.u32        q13, q9, #24
250
251         veor            q8, q14, q2
252         veor            q9, q15, q3
253         vshl.u32        q14, q8, #8
254         vshl.u32        q15, q9, #8
255         vsri.u32        q14, q8, #24
256         vsri.u32        q15, q9, #24
257
258         vld1.32         {q8-q9}, [sp, :256]
259
260         // x8 += x12, x4 = rotl32(x4 ^ x8, 7)
261         // x9 += x13, x5 = rotl32(x5 ^ x9, 7)
262         // x10 += x14, x6 = rotl32(x6 ^ x10, 7)
263         // x11 += x15, x7 = rotl32(x7 ^ x11, 7)
264         vadd.i32        q8, q8, q12
265         vadd.i32        q9, q9, q13
266         vadd.i32        q10, q10, q14
267         vadd.i32        q11, q11, q15
268
269         vst1.32         {q8-q9}, [sp, :256]
270
271         veor            q8, q4, q8
272         veor            q9, q5, q9
273         vshl.u32        q4, q8, #7
274         vshl.u32        q5, q9, #7
275         vsri.u32        q4, q8, #25
276         vsri.u32        q5, q9, #25
277
278         veor            q8, q6, q10
279         veor            q9, q7, q11
280         vshl.u32        q6, q8, #7
281         vshl.u32        q7, q9, #7
282         vsri.u32        q6, q8, #25
283         vsri.u32        q7, q9, #25
284
285         vld1.32         {q8-q9}, [sp, :256]
286
287         // x0 += x5, x15 = rotl32(x15 ^ x0, 16)
288         // x1 += x6, x12 = rotl32(x12 ^ x1, 16)
289         // x2 += x7, x13 = rotl32(x13 ^ x2, 16)
290         // x3 += x4, x14 = rotl32(x14 ^ x3, 16)
291         vadd.i32        q0, q0, q5
292         vadd.i32        q1, q1, q6
293         vadd.i32        q2, q2, q7
294         vadd.i32        q3, q3, q4
295
296         veor            q15, q15, q0
297         veor            q12, q12, q1
298         veor            q13, q13, q2
299         veor            q14, q14, q3
300
301         vrev32.16       q15, q15
302         vrev32.16       q12, q12
303         vrev32.16       q13, q13
304         vrev32.16       q14, q14
305
306         // x10 += x15, x5 = rotl32(x5 ^ x10, 12)
307         // x11 += x12, x6 = rotl32(x6 ^ x11, 12)
308         // x8 += x13, x7 = rotl32(x7 ^ x8, 12)
309         // x9 += x14, x4 = rotl32(x4 ^ x9, 12)
310         vadd.i32        q10, q10, q15
311         vadd.i32        q11, q11, q12
312         vadd.i32        q8, q8, q13
313         vadd.i32        q9, q9, q14
314
315         vst1.32         {q8-q9}, [sp, :256]
316
317         veor            q8, q7, q8
318         veor            q9, q4, q9
319         vshl.u32        q7, q8, #12
320         vshl.u32        q4, q9, #12
321         vsri.u32        q7, q8, #20
322         vsri.u32        q4, q9, #20
323
324         veor            q8, q5, q10
325         veor            q9, q6, q11
326         vshl.u32        q5, q8, #12
327         vshl.u32        q6, q9, #12
328         vsri.u32        q5, q8, #20
329         vsri.u32        q6, q9, #20
330
331         // x0 += x5, x15 = rotl32(x15 ^ x0, 8)
332         // x1 += x6, x12 = rotl32(x12 ^ x1, 8)
333         // x2 += x7, x13 = rotl32(x13 ^ x2, 8)
334         // x3 += x4, x14 = rotl32(x14 ^ x3, 8)
335         vadd.i32        q0, q0, q5
336         vadd.i32        q1, q1, q6
337         vadd.i32        q2, q2, q7
338         vadd.i32        q3, q3, q4
339
340         veor            q8, q15, q0
341         veor            q9, q12, q1
342         vshl.u32        q15, q8, #8
343         vshl.u32        q12, q9, #8
344         vsri.u32        q15, q8, #24
345         vsri.u32        q12, q9, #24
346
347         veor            q8, q13, q2
348         veor            q9, q14, q3
349         vshl.u32        q13, q8, #8
350         vshl.u32        q14, q9, #8
351         vsri.u32        q13, q8, #24
352         vsri.u32        q14, q9, #24
353
354         vld1.32         {q8-q9}, [sp, :256]
355
356         // x10 += x15, x5 = rotl32(x5 ^ x10, 7)
357         // x11 += x12, x6 = rotl32(x6 ^ x11, 7)
358         // x8 += x13, x7 = rotl32(x7 ^ x8, 7)
359         // x9 += x14, x4 = rotl32(x4 ^ x9, 7)
360         vadd.i32        q10, q10, q15
361         vadd.i32        q11, q11, q12
362         vadd.i32        q8, q8, q13
363         vadd.i32        q9, q9, q14
364
365         vst1.32         {q8-q9}, [sp, :256]
366
367         veor            q8, q7, q8
368         veor            q9, q4, q9
369         vshl.u32        q7, q8, #7
370         vshl.u32        q4, q9, #7
371         vsri.u32        q7, q8, #25
372         vsri.u32        q4, q9, #25
373
374         veor            q8, q5, q10
375         veor            q9, q6, q11
376         vshl.u32        q5, q8, #7
377         vshl.u32        q6, q9, #7
378         vsri.u32        q5, q8, #25
379         vsri.u32        q6, q9, #25
380
381         subs            r3, r3, #1
382         beq             0f
383
384         vld1.32         {q8-q9}, [sp, :256]
385         b               .Ldoubleround4
386
387         // x0[0-3] += s0[0]
388         // x1[0-3] += s0[1]
389         // x2[0-3] += s0[2]
390         // x3[0-3] += s0[3]
391 0:      ldmia           r0!, {r3-r6}
392         vdup.32         q8, r3
393         vdup.32         q9, r4
394         vadd.i32        q0, q0, q8
395         vadd.i32        q1, q1, q9
396         vdup.32         q8, r5
397         vdup.32         q9, r6
398         vadd.i32        q2, q2, q8
399         vadd.i32        q3, q3, q9
400
401         // x4[0-3] += s1[0]
402         // x5[0-3] += s1[1]
403         // x6[0-3] += s1[2]
404         // x7[0-3] += s1[3]
405         ldmia           r0!, {r3-r6}
406         vdup.32         q8, r3
407         vdup.32         q9, r4
408         vadd.i32        q4, q4, q8
409         vadd.i32        q5, q5, q9
410         vdup.32         q8, r5
411         vdup.32         q9, r6
412         vadd.i32        q6, q6, q8
413         vadd.i32        q7, q7, q9
414
415         // interleave 32-bit words in state n, n+1
416         vzip.32         q0, q1
417         vzip.32         q2, q3
418         vzip.32         q4, q5
419         vzip.32         q6, q7
420
421         // interleave 64-bit words in state n, n+2
422         vswp            d1, d4
423         vswp            d3, d6
424         vswp            d9, d12
425         vswp            d11, d14
426
427         // xor with corresponding input, write to output
428         vld1.8          {q8-q9}, [r2]!
429         veor            q8, q8, q0
430         veor            q9, q9, q4
431         vst1.8          {q8-q9}, [r1]!
432
433         vld1.32         {q8-q9}, [sp, :256]
434
435         // x8[0-3] += s2[0]
436         // x9[0-3] += s2[1]
437         // x10[0-3] += s2[2]
438         // x11[0-3] += s2[3]
439         ldmia           r0!, {r3-r6}
440         vdup.32         q0, r3
441         vdup.32         q4, r4
442         vadd.i32        q8, q8, q0
443         vadd.i32        q9, q9, q4
444         vdup.32         q0, r5
445         vdup.32         q4, r6
446         vadd.i32        q10, q10, q0
447         vadd.i32        q11, q11, q4
448
449         // x12[0-3] += s3[0]
450         // x13[0-3] += s3[1]
451         // x14[0-3] += s3[2]
452         // x15[0-3] += s3[3]
453         ldmia           r0!, {r3-r6}
454         vdup.32         q0, r3
455         vdup.32         q4, r4
456         adr             r3, CTRINC
457         vadd.i32        q12, q12, q0
458         vld1.32         {q0}, [r3, :128]
459         vadd.i32        q13, q13, q4
460         vadd.i32        q12, q12, q0            // x12 += counter values 0-3
461
462         vdup.32         q0, r5
463         vdup.32         q4, r6
464         vadd.i32        q14, q14, q0
465         vadd.i32        q15, q15, q4
466
467         // interleave 32-bit words in state n, n+1
468         vzip.32         q8, q9
469         vzip.32         q10, q11
470         vzip.32         q12, q13
471         vzip.32         q14, q15
472
473         // interleave 64-bit words in state n, n+2
474         vswp            d17, d20
475         vswp            d19, d22
476         vswp            d25, d28
477         vswp            d27, d30
478
479         vmov            q4, q1
480
481         vld1.8          {q0-q1}, [r2]!
482         veor            q0, q0, q8
483         veor            q1, q1, q12
484         vst1.8          {q0-q1}, [r1]!
485
486         vld1.8          {q0-q1}, [r2]!
487         veor            q0, q0, q2
488         veor            q1, q1, q6
489         vst1.8          {q0-q1}, [r1]!
490
491         vld1.8          {q0-q1}, [r2]!
492         veor            q0, q0, q10
493         veor            q1, q1, q14
494         vst1.8          {q0-q1}, [r1]!
495
496         vld1.8          {q0-q1}, [r2]!
497         veor            q0, q0, q4
498         veor            q1, q1, q5
499         vst1.8          {q0-q1}, [r1]!
500
501         vld1.8          {q0-q1}, [r2]!
502         veor            q0, q0, q9
503         veor            q1, q1, q13
504         vst1.8          {q0-q1}, [r1]!
505
506         vld1.8          {q0-q1}, [r2]!
507         veor            q0, q0, q3
508         veor            q1, q1, q7
509         vst1.8          {q0-q1}, [r1]!
510
511         vld1.8          {q0-q1}, [r2]
512         veor            q0, q0, q11
513         veor            q1, q1, q15
514         vst1.8          {q0-q1}, [r1]
515
516         mov             sp, ip
517         pop             {r4-r6, pc}
518 ENDPROC(chacha20_4block_xor_neon)
519
520         .align          4
521 CTRINC: .word           0, 1, 2, 3