xref: /linux/arch/arm/crypto/aes-neonbs-core.S (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Bit sliced AES using NEON instructions
4 *
5 * Copyright (C) 2017 Linaro Ltd.
6 * Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
7 */
8
9/*
10 * The algorithm implemented here is described in detail by the paper
11 * 'Faster and Timing-Attack Resistant AES-GCM' by Emilia Kaesper and
12 * Peter Schwabe (https://eprint.iacr.org/2009/129.pdf)
13 *
14 * This implementation is based primarily on the OpenSSL implementation
15 * for 32-bit ARM written by Andy Polyakov <appro@openssl.org>
16 */
17
18#include <linux/linkage.h>
19#include <asm/assembler.h>
20
21	.text
22	.fpu		neon
23
24	rounds		.req	ip
25	bskey		.req	r4
26
27	q0l		.req	d0
28	q0h		.req	d1
29	q1l		.req	d2
30	q1h		.req	d3
31	q2l		.req	d4
32	q2h		.req	d5
33	q3l		.req	d6
34	q3h		.req	d7
35	q4l		.req	d8
36	q4h		.req	d9
37	q5l		.req	d10
38	q5h		.req	d11
39	q6l		.req	d12
40	q6h		.req	d13
41	q7l		.req	d14
42	q7h		.req	d15
43	q8l		.req	d16
44	q8h		.req	d17
45	q9l		.req	d18
46	q9h		.req	d19
47	q10l		.req	d20
48	q10h		.req	d21
49	q11l		.req	d22
50	q11h		.req	d23
51	q12l		.req	d24
52	q12h		.req	d25
53	q13l		.req	d26
54	q13h		.req	d27
55	q14l		.req	d28
56	q14h		.req	d29
57	q15l		.req	d30
58	q15h		.req	d31
59
60	.macro		__tbl, out, tbl, in, tmp
61	.ifc		\out, \tbl
62	.ifb		\tmp
63	.error		__tbl needs temp register if out == tbl
64	.endif
65	vmov		\tmp, \out
66	.endif
67	vtbl.8		\out\()l, {\tbl}, \in\()l
68	.ifc		\out, \tbl
69	vtbl.8		\out\()h, {\tmp}, \in\()h
70	.else
71	vtbl.8		\out\()h, {\tbl}, \in\()h
72	.endif
73	.endm
74
75	.macro		__ldr, out, sym
76	vldr		\out\()l, \sym
77	vldr		\out\()h, \sym + 8
78	.endm
79
80	.macro		in_bs_ch, b0, b1, b2, b3, b4, b5, b6, b7
81	veor		\b2, \b2, \b1
82	veor		\b5, \b5, \b6
83	veor		\b3, \b3, \b0
84	veor		\b6, \b6, \b2
85	veor		\b5, \b5, \b0
86	veor		\b6, \b6, \b3
87	veor		\b3, \b3, \b7
88	veor		\b7, \b7, \b5
89	veor		\b3, \b3, \b4
90	veor		\b4, \b4, \b5
91	veor		\b2, \b2, \b7
92	veor		\b3, \b3, \b1
93	veor		\b1, \b1, \b5
94	.endm
95
96	.macro		out_bs_ch, b0, b1, b2, b3, b4, b5, b6, b7
97	veor		\b0, \b0, \b6
98	veor		\b1, \b1, \b4
99	veor		\b4, \b4, \b6
100	veor		\b2, \b2, \b0
101	veor		\b6, \b6, \b1
102	veor		\b1, \b1, \b5
103	veor		\b5, \b5, \b3
104	veor		\b3, \b3, \b7
105	veor		\b7, \b7, \b5
106	veor		\b2, \b2, \b5
107	veor		\b4, \b4, \b7
108	.endm
109
110	.macro		inv_in_bs_ch, b6, b1, b2, b4, b7, b0, b3, b5
111	veor		\b1, \b1, \b7
112	veor		\b4, \b4, \b7
113	veor		\b7, \b7, \b5
114	veor		\b1, \b1, \b3
115	veor		\b2, \b2, \b5
116	veor		\b3, \b3, \b7
117	veor		\b6, \b6, \b1
118	veor		\b2, \b2, \b0
119	veor		\b5, \b5, \b3
120	veor		\b4, \b4, \b6
121	veor		\b0, \b0, \b6
122	veor		\b1, \b1, \b4
123	.endm
124
125	.macro		inv_out_bs_ch, b6, b5, b0, b3, b7, b1, b4, b2
126	veor		\b1, \b1, \b5
127	veor		\b2, \b2, \b7
128	veor		\b3, \b3, \b1
129	veor		\b4, \b4, \b5
130	veor		\b7, \b7, \b5
131	veor		\b3, \b3, \b4
132	veor 		\b5, \b5, \b0
133	veor		\b3, \b3, \b7
134	veor		\b6, \b6, \b2
135	veor		\b2, \b2, \b1
136	veor		\b6, \b6, \b3
137	veor		\b3, \b3, \b0
138	veor		\b5, \b5, \b6
139	.endm
140
141	.macro		mul_gf4, x0, x1, y0, y1, t0, t1
142	veor 		\t0, \y0, \y1
143	vand		\t0, \t0, \x0
144	veor		\x0, \x0, \x1
145	vand		\t1, \x1, \y0
146	vand		\x0, \x0, \y1
147	veor		\x1, \t1, \t0
148	veor		\x0, \x0, \t1
149	.endm
150
151	.macro		mul_gf4_n_gf4, x0, x1, y0, y1, t0, x2, x3, y2, y3, t1
152	veor		\t0, \y0, \y1
153	veor 		\t1, \y2, \y3
154	vand		\t0, \t0, \x0
155	vand		\t1, \t1, \x2
156	veor		\x0, \x0, \x1
157	veor		\x2, \x2, \x3
158	vand		\x1, \x1, \y0
159	vand		\x3, \x3, \y2
160	vand		\x0, \x0, \y1
161	vand		\x2, \x2, \y3
162	veor		\x1, \x1, \x0
163	veor		\x2, \x2, \x3
164	veor		\x0, \x0, \t0
165	veor		\x3, \x3, \t1
166	.endm
167
168	.macro		mul_gf16_2, x0, x1, x2, x3, x4, x5, x6, x7, \
169				    y0, y1, y2, y3, t0, t1, t2, t3
170	veor		\t0, \x0, \x2
171	veor		\t1, \x1, \x3
172	mul_gf4  	\x0, \x1, \y0, \y1, \t2, \t3
173	veor		\y0, \y0, \y2
174	veor		\y1, \y1, \y3
175	mul_gf4_n_gf4	\t0, \t1, \y0, \y1, \t3, \x2, \x3, \y2, \y3, \t2
176	veor		\x0, \x0, \t0
177	veor		\x2, \x2, \t0
178	veor		\x1, \x1, \t1
179	veor		\x3, \x3, \t1
180	veor		\t0, \x4, \x6
181	veor		\t1, \x5, \x7
182	mul_gf4_n_gf4	\t0, \t1, \y0, \y1, \t3, \x6, \x7, \y2, \y3, \t2
183	veor		\y0, \y0, \y2
184	veor		\y1, \y1, \y3
185	mul_gf4  	\x4, \x5, \y0, \y1, \t2, \t3
186	veor		\x4, \x4, \t0
187	veor		\x6, \x6, \t0
188	veor		\x5, \x5, \t1
189	veor		\x7, \x7, \t1
190	.endm
191
192	.macro		inv_gf256, x0, x1, x2, x3, x4, x5, x6, x7, \
193				   t0, t1, t2, t3, s0, s1, s2, s3
194	veor		\t3, \x4, \x6
195	veor		\t0, \x5, \x7
196	veor		\t1, \x1, \x3
197	veor		\s1, \x7, \x6
198	veor		\s0, \x0, \x2
199	veor		\s3, \t3, \t0
200	vorr		\t2, \t0, \t1
201	vand		\s2, \t3, \s0
202	vorr		\t3, \t3, \s0
203	veor		\s0, \s0, \t1
204	vand		\t0, \t0, \t1
205	veor		\t1, \x3, \x2
206	vand		\s3, \s3, \s0
207	vand		\s1, \s1, \t1
208	veor		\t1, \x4, \x5
209	veor		\s0, \x1, \x0
210	veor		\t3, \t3, \s1
211	veor		\t2, \t2, \s1
212	vand		\s1, \t1, \s0
213	vorr		\t1, \t1, \s0
214	veor		\t3, \t3, \s3
215	veor		\t0, \t0, \s1
216	veor		\t2, \t2, \s2
217	veor		\t1, \t1, \s3
218	veor		\t0, \t0, \s2
219	vand		\s0, \x7, \x3
220	veor		\t1, \t1, \s2
221	vand		\s1, \x6, \x2
222	vand		\s2, \x5, \x1
223	vorr		\s3, \x4, \x0
224	veor		\t3, \t3, \s0
225	veor		\t1, \t1, \s2
226	veor		\s0, \t0, \s3
227	veor		\t2, \t2, \s1
228	vand		\s2, \t3, \t1
229	veor		\s1, \t2, \s2
230	veor		\s3, \s0, \s2
231	vbsl		\s1, \t1, \s0
232	vmvn		\t0, \s0
233	vbsl		\s0, \s1, \s3
234	vbsl		\t0, \s1, \s3
235	vbsl		\s3, \t3, \t2
236	veor		\t3, \t3, \t2
237	vand		\s2, \s0, \s3
238	veor		\t1, \t1, \t0
239	veor		\s2, \s2, \t3
240	mul_gf16_2	\x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \
241			\s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
242	.endm
243
244	.macro		sbox, b0, b1, b2, b3, b4, b5, b6, b7, \
245			      t0, t1, t2, t3, s0, s1, s2, s3
246	in_bs_ch	\b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7
247	inv_gf256	\b6, \b5, \b0, \b3, \b7, \b1, \b4, \b2, \
248			\t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
249	out_bs_ch	\b7, \b1, \b4, \b2, \b6, \b5, \b0, \b3
250	.endm
251
252	.macro		inv_sbox, b0, b1, b2, b3, b4, b5, b6, b7, \
253				  t0, t1, t2, t3, s0, s1, s2, s3
254	inv_in_bs_ch	\b0, \b1, \b2, \b3, \b4, \b5, \b6, \b7
255	inv_gf256	\b5, \b1, \b2, \b6, \b3, \b7, \b0, \b4, \
256			\t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
257	inv_out_bs_ch	\b3, \b7, \b0, \b4, \b5, \b1, \b2, \b6
258	.endm
259
260	.macro		shift_rows, x0, x1, x2, x3, x4, x5, x6, x7, \
261				    t0, t1, t2, t3, mask
262	vld1.8		{\t0-\t1}, [bskey, :256]!
263	veor		\t0, \t0, \x0
264	vld1.8		{\t2-\t3}, [bskey, :256]!
265	veor		\t1, \t1, \x1
266	__tbl		\x0, \t0, \mask
267	veor		\t2, \t2, \x2
268	__tbl		\x1, \t1, \mask
269	vld1.8		{\t0-\t1}, [bskey, :256]!
270	veor		\t3, \t3, \x3
271	__tbl		\x2, \t2, \mask
272	__tbl		\x3, \t3, \mask
273	vld1.8		{\t2-\t3}, [bskey, :256]!
274	veor		\t0, \t0, \x4
275	veor		\t1, \t1, \x5
276	__tbl		\x4, \t0, \mask
277	veor		\t2, \t2, \x6
278	__tbl		\x5, \t1, \mask
279	veor		\t3, \t3, \x7
280	__tbl		\x6, \t2, \mask
281	__tbl		\x7, \t3, \mask
282	.endm
283
284	.macro		inv_shift_rows, x0, x1, x2, x3, x4, x5, x6, x7, \
285					t0, t1, t2, t3, mask
286	__tbl		\x0, \x0, \mask, \t0
287	__tbl		\x1, \x1, \mask, \t1
288	__tbl		\x2, \x2, \mask, \t2
289	__tbl		\x3, \x3, \mask, \t3
290	__tbl		\x4, \x4, \mask, \t0
291	__tbl		\x5, \x5, \mask, \t1
292	__tbl		\x6, \x6, \mask, \t2
293	__tbl		\x7, \x7, \mask, \t3
294	.endm
295
296	.macro		mix_cols, x0, x1, x2, x3, x4, x5, x6, x7, \
297				  t0, t1, t2, t3, t4, t5, t6, t7, inv
298	vext.8		\t0, \x0, \x0, #12
299	vext.8		\t1, \x1, \x1, #12
300	veor		\x0, \x0, \t0
301	vext.8		\t2, \x2, \x2, #12
302	veor		\x1, \x1, \t1
303	vext.8		\t3, \x3, \x3, #12
304	veor		\x2, \x2, \t2
305	vext.8		\t4, \x4, \x4, #12
306	veor		\x3, \x3, \t3
307	vext.8		\t5, \x5, \x5, #12
308	veor		\x4, \x4, \t4
309	vext.8		\t6, \x6, \x6, #12
310	veor		\x5, \x5, \t5
311	vext.8		\t7, \x7, \x7, #12
312	veor		\x6, \x6, \t6
313	veor		\t1, \t1, \x0
314	veor.8		\x7, \x7, \t7
315	vext.8		\x0, \x0, \x0, #8
316	veor		\t2, \t2, \x1
317	veor		\t0, \t0, \x7
318	veor		\t1, \t1, \x7
319	vext.8		\x1, \x1, \x1, #8
320	veor		\t5, \t5, \x4
321	veor		\x0, \x0, \t0
322	veor		\t6, \t6, \x5
323	veor		\x1, \x1, \t1
324	vext.8		\t0, \x4, \x4, #8
325	veor		\t4, \t4, \x3
326	vext.8		\t1, \x5, \x5, #8
327	veor		\t7, \t7, \x6
328	vext.8		\x4, \x3, \x3, #8
329	veor		\t3, \t3, \x2
330	vext.8		\x5, \x7, \x7, #8
331	veor		\t4, \t4, \x7
332	vext.8		\x3, \x6, \x6, #8
333	veor		\t3, \t3, \x7
334	vext.8		\x6, \x2, \x2, #8
335	veor		\x7, \t1, \t5
336	.ifb		\inv
337	veor		\x2, \t0, \t4
338	veor		\x4, \x4, \t3
339	veor		\x5, \x5, \t7
340	veor		\x3, \x3, \t6
341	veor		\x6, \x6, \t2
342	.else
343	veor		\t3, \t3, \x4
344	veor		\x5, \x5, \t7
345	veor		\x2, \x3, \t6
346	veor		\x3, \t0, \t4
347	veor		\x4, \x6, \t2
348	vmov		\x6, \t3
349	.endif
350	.endm
351
352	.macro		inv_mix_cols, x0, x1, x2, x3, x4, x5, x6, x7, \
353				      t0, t1, t2, t3, t4, t5, t6, t7
354	vld1.8		{\t0-\t1}, [bskey, :256]!
355	veor		\x0, \x0, \t0
356	vld1.8		{\t2-\t3}, [bskey, :256]!
357	veor		\x1, \x1, \t1
358	vld1.8		{\t4-\t5}, [bskey, :256]!
359	veor		\x2, \x2, \t2
360	vld1.8		{\t6-\t7}, [bskey, :256]
361	sub		bskey, bskey, #224
362	veor		\x3, \x3, \t3
363	veor		\x4, \x4, \t4
364	veor		\x5, \x5, \t5
365	veor		\x6, \x6, \t6
366	veor		\x7, \x7, \t7
367	vext.8		\t0, \x0, \x0, #8
368	vext.8		\t6, \x6, \x6, #8
369	vext.8		\t7, \x7, \x7, #8
370	veor		\t0, \t0, \x0
371	vext.8		\t1, \x1, \x1, #8
372	veor		\t6, \t6, \x6
373	vext.8		\t2, \x2, \x2, #8
374	veor		\t7, \t7, \x7
375	vext.8		\t3, \x3, \x3, #8
376	veor		\t1, \t1, \x1
377	vext.8		\t4, \x4, \x4, #8
378	veor		\t2, \t2, \x2
379	vext.8		\t5, \x5, \x5, #8
380	veor		\t3, \t3, \x3
381	veor		\t4, \t4, \x4
382	veor		\t5, \t5, \x5
383	veor		\x0, \x0, \t6
384	veor		\x1, \x1, \t6
385	veor		\x2, \x2, \t0
386	veor		\x4, \x4, \t2
387	veor		\x3, \x3, \t1
388	veor		\x1, \x1, \t7
389	veor		\x2, \x2, \t7
390	veor		\x4, \x4, \t6
391	veor		\x5, \x5, \t3
392	veor		\x3, \x3, \t6
393	veor		\x6, \x6, \t4
394	veor		\x4, \x4, \t7
395	veor		\x5, \x5, \t7
396	veor		\x7, \x7, \t5
397	mix_cols	\x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \
398			\t0, \t1, \t2, \t3, \t4, \t5, \t6, \t7, 1
399	.endm
400
401	.macro		swapmove_2x, a0, b0, a1, b1, n, mask, t0, t1
402	vshr.u64	\t0, \b0, #\n
403	vshr.u64	\t1, \b1, #\n
404	veor		\t0, \t0, \a0
405	veor		\t1, \t1, \a1
406	vand		\t0, \t0, \mask
407	vand		\t1, \t1, \mask
408	veor		\a0, \a0, \t0
409	vshl.s64	\t0, \t0, #\n
410	veor		\a1, \a1, \t1
411	vshl.s64	\t1, \t1, #\n
412	veor		\b0, \b0, \t0
413	veor		\b1, \b1, \t1
414	.endm
415
416	.macro		bitslice, x7, x6, x5, x4, x3, x2, x1, x0, t0, t1, t2, t3
417	vmov.i8		\t0, #0x55
418	vmov.i8		\t1, #0x33
419	swapmove_2x	\x0, \x1, \x2, \x3, 1, \t0, \t2, \t3
420	swapmove_2x	\x4, \x5, \x6, \x7, 1, \t0, \t2, \t3
421	vmov.i8		\t0, #0x0f
422	swapmove_2x	\x0, \x2, \x1, \x3, 2, \t1, \t2, \t3
423	swapmove_2x	\x4, \x6, \x5, \x7, 2, \t1, \t2, \t3
424	swapmove_2x	\x0, \x4, \x1, \x5, 4, \t0, \t2, \t3
425	swapmove_2x	\x2, \x6, \x3, \x7, 4, \t0, \t2, \t3
426	.endm
427
428	.align		4
429M0:	.quad		0x02060a0e03070b0f, 0x0004080c0105090d
430
431	/*
432	 * void aesbs_convert_key(u8 out[], u32 const rk[], int rounds)
433	 */
434ENTRY(aesbs_convert_key)
435	vld1.32		{q7}, [r1]!		// load round 0 key
436	vld1.32		{q15}, [r1]!		// load round 1 key
437
438	vmov.i8		q8,  #0x01		// bit masks
439	vmov.i8		q9,  #0x02
440	vmov.i8		q10, #0x04
441	vmov.i8		q11, #0x08
442	vmov.i8		q12, #0x10
443	vmov.i8		q13, #0x20
444	__ldr		q14, M0
445
446	sub		r2, r2, #1
447	vst1.8		{q7}, [r0, :128]!	// save round 0 key
448
449.Lkey_loop:
450	__tbl		q7, q15, q14
451	vmov.i8		q6, #0x40
452	vmov.i8		q15, #0x80
453
454	vtst.8		q0, q7, q8
455	vtst.8		q1, q7, q9
456	vtst.8		q2, q7, q10
457	vtst.8		q3, q7, q11
458	vtst.8		q4, q7, q12
459	vtst.8		q5, q7, q13
460	vtst.8		q6, q7, q6
461	vtst.8		q7, q7, q15
462	vld1.32		{q15}, [r1]!		// load next round key
463	vmvn		q0, q0
464	vmvn		q1, q1
465	vmvn		q5, q5
466	vmvn		q6, q6
467
468	subs		r2, r2, #1
469	vst1.8		{q0-q1}, [r0, :256]!
470	vst1.8		{q2-q3}, [r0, :256]!
471	vst1.8		{q4-q5}, [r0, :256]!
472	vst1.8		{q6-q7}, [r0, :256]!
473	bne		.Lkey_loop
474
475	vmov.i8		q7, #0x63		// compose .L63
476	veor		q15, q15, q7
477	vst1.8		{q15}, [r0, :128]
478	bx		lr
479ENDPROC(aesbs_convert_key)
480
481	.align		4
482M0SR:	.quad		0x0a0e02060f03070b, 0x0004080c05090d01
483
484aesbs_encrypt8:
485	vld1.8		{q9}, [bskey, :128]!	// round 0 key
486	__ldr		q8, M0SR
487
488	veor		q10, q0, q9		// xor with round0 key
489	veor		q11, q1, q9
490	__tbl		q0, q10, q8
491	veor		q12, q2, q9
492	__tbl		q1, q11, q8
493	veor		q13, q3, q9
494	__tbl		q2, q12, q8
495	veor		q14, q4, q9
496	__tbl		q3, q13, q8
497	veor		q15, q5, q9
498	__tbl		q4, q14, q8
499	veor		q10, q6, q9
500	__tbl		q5, q15, q8
501	veor		q11, q7, q9
502	__tbl		q6, q10, q8
503	__tbl		q7, q11, q8
504
505	bitslice	q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11
506
507	sub		rounds, rounds, #1
508	b		.Lenc_sbox
509
510	.align		5
511SR:	.quad		0x0504070600030201, 0x0f0e0d0c0a09080b
512SRM0:	.quad		0x0304090e00050a0f, 0x01060b0c0207080d
513
514.Lenc_last:
515	__ldr		q12, SRM0
516.Lenc_loop:
517	shift_rows	q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12
518.Lenc_sbox:
519	sbox		q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, \
520								q13, q14, q15
521	subs		rounds, rounds, #1
522	bcc		.Lenc_done
523
524	mix_cols	q0, q1, q4, q6, q3, q7, q2, q5, q8, q9, q10, q11, q12, \
525								q13, q14, q15
526
527	beq		.Lenc_last
528	__ldr		q12, SR
529	b		.Lenc_loop
530
531.Lenc_done:
532	vld1.8		{q12}, [bskey, :128]	// last round key
533
534	bitslice	q0, q1, q4, q6, q3, q7, q2, q5, q8, q9, q10, q11
535
536	veor		q0, q0, q12
537	veor		q1, q1, q12
538	veor		q4, q4, q12
539	veor		q6, q6, q12
540	veor		q3, q3, q12
541	veor		q7, q7, q12
542	veor		q2, q2, q12
543	veor		q5, q5, q12
544	bx		lr
545ENDPROC(aesbs_encrypt8)
546
547	.align		4
548M0ISR:	.quad		0x0a0e0206070b0f03, 0x0004080c0d010509
549
550aesbs_decrypt8:
551	add		bskey, bskey, rounds, lsl #7
552	sub		bskey, bskey, #112
553	vld1.8		{q9}, [bskey, :128]	// round 0 key
554	sub		bskey, bskey, #128
555	__ldr		q8, M0ISR
556
557	veor		q10, q0, q9		// xor with round0 key
558	veor		q11, q1, q9
559	__tbl		q0, q10, q8
560	veor		q12, q2, q9
561	__tbl		q1, q11, q8
562	veor		q13, q3, q9
563	__tbl		q2, q12, q8
564	veor		q14, q4, q9
565	__tbl		q3, q13, q8
566	veor		q15, q5, q9
567	__tbl		q4, q14, q8
568	veor		q10, q6, q9
569	__tbl		q5, q15, q8
570	veor		q11, q7, q9
571	__tbl		q6, q10, q8
572	__tbl		q7, q11, q8
573
574	bitslice	q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11
575
576	sub		rounds, rounds, #1
577	b		.Ldec_sbox
578
579	.align		5
580ISR:	.quad		0x0504070602010003, 0x0f0e0d0c080b0a09
581ISRM0:	.quad		0x01040b0e0205080f, 0x0306090c00070a0d
582
583.Ldec_last:
584	__ldr		q12, ISRM0
585.Ldec_loop:
586	inv_shift_rows	q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12
587.Ldec_sbox:
588	inv_sbox	q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, \
589								q13, q14, q15
590	subs		rounds, rounds, #1
591	bcc		.Ldec_done
592
593	inv_mix_cols	q0, q1, q6, q4, q2, q7, q3, q5, q8, q9, q10, q11, q12, \
594								q13, q14, q15
595
596	beq		.Ldec_last
597	__ldr		q12, ISR
598	b		.Ldec_loop
599
600.Ldec_done:
601	add		bskey, bskey, #112
602	vld1.8		{q12}, [bskey, :128]	// last round key
603
604	bitslice	q0, q1, q6, q4, q2, q7, q3, q5, q8, q9, q10, q11
605
606	veor		q0, q0, q12
607	veor		q1, q1, q12
608	veor		q6, q6, q12
609	veor		q4, q4, q12
610	veor		q2, q2, q12
611	veor		q7, q7, q12
612	veor		q3, q3, q12
613	veor		q5, q5, q12
614	bx		lr
615ENDPROC(aesbs_decrypt8)
616
617	/*
618	 * aesbs_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
619	 *		     int blocks)
620	 * aesbs_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
621	 *		     int blocks)
622	 */
623	.macro		__ecb_crypt, do8, o0, o1, o2, o3, o4, o5, o6, o7
624	push		{r4-r6, lr}
625	ldr		r5, [sp, #16]		// number of blocks
626
62799:	adr		ip, 0f
628	and		lr, r5, #7
629	cmp		r5, #8
630	sub		ip, ip, lr, lsl #2
631	movlt		pc, ip			// computed goto if blocks < 8
632
633	vld1.8		{q0}, [r1]!
634	vld1.8		{q1}, [r1]!
635	vld1.8		{q2}, [r1]!
636	vld1.8		{q3}, [r1]!
637	vld1.8		{q4}, [r1]!
638	vld1.8		{q5}, [r1]!
639	vld1.8		{q6}, [r1]!
640	vld1.8		{q7}, [r1]!
641
6420:	mov		bskey, r2
643	mov		rounds, r3
644	bl		\do8
645
646	adr		ip, 1f
647	and		lr, r5, #7
648	cmp		r5, #8
649	sub		ip, ip, lr, lsl #2
650	movlt		pc, ip			// computed goto if blocks < 8
651
652	vst1.8		{\o0}, [r0]!
653	vst1.8		{\o1}, [r0]!
654	vst1.8		{\o2}, [r0]!
655	vst1.8		{\o3}, [r0]!
656	vst1.8		{\o4}, [r0]!
657	vst1.8		{\o5}, [r0]!
658	vst1.8		{\o6}, [r0]!
659	vst1.8		{\o7}, [r0]!
660
6611:	subs		r5, r5, #8
662	bgt		99b
663
664	pop		{r4-r6, pc}
665	.endm
666
667	.align		4
668ENTRY(aesbs_ecb_encrypt)
669	__ecb_crypt	aesbs_encrypt8, q0, q1, q4, q6, q3, q7, q2, q5
670ENDPROC(aesbs_ecb_encrypt)
671
672	.align		4
673ENTRY(aesbs_ecb_decrypt)
674	__ecb_crypt	aesbs_decrypt8, q0, q1, q6, q4, q2, q7, q3, q5
675ENDPROC(aesbs_ecb_decrypt)
676
677	/*
678	 * aesbs_cbc_decrypt(u8 out[], u8 const in[], u8 const rk[],
679	 *		     int rounds, int blocks, u8 iv[])
680	 */
681	.align		4
682ENTRY(aesbs_cbc_decrypt)
683	mov		ip, sp
684	push		{r4-r6, lr}
685	ldm		ip, {r5-r6}		// load args 4-5
686
68799:	adr		ip, 0f
688	and		lr, r5, #7
689	cmp		r5, #8
690	sub		ip, ip, lr, lsl #2
691	mov		lr, r1
692	movlt		pc, ip			// computed goto if blocks < 8
693
694	vld1.8		{q0}, [lr]!
695	vld1.8		{q1}, [lr]!
696	vld1.8		{q2}, [lr]!
697	vld1.8		{q3}, [lr]!
698	vld1.8		{q4}, [lr]!
699	vld1.8		{q5}, [lr]!
700	vld1.8		{q6}, [lr]!
701	vld1.8		{q7}, [lr]
702
7030:	mov		bskey, r2
704	mov		rounds, r3
705	bl		aesbs_decrypt8
706
707	vld1.8		{q8}, [r6]
708	vmov		q9, q8
709	vmov		q10, q8
710	vmov		q11, q8
711	vmov		q12, q8
712	vmov		q13, q8
713	vmov		q14, q8
714	vmov		q15, q8
715
716	adr		ip, 1f
717	and		lr, r5, #7
718	cmp		r5, #8
719	sub		ip, ip, lr, lsl #2
720	movlt		pc, ip			// computed goto if blocks < 8
721
722	vld1.8		{q9}, [r1]!
723	vld1.8		{q10}, [r1]!
724	vld1.8		{q11}, [r1]!
725	vld1.8		{q12}, [r1]!
726	vld1.8		{q13}, [r1]!
727	vld1.8		{q14}, [r1]!
728	vld1.8		{q15}, [r1]!
729	W(nop)
730
7311:	adr		ip, 2f
732	sub		ip, ip, lr, lsl #3
733	movlt		pc, ip			// computed goto if blocks < 8
734
735	veor		q0, q0, q8
736	vst1.8		{q0}, [r0]!
737	veor		q1, q1, q9
738	vst1.8		{q1}, [r0]!
739	veor		q6, q6, q10
740	vst1.8		{q6}, [r0]!
741	veor		q4, q4, q11
742	vst1.8		{q4}, [r0]!
743	veor		q2, q2, q12
744	vst1.8		{q2}, [r0]!
745	veor		q7, q7, q13
746	vst1.8		{q7}, [r0]!
747	veor		q3, q3, q14
748	vst1.8		{q3}, [r0]!
749	veor		q5, q5, q15
750	vld1.8		{q8}, [r1]!		// load next round's iv
7512:	vst1.8		{q5}, [r0]!
752
753	subs		r5, r5, #8
754	vst1.8		{q8}, [r6]		// store next round's iv
755	bgt		99b
756
757	pop		{r4-r6, pc}
758ENDPROC(aesbs_cbc_decrypt)
759
760	.macro		next_ctr, q
761	vmov		\q\()h, r9, r10
762	adds		r10, r10, #1
763	adcs		r9, r9, #0
764	vmov		\q\()l, r7, r8
765	adcs		r8, r8, #0
766	adc		r7, r7, #0
767	vrev32.8	\q, \q
768	.endm
769
770	/*
771	 * aesbs_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[],
772	 *		     int rounds, int bytes, u8 ctr[])
773	 */
774ENTRY(aesbs_ctr_encrypt)
775	mov		ip, sp
776	push		{r4-r10, lr}
777
778	ldm		ip, {r5, r6}		// load args 4-5
779	vld1.8		{q0}, [r6]		// load counter
780	vrev32.8	q1, q0
781	vmov		r9, r10, d3
782	vmov		r7, r8, d2
783
784	adds		r10, r10, #1
785	adcs		r9, r9, #0
786	adcs		r8, r8, #0
787	adc		r7, r7, #0
788
78999:	vmov		q1, q0
790	sub		lr, r5, #1
791	vmov		q2, q0
792	adr		ip, 0f
793	vmov		q3, q0
794	and		lr, lr, #112
795	vmov		q4, q0
796	cmp		r5, #112
797	vmov		q5, q0
798	sub		ip, ip, lr, lsl #1
799	vmov		q6, q0
800	add		ip, ip, lr, lsr #2
801	vmov		q7, q0
802	movle		pc, ip			// computed goto if bytes < 112
803
804	next_ctr	q1
805	next_ctr	q2
806	next_ctr	q3
807	next_ctr	q4
808	next_ctr	q5
809	next_ctr	q6
810	next_ctr	q7
811
8120:	mov		bskey, r2
813	mov		rounds, r3
814	bl		aesbs_encrypt8
815
816	adr		ip, 1f
817	sub		lr, r5, #1
818	cmp		r5, #128
819	bic		lr, lr, #15
820	ands		r4, r5, #15		// preserves C flag
821	teqcs		r5, r5			// set Z flag if not last iteration
822	sub		ip, ip, lr, lsr #2
823	rsb		r4, r4, #16
824	movcc		pc, ip			// computed goto if bytes < 128
825
826	vld1.8		{q8}, [r1]!
827	vld1.8		{q9}, [r1]!
828	vld1.8		{q10}, [r1]!
829	vld1.8		{q11}, [r1]!
830	vld1.8		{q12}, [r1]!
831	vld1.8		{q13}, [r1]!
832	vld1.8		{q14}, [r1]!
8331:	subne		r1, r1, r4
834	vld1.8		{q15}, [r1]!
835
836	add		ip, ip, #2f - 1b
837
838	veor		q0, q0, q8
839	veor		q1, q1, q9
840	veor		q4, q4, q10
841	veor		q6, q6, q11
842	veor		q3, q3, q12
843	veor		q7, q7, q13
844	veor		q2, q2, q14
845	bne		3f
846	veor		q5, q5, q15
847
848	movcc		pc, ip			// computed goto if bytes < 128
849
850	vst1.8		{q0}, [r0]!
851	vst1.8		{q1}, [r0]!
852	vst1.8		{q4}, [r0]!
853	vst1.8		{q6}, [r0]!
854	vst1.8		{q3}, [r0]!
855	vst1.8		{q7}, [r0]!
856	vst1.8		{q2}, [r0]!
8572:	subne		r0, r0, r4
858	vst1.8		{q5}, [r0]!
859
860	next_ctr	q0
861
862	subs		r5, r5, #128
863	bgt		99b
864
865	vst1.8		{q0}, [r6]
866	pop		{r4-r10, pc}
867
8683:	adr		lr, .Lpermute_table + 16
869	cmp		r5, #16			// Z flag remains cleared
870	sub		lr, lr, r4
871	vld1.8		{q8-q9}, [lr]
872	vtbl.8		d16, {q5}, d16
873	vtbl.8		d17, {q5}, d17
874	veor		q5, q8, q15
875	bcc		4f			// have to reload prev if R5 < 16
876	vtbx.8		d10, {q2}, d18
877	vtbx.8		d11, {q2}, d19
878	mov		pc, ip			// branch back to VST sequence
879
8804:	sub		r0, r0, r4
881	vshr.s8		q9, q9, #7		// create mask for VBIF
882	vld1.8		{q8}, [r0]		// reload
883	vbif		q5, q8, q9
884	vst1.8		{q5}, [r0]
885	pop		{r4-r10, pc}
886ENDPROC(aesbs_ctr_encrypt)
887
888	.align		6
889.Lpermute_table:
890	.byte		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
891	.byte		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
892	.byte		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
893	.byte		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
894	.byte		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
895	.byte		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
896
897	.macro		next_tweak, out, in, const, tmp
898	vshr.s64	\tmp, \in, #63
899	vand		\tmp, \tmp, \const
900	vadd.u64	\out, \in, \in
901	vext.8		\tmp, \tmp, \tmp, #8
902	veor		\out, \out, \tmp
903	.endm
904
905	/*
906	 * aesbs_xts_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
907	 *		     int blocks, u8 iv[], int reorder_last_tweak)
908	 * aesbs_xts_decrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
909	 *		     int blocks, u8 iv[], int reorder_last_tweak)
910	 */
911	.align		6
912__xts_prepare8:
913	vld1.8		{q14}, [r7]		// load iv
914	vmov.i32	d30, #0x87		// compose tweak mask vector
915	vmovl.u32	q15, d30
916	vshr.u64	d30, d31, #7
917	vmov		q12, q14
918
919	adr		ip, 0f
920	and		r4, r6, #7
921	cmp		r6, #8
922	sub		ip, ip, r4, lsl #5
923	mov		r4, sp
924	movlt		pc, ip			// computed goto if blocks < 8
925
926	vld1.8		{q0}, [r1]!
927	next_tweak	q12, q14, q15, q13
928	veor		q0, q0, q14
929	vst1.8		{q14}, [r4, :128]!
930
931	vld1.8		{q1}, [r1]!
932	next_tweak	q14, q12, q15, q13
933	veor		q1, q1, q12
934	vst1.8		{q12}, [r4, :128]!
935
936	vld1.8		{q2}, [r1]!
937	next_tweak	q12, q14, q15, q13
938	veor		q2, q2, q14
939	vst1.8		{q14}, [r4, :128]!
940
941	vld1.8		{q3}, [r1]!
942	next_tweak	q14, q12, q15, q13
943	veor		q3, q3, q12
944	vst1.8		{q12}, [r4, :128]!
945
946	vld1.8		{q4}, [r1]!
947	next_tweak	q12, q14, q15, q13
948	veor		q4, q4, q14
949	vst1.8		{q14}, [r4, :128]!
950
951	vld1.8		{q5}, [r1]!
952	next_tweak	q14, q12, q15, q13
953	veor		q5, q5, q12
954	vst1.8		{q12}, [r4, :128]!
955
956	vld1.8		{q6}, [r1]!
957	next_tweak	q12, q14, q15, q13
958	veor		q6, q6, q14
959	vst1.8		{q14}, [r4, :128]!
960
961	vld1.8		{q7}, [r1]!
962	next_tweak	q14, q12, q15, q13
963THUMB(	itt		le		)
964	W(cmple)	r8, #0
965	ble		1f
9660:	veor		q7, q7, q12
967	vst1.8		{q12}, [r4, :128]
968
969	vst1.8		{q14}, [r7]		// store next iv
970	bx		lr
971
9721:	vswp		q12, q14
973	b		0b
974ENDPROC(__xts_prepare8)
975
976	.macro		__xts_crypt, do8, o0, o1, o2, o3, o4, o5, o6, o7
977	push		{r4-r8, lr}
978	mov		r5, sp			// preserve sp
979	ldrd		r6, r7, [sp, #24]	// get blocks and iv args
980	rsb		r8, ip, #1
981	sub		ip, sp, #128		// make room for 8x tweak
982	bic		ip, ip, #0xf		// align sp to 16 bytes
983	mov		sp, ip
984
98599:	bl		__xts_prepare8
986
987	mov		bskey, r2
988	mov		rounds, r3
989	bl		\do8
990
991	adr		ip, 0f
992	and		lr, r6, #7
993	cmp		r6, #8
994	sub		ip, ip, lr, lsl #2
995	mov		r4, sp
996	movlt		pc, ip			// computed goto if blocks < 8
997
998	vld1.8		{q8}, [r4, :128]!
999	vld1.8		{q9}, [r4, :128]!
1000	vld1.8		{q10}, [r4, :128]!
1001	vld1.8		{q11}, [r4, :128]!
1002	vld1.8		{q12}, [r4, :128]!
1003	vld1.8		{q13}, [r4, :128]!
1004	vld1.8		{q14}, [r4, :128]!
1005	vld1.8		{q15}, [r4, :128]
1006
10070:	adr		ip, 1f
1008	sub		ip, ip, lr, lsl #3
1009	movlt		pc, ip			// computed goto if blocks < 8
1010
1011	veor		\o0, \o0, q8
1012	vst1.8		{\o0}, [r0]!
1013	veor		\o1, \o1, q9
1014	vst1.8		{\o1}, [r0]!
1015	veor		\o2, \o2, q10
1016	vst1.8		{\o2}, [r0]!
1017	veor		\o3, \o3, q11
1018	vst1.8		{\o3}, [r0]!
1019	veor		\o4, \o4, q12
1020	vst1.8		{\o4}, [r0]!
1021	veor		\o5, \o5, q13
1022	vst1.8		{\o5}, [r0]!
1023	veor		\o6, \o6, q14
1024	vst1.8		{\o6}, [r0]!
1025	veor		\o7, \o7, q15
1026	vst1.8		{\o7}, [r0]!
1027
10281:	subs		r6, r6, #8
1029	bgt		99b
1030
1031	mov		sp, r5
1032	pop		{r4-r8, pc}
1033	.endm
1034
1035ENTRY(aesbs_xts_encrypt)
1036	mov		ip, #0			// never reorder final tweak
1037	__xts_crypt	aesbs_encrypt8, q0, q1, q4, q6, q3, q7, q2, q5
1038ENDPROC(aesbs_xts_encrypt)
1039
1040ENTRY(aesbs_xts_decrypt)
1041	ldr		ip, [sp, #8]		// reorder final tweak?
1042	__xts_crypt	aesbs_decrypt8, q0, q1, q6, q4, q2, q7, q3, q5
1043ENDPROC(aesbs_xts_decrypt)
1044