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