1#! /usr/bin/env perl
2# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     https://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
17# ====================================================================
18# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
19# project.
20#
21# Specific modes and adaptation for Linux kernel by Ard Biesheuvel
22# of Linaro.
23# ====================================================================
24
25# Bit-sliced AES for ARM NEON
26#
27# February 2012.
28#
29# This implementation is direct adaptation of bsaes-x86_64 module for
30# ARM NEON. Except that this module is endian-neutral [in sense that
31# it can be compiled for either endianness] by courtesy of vld1.8's
32# neutrality. Initial version doesn't implement interface to OpenSSL,
33# only low-level primitives and unsupported entry points, just enough
34# to collect performance results, which for Cortex-A8 core are:
35#
36# encrypt	19.5 cycles per byte processed with 128-bit key
37# decrypt	22.1 cycles per byte processed with 128-bit key
38# key conv.	440  cycles per 128-bit key/0.18 of 8x block
39#
40# Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7,
41# which is [much] worse than anticipated (for further details see
42# http://www.openssl.org/~appro/Snapdragon-S4.html).
43#
44# Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code
45# manages in 20.0 cycles].
46#
47# When comparing to x86_64 results keep in mind that NEON unit is
48# [mostly] single-issue and thus can't [fully] benefit from
49# instruction-level parallelism. And when comparing to aes-armv4
50# results keep in mind key schedule conversion overhead (see
51# bsaes-x86_64.pl for further details)...
52#
53#						<appro@openssl.org>
54
55# April-August 2013
56# Add CBC, CTR and XTS subroutines and adapt for kernel use; courtesy of Ard.
57
58$flavour = shift;
59if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
60else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
61
62if ($flavour && $flavour ne "void") {
63    $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
64    ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
65    ( $xlate="${dir}../../../perlasm/arm-xlate.pl" and -f $xlate) or
66    die "can't locate arm-xlate.pl";
67
68    open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
69    *STDOUT=*OUT;
70} else {
71    open OUT,">$output";
72    *STDOUT=*OUT;
73}
74
75my ($inp,$out,$len,$key)=("r0","r1","r2","r3");
76my @XMM=map("q$_",(0..15));
77
78{
79my ($key,$rounds,$const)=("r4","r5","r6");
80
81sub Dlo()   { shift=~m|q([1]?[0-9])|?"d".($1*2):"";     }
82sub Dhi()   { shift=~m|q([1]?[0-9])|?"d".($1*2+1):"";   }
83
84sub Sbox {
85# input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
86# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
87my @b=@_[0..7];
88my @t=@_[8..11];
89my @s=@_[12..15];
90	&InBasisChange	(@b);
91	&Inv_GF256	(@b[6,5,0,3,7,1,4,2],@t,@s);
92	&OutBasisChange	(@b[7,1,4,2,6,5,0,3]);
93}
94
95sub InBasisChange {
96# input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
97# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
98my @b=@_[0..7];
99$code.=<<___;
100	veor	@b[2], @b[2], @b[1]
101	veor	@b[5], @b[5], @b[6]
102	veor	@b[3], @b[3], @b[0]
103	veor	@b[6], @b[6], @b[2]
104	veor	@b[5], @b[5], @b[0]
105
106	veor	@b[6], @b[6], @b[3]
107	veor	@b[3], @b[3], @b[7]
108	veor	@b[7], @b[7], @b[5]
109	veor	@b[3], @b[3], @b[4]
110	veor	@b[4], @b[4], @b[5]
111
112	veor	@b[2], @b[2], @b[7]
113	veor	@b[3], @b[3], @b[1]
114	veor	@b[1], @b[1], @b[5]
115___
116}
117
118sub OutBasisChange {
119# input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
120# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
121my @b=@_[0..7];
122$code.=<<___;
123	veor	@b[0], @b[0], @b[6]
124	veor	@b[1], @b[1], @b[4]
125	veor	@b[4], @b[4], @b[6]
126	veor	@b[2], @b[2], @b[0]
127	veor	@b[6], @b[6], @b[1]
128
129	veor	@b[1], @b[1], @b[5]
130	veor	@b[5], @b[5], @b[3]
131	veor	@b[3], @b[3], @b[7]
132	veor	@b[7], @b[7], @b[5]
133	veor	@b[2], @b[2], @b[5]
134
135	veor	@b[4], @b[4], @b[7]
136___
137}
138
139sub InvSbox {
140# input in lsb 	> [b0, b1, b2, b3, b4, b5, b6, b7] < msb
141# output in lsb	> [b0, b1, b6, b4, b2, b7, b3, b5] < msb
142my @b=@_[0..7];
143my @t=@_[8..11];
144my @s=@_[12..15];
145	&InvInBasisChange	(@b);
146	&Inv_GF256		(@b[5,1,2,6,3,7,0,4],@t,@s);
147	&InvOutBasisChange	(@b[3,7,0,4,5,1,2,6]);
148}
149
150sub InvInBasisChange {		# OutBasisChange in reverse (with twist)
151my @b=@_[5,1,2,6,3,7,0,4];
152$code.=<<___
153	 veor	@b[1], @b[1], @b[7]
154	veor	@b[4], @b[4], @b[7]
155
156	veor	@b[7], @b[7], @b[5]
157	 veor	@b[1], @b[1], @b[3]
158	veor	@b[2], @b[2], @b[5]
159	veor	@b[3], @b[3], @b[7]
160
161	veor	@b[6], @b[6], @b[1]
162	veor	@b[2], @b[2], @b[0]
163	 veor	@b[5], @b[5], @b[3]
164	veor	@b[4], @b[4], @b[6]
165	veor	@b[0], @b[0], @b[6]
166	veor	@b[1], @b[1], @b[4]
167___
168}
169
170sub InvOutBasisChange {		# InBasisChange in reverse
171my @b=@_[2,5,7,3,6,1,0,4];
172$code.=<<___;
173	veor	@b[1], @b[1], @b[5]
174	veor	@b[2], @b[2], @b[7]
175
176	veor	@b[3], @b[3], @b[1]
177	veor	@b[4], @b[4], @b[5]
178	veor	@b[7], @b[7], @b[5]
179	veor	@b[3], @b[3], @b[4]
180	 veor 	@b[5], @b[5], @b[0]
181	veor	@b[3], @b[3], @b[7]
182	 veor	@b[6], @b[6], @b[2]
183	 veor	@b[2], @b[2], @b[1]
184	veor	@b[6], @b[6], @b[3]
185
186	veor	@b[3], @b[3], @b[0]
187	veor	@b[5], @b[5], @b[6]
188___
189}
190
191sub Mul_GF4 {
192#;*************************************************************
193#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
194#;*************************************************************
195my ($x0,$x1,$y0,$y1,$t0,$t1)=@_;
196$code.=<<___;
197	veor 	$t0, $y0, $y1
198	vand	$t0, $t0, $x0
199	veor	$x0, $x0, $x1
200	vand	$t1, $x1, $y0
201	vand	$x0, $x0, $y1
202	veor	$x1, $t1, $t0
203	veor	$x0, $x0, $t1
204___
205}
206
207sub Mul_GF4_N {				# not used, see next subroutine
208# multiply and scale by N
209my ($x0,$x1,$y0,$y1,$t0)=@_;
210$code.=<<___;
211	veor	$t0, $y0, $y1
212	vand	$t0, $t0, $x0
213	veor	$x0, $x0, $x1
214	vand	$x1, $x1, $y0
215	vand	$x0, $x0, $y1
216	veor	$x1, $x1, $x0
217	veor	$x0, $x0, $t0
218___
219}
220
221sub Mul_GF4_N_GF4 {
222# interleaved Mul_GF4_N and Mul_GF4
223my ($x0,$x1,$y0,$y1,$t0,
224    $x2,$x3,$y2,$y3,$t1)=@_;
225$code.=<<___;
226	veor	$t0, $y0, $y1
227	 veor 	$t1, $y2, $y3
228	vand	$t0, $t0, $x0
229	 vand	$t1, $t1, $x2
230	veor	$x0, $x0, $x1
231	 veor	$x2, $x2, $x3
232	vand	$x1, $x1, $y0
233	 vand	$x3, $x3, $y2
234	vand	$x0, $x0, $y1
235	 vand	$x2, $x2, $y3
236	veor	$x1, $x1, $x0
237	 veor	$x2, $x2, $x3
238	veor	$x0, $x0, $t0
239	 veor	$x3, $x3, $t1
240___
241}
242sub Mul_GF16_2 {
243my @x=@_[0..7];
244my @y=@_[8..11];
245my @t=@_[12..15];
246$code.=<<___;
247	veor	@t[0], @x[0], @x[2]
248	veor	@t[1], @x[1], @x[3]
249___
250	&Mul_GF4  	(@x[0], @x[1], @y[0], @y[1], @t[2..3]);
251$code.=<<___;
252	veor	@y[0], @y[0], @y[2]
253	veor	@y[1], @y[1], @y[3]
254___
255	Mul_GF4_N_GF4	(@t[0], @t[1], @y[0], @y[1], @t[3],
256			 @x[2], @x[3], @y[2], @y[3], @t[2]);
257$code.=<<___;
258	veor	@x[0], @x[0], @t[0]
259	veor	@x[2], @x[2], @t[0]
260	veor	@x[1], @x[1], @t[1]
261	veor	@x[3], @x[3], @t[1]
262
263	veor	@t[0], @x[4], @x[6]
264	veor	@t[1], @x[5], @x[7]
265___
266	&Mul_GF4_N_GF4	(@t[0], @t[1], @y[0], @y[1], @t[3],
267			 @x[6], @x[7], @y[2], @y[3], @t[2]);
268$code.=<<___;
269	veor	@y[0], @y[0], @y[2]
270	veor	@y[1], @y[1], @y[3]
271___
272	&Mul_GF4  	(@x[4], @x[5], @y[0], @y[1], @t[2..3]);
273$code.=<<___;
274	veor	@x[4], @x[4], @t[0]
275	veor	@x[6], @x[6], @t[0]
276	veor	@x[5], @x[5], @t[1]
277	veor	@x[7], @x[7], @t[1]
278___
279}
280sub Inv_GF256 {
281#;********************************************************************
282#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144)       *
283#;********************************************************************
284my @x=@_[0..7];
285my @t=@_[8..11];
286my @s=@_[12..15];
287# direct optimizations from hardware
288$code.=<<___;
289	veor	@t[3], @x[4], @x[6]
290	veor	@t[2], @x[5], @x[7]
291	veor	@t[1], @x[1], @x[3]
292	veor	@s[1], @x[7], @x[6]
293	 vmov	@t[0], @t[2]
294	veor	@s[0], @x[0], @x[2]
295
296	vorr	@t[2], @t[2], @t[1]
297	veor	@s[3], @t[3], @t[0]
298	vand	@s[2], @t[3], @s[0]
299	vorr	@t[3], @t[3], @s[0]
300	veor	@s[0], @s[0], @t[1]
301	vand	@t[0], @t[0], @t[1]
302	veor	@t[1], @x[3], @x[2]
303	vand	@s[3], @s[3], @s[0]
304	vand	@s[1], @s[1], @t[1]
305	veor	@t[1], @x[4], @x[5]
306	veor	@s[0], @x[1], @x[0]
307	veor	@t[3], @t[3], @s[1]
308	veor	@t[2], @t[2], @s[1]
309	vand	@s[1], @t[1], @s[0]
310	vorr	@t[1], @t[1], @s[0]
311	veor	@t[3], @t[3], @s[3]
312	veor	@t[0], @t[0], @s[1]
313	veor	@t[2], @t[2], @s[2]
314	veor	@t[1], @t[1], @s[3]
315	veor	@t[0], @t[0], @s[2]
316	vand	@s[0], @x[7], @x[3]
317	veor	@t[1], @t[1], @s[2]
318	vand	@s[1], @x[6], @x[2]
319	vand	@s[2], @x[5], @x[1]
320	vorr	@s[3], @x[4], @x[0]
321	veor	@t[3], @t[3], @s[0]
322	veor	@t[1], @t[1], @s[2]
323	veor	@t[0], @t[0], @s[3]
324	veor	@t[2], @t[2], @s[1]
325
326	@ Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
327
328	@ new smaller inversion
329
330	vand	@s[2], @t[3], @t[1]
331	vmov	@s[0], @t[0]
332
333	veor	@s[1], @t[2], @s[2]
334	veor	@s[3], @t[0], @s[2]
335	veor	@s[2], @t[0], @s[2]	@ @s[2]=@s[3]
336
337	vbsl	@s[1], @t[1], @t[0]
338	vbsl	@s[3], @t[3], @t[2]
339	veor	@t[3], @t[3], @t[2]
340
341	vbsl	@s[0], @s[1], @s[2]
342	vbsl	@t[0], @s[2], @s[1]
343
344	vand	@s[2], @s[0], @s[3]
345	veor	@t[1], @t[1], @t[0]
346
347	veor	@s[2], @s[2], @t[3]
348___
349# output in s3, s2, s1, t1
350
351# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
352
353# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
354	&Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
355
356### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
357}
358
359# AES linear components
360
361sub ShiftRows {
362my @x=@_[0..7];
363my @t=@_[8..11];
364my $mask=pop;
365$code.=<<___;
366	vldmia	$key!, {@t[0]-@t[3]}
367	veor	@t[0], @t[0], @x[0]
368	veor	@t[1], @t[1], @x[1]
369	vtbl.8	`&Dlo(@x[0])`, {@t[0]}, `&Dlo($mask)`
370	vtbl.8	`&Dhi(@x[0])`, {@t[0]}, `&Dhi($mask)`
371	vldmia	$key!, {@t[0]}
372	veor	@t[2], @t[2], @x[2]
373	vtbl.8	`&Dlo(@x[1])`, {@t[1]}, `&Dlo($mask)`
374	vtbl.8	`&Dhi(@x[1])`, {@t[1]}, `&Dhi($mask)`
375	vldmia	$key!, {@t[1]}
376	veor	@t[3], @t[3], @x[3]
377	vtbl.8	`&Dlo(@x[2])`, {@t[2]}, `&Dlo($mask)`
378	vtbl.8	`&Dhi(@x[2])`, {@t[2]}, `&Dhi($mask)`
379	vldmia	$key!, {@t[2]}
380	vtbl.8	`&Dlo(@x[3])`, {@t[3]}, `&Dlo($mask)`
381	vtbl.8	`&Dhi(@x[3])`, {@t[3]}, `&Dhi($mask)`
382	vldmia	$key!, {@t[3]}
383	veor	@t[0], @t[0], @x[4]
384	veor	@t[1], @t[1], @x[5]
385	vtbl.8	`&Dlo(@x[4])`, {@t[0]}, `&Dlo($mask)`
386	vtbl.8	`&Dhi(@x[4])`, {@t[0]}, `&Dhi($mask)`
387	veor	@t[2], @t[2], @x[6]
388	vtbl.8	`&Dlo(@x[5])`, {@t[1]}, `&Dlo($mask)`
389	vtbl.8	`&Dhi(@x[5])`, {@t[1]}, `&Dhi($mask)`
390	veor	@t[3], @t[3], @x[7]
391	vtbl.8	`&Dlo(@x[6])`, {@t[2]}, `&Dlo($mask)`
392	vtbl.8	`&Dhi(@x[6])`, {@t[2]}, `&Dhi($mask)`
393	vtbl.8	`&Dlo(@x[7])`, {@t[3]}, `&Dlo($mask)`
394	vtbl.8	`&Dhi(@x[7])`, {@t[3]}, `&Dhi($mask)`
395___
396}
397
398sub MixColumns {
399# modified to emit output in order suitable for feeding back to aesenc[last]
400my @x=@_[0..7];
401my @t=@_[8..15];
402my $inv=@_[16];	# optional
403$code.=<<___;
404	vext.8	@t[0], @x[0], @x[0], #12	@ x0 <<< 32
405	vext.8	@t[1], @x[1], @x[1], #12
406	 veor	@x[0], @x[0], @t[0]		@ x0 ^ (x0 <<< 32)
407	vext.8	@t[2], @x[2], @x[2], #12
408	 veor	@x[1], @x[1], @t[1]
409	vext.8	@t[3], @x[3], @x[3], #12
410	 veor	@x[2], @x[2], @t[2]
411	vext.8	@t[4], @x[4], @x[4], #12
412	 veor	@x[3], @x[3], @t[3]
413	vext.8	@t[5], @x[5], @x[5], #12
414	 veor	@x[4], @x[4], @t[4]
415	vext.8	@t[6], @x[6], @x[6], #12
416	 veor	@x[5], @x[5], @t[5]
417	vext.8	@t[7], @x[7], @x[7], #12
418	 veor	@x[6], @x[6], @t[6]
419
420	veor	@t[1], @t[1], @x[0]
421	 veor	@x[7], @x[7], @t[7]
422	 vext.8	@x[0], @x[0], @x[0], #8		@ (x0 ^ (x0 <<< 32)) <<< 64)
423	veor	@t[2], @t[2], @x[1]
424	veor	@t[0], @t[0], @x[7]
425	veor	@t[1], @t[1], @x[7]
426	 vext.8	@x[1], @x[1], @x[1], #8
427	veor	@t[5], @t[5], @x[4]
428	 veor	@x[0], @x[0], @t[0]
429	veor	@t[6], @t[6], @x[5]
430	 veor	@x[1], @x[1], @t[1]
431	 vext.8	@t[0], @x[4], @x[4], #8
432	veor	@t[4], @t[4], @x[3]
433	 vext.8	@t[1], @x[5], @x[5], #8
434	veor	@t[7], @t[7], @x[6]
435	 vext.8	@x[4], @x[3], @x[3], #8
436	veor	@t[3], @t[3], @x[2]
437	 vext.8	@x[5], @x[7], @x[7], #8
438	veor	@t[4], @t[4], @x[7]
439	 vext.8	@x[3], @x[6], @x[6], #8
440	veor	@t[3], @t[3], @x[7]
441	 vext.8	@x[6], @x[2], @x[2], #8
442	veor	@x[7], @t[1], @t[5]
443___
444$code.=<<___ if (!$inv);
445	veor	@x[2], @t[0], @t[4]
446	veor	@x[4], @x[4], @t[3]
447	veor	@x[5], @x[5], @t[7]
448	veor	@x[3], @x[3], @t[6]
449	 @ vmov	@x[2], @t[0]
450	veor	@x[6], @x[6], @t[2]
451	 @ vmov	@x[7], @t[1]
452___
453$code.=<<___ if ($inv);
454	veor	@t[3], @t[3], @x[4]
455	veor	@x[5], @x[5], @t[7]
456	veor	@x[2], @x[3], @t[6]
457	veor	@x[3], @t[0], @t[4]
458	veor	@x[4], @x[6], @t[2]
459	vmov	@x[6], @t[3]
460	 @ vmov	@x[7], @t[1]
461___
462}
463
464sub InvMixColumns_orig {
465my @x=@_[0..7];
466my @t=@_[8..15];
467
468$code.=<<___;
469	@ multiplication by 0x0e
470	vext.8	@t[7], @x[7], @x[7], #12
471	vmov	@t[2], @x[2]
472	veor	@x[2], @x[2], @x[5]		@ 2 5
473	veor	@x[7], @x[7], @x[5]		@ 7 5
474	vext.8	@t[0], @x[0], @x[0], #12
475	vmov	@t[5], @x[5]
476	veor	@x[5], @x[5], @x[0]		@ 5 0		[1]
477	veor	@x[0], @x[0], @x[1]		@ 0 1
478	vext.8	@t[1], @x[1], @x[1], #12
479	veor	@x[1], @x[1], @x[2]		@ 1 25
480	veor	@x[0], @x[0], @x[6]		@ 01 6		[2]
481	vext.8	@t[3], @x[3], @x[3], #12
482	veor	@x[1], @x[1], @x[3]		@ 125 3		[4]
483	veor	@x[2], @x[2], @x[0]		@ 25 016	[3]
484	veor	@x[3], @x[3], @x[7]		@ 3 75
485	veor	@x[7], @x[7], @x[6]		@ 75 6		[0]
486	vext.8	@t[6], @x[6], @x[6], #12
487	vmov	@t[4], @x[4]
488	veor	@x[6], @x[6], @x[4]		@ 6 4
489	veor	@x[4], @x[4], @x[3]		@ 4 375		[6]
490	veor	@x[3], @x[3], @x[7]		@ 375 756=36
491	veor	@x[6], @x[6], @t[5]		@ 64 5		[7]
492	veor	@x[3], @x[3], @t[2]		@ 36 2
493	vext.8	@t[5], @t[5], @t[5], #12
494	veor	@x[3], @x[3], @t[4]		@ 362 4		[5]
495___
496					my @y = @x[7,5,0,2,1,3,4,6];
497$code.=<<___;
498	@ multiplication by 0x0b
499	veor	@y[1], @y[1], @y[0]
500	veor	@y[0], @y[0], @t[0]
501	vext.8	@t[2], @t[2], @t[2], #12
502	veor	@y[1], @y[1], @t[1]
503	veor	@y[0], @y[0], @t[5]
504	vext.8	@t[4], @t[4], @t[4], #12
505	veor	@y[1], @y[1], @t[6]
506	veor	@y[0], @y[0], @t[7]
507	veor	@t[7], @t[7], @t[6]		@ clobber t[7]
508
509	veor	@y[3], @y[3], @t[0]
510	 veor	@y[1], @y[1], @y[0]
511	vext.8	@t[0], @t[0], @t[0], #12
512	veor	@y[2], @y[2], @t[1]
513	veor	@y[4], @y[4], @t[1]
514	vext.8	@t[1], @t[1], @t[1], #12
515	veor	@y[2], @y[2], @t[2]
516	veor	@y[3], @y[3], @t[2]
517	veor	@y[5], @y[5], @t[2]
518	veor	@y[2], @y[2], @t[7]
519	vext.8	@t[2], @t[2], @t[2], #12
520	veor	@y[3], @y[3], @t[3]
521	veor	@y[6], @y[6], @t[3]
522	veor	@y[4], @y[4], @t[3]
523	veor	@y[7], @y[7], @t[4]
524	vext.8	@t[3], @t[3], @t[3], #12
525	veor	@y[5], @y[5], @t[4]
526	veor	@y[7], @y[7], @t[7]
527	veor	@t[7], @t[7], @t[5]		@ clobber t[7] even more
528	veor	@y[3], @y[3], @t[5]
529	veor	@y[4], @y[4], @t[4]
530
531	veor	@y[5], @y[5], @t[7]
532	vext.8	@t[4], @t[4], @t[4], #12
533	veor	@y[6], @y[6], @t[7]
534	veor	@y[4], @y[4], @t[7]
535
536	veor	@t[7], @t[7], @t[5]
537	vext.8	@t[5], @t[5], @t[5], #12
538
539	@ multiplication by 0x0d
540	veor	@y[4], @y[4], @y[7]
541	 veor	@t[7], @t[7], @t[6]		@ restore t[7]
542	veor	@y[7], @y[7], @t[4]
543	vext.8	@t[6], @t[6], @t[6], #12
544	veor	@y[2], @y[2], @t[0]
545	veor	@y[7], @y[7], @t[5]
546	vext.8	@t[7], @t[7], @t[7], #12
547	veor	@y[2], @y[2], @t[2]
548
549	veor	@y[3], @y[3], @y[1]
550	veor	@y[1], @y[1], @t[1]
551	veor	@y[0], @y[0], @t[0]
552	veor	@y[3], @y[3], @t[0]
553	veor	@y[1], @y[1], @t[5]
554	veor	@y[0], @y[0], @t[5]
555	vext.8	@t[0], @t[0], @t[0], #12
556	veor	@y[1], @y[1], @t[7]
557	veor	@y[0], @y[0], @t[6]
558	veor	@y[3], @y[3], @y[1]
559	veor	@y[4], @y[4], @t[1]
560	vext.8	@t[1], @t[1], @t[1], #12
561
562	veor	@y[7], @y[7], @t[7]
563	veor	@y[4], @y[4], @t[2]
564	veor	@y[5], @y[5], @t[2]
565	veor	@y[2], @y[2], @t[6]
566	veor	@t[6], @t[6], @t[3]		@ clobber t[6]
567	vext.8	@t[2], @t[2], @t[2], #12
568	veor	@y[4], @y[4], @y[7]
569	veor	@y[3], @y[3], @t[6]
570
571	veor	@y[6], @y[6], @t[6]
572	veor	@y[5], @y[5], @t[5]
573	vext.8	@t[5], @t[5], @t[5], #12
574	veor	@y[6], @y[6], @t[4]
575	vext.8	@t[4], @t[4], @t[4], #12
576	veor	@y[5], @y[5], @t[6]
577	veor	@y[6], @y[6], @t[7]
578	vext.8	@t[7], @t[7], @t[7], #12
579	veor	@t[6], @t[6], @t[3]		@ restore t[6]
580	vext.8	@t[3], @t[3], @t[3], #12
581
582	@ multiplication by 0x09
583	veor	@y[4], @y[4], @y[1]
584	veor	@t[1], @t[1], @y[1]		@ t[1]=y[1]
585	veor	@t[0], @t[0], @t[5]		@ clobber t[0]
586	vext.8	@t[6], @t[6], @t[6], #12
587	veor	@t[1], @t[1], @t[5]
588	veor	@y[3], @y[3], @t[0]
589	veor	@t[0], @t[0], @y[0]		@ t[0]=y[0]
590	veor	@t[1], @t[1], @t[6]
591	veor	@t[6], @t[6], @t[7]		@ clobber t[6]
592	veor	@y[4], @y[4], @t[1]
593	veor	@y[7], @y[7], @t[4]
594	veor	@y[6], @y[6], @t[3]
595	veor	@y[5], @y[5], @t[2]
596	veor	@t[4], @t[4], @y[4]		@ t[4]=y[4]
597	veor	@t[3], @t[3], @y[3]		@ t[3]=y[3]
598	veor	@t[5], @t[5], @y[5]		@ t[5]=y[5]
599	veor	@t[2], @t[2], @y[2]		@ t[2]=y[2]
600	veor	@t[3], @t[3], @t[7]
601	veor	@XMM[5], @t[5], @t[6]
602	veor	@XMM[6], @t[6], @y[6]		@ t[6]=y[6]
603	veor	@XMM[2], @t[2], @t[6]
604	veor	@XMM[7], @t[7], @y[7]		@ t[7]=y[7]
605
606	vmov	@XMM[0], @t[0]
607	vmov	@XMM[1], @t[1]
608	@ vmov	@XMM[2], @t[2]
609	vmov	@XMM[3], @t[3]
610	vmov	@XMM[4], @t[4]
611	@ vmov	@XMM[5], @t[5]
612	@ vmov	@XMM[6], @t[6]
613	@ vmov	@XMM[7], @t[7]
614___
615}
616
617sub InvMixColumns {
618my @x=@_[0..7];
619my @t=@_[8..15];
620
621# Thanks to Jussi Kivilinna for providing pointer to
622#
623# | 0e 0b 0d 09 |   | 02 03 01 01 |   | 05 00 04 00 |
624# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 |
625# | 0d 09 0e 0b |   | 01 01 02 03 |   | 04 00 05 00 |
626# | 0b 0d 09 0e |   | 03 01 01 02 |   | 00 04 00 05 |
627
628$code.=<<___;
629	@ multiplication by 0x05-0x00-0x04-0x00
630	vext.8	@t[0], @x[0], @x[0], #8
631	vext.8	@t[6], @x[6], @x[6], #8
632	vext.8	@t[7], @x[7], @x[7], #8
633	veor	@t[0], @t[0], @x[0]
634	vext.8	@t[1], @x[1], @x[1], #8
635	veor	@t[6], @t[6], @x[6]
636	vext.8	@t[2], @x[2], @x[2], #8
637	veor	@t[7], @t[7], @x[7]
638	vext.8	@t[3], @x[3], @x[3], #8
639	veor	@t[1], @t[1], @x[1]
640	vext.8	@t[4], @x[4], @x[4], #8
641	veor	@t[2], @t[2], @x[2]
642	vext.8	@t[5], @x[5], @x[5], #8
643	veor	@t[3], @t[3], @x[3]
644	veor	@t[4], @t[4], @x[4]
645	veor	@t[5], @t[5], @x[5]
646
647	 veor	@x[0], @x[0], @t[6]
648	 veor	@x[1], @x[1], @t[6]
649	 veor	@x[2], @x[2], @t[0]
650	 veor	@x[4], @x[4], @t[2]
651	 veor	@x[3], @x[3], @t[1]
652	 veor	@x[1], @x[1], @t[7]
653	 veor	@x[2], @x[2], @t[7]
654	 veor	@x[4], @x[4], @t[6]
655	 veor	@x[5], @x[5], @t[3]
656	 veor	@x[3], @x[3], @t[6]
657	 veor	@x[6], @x[6], @t[4]
658	 veor	@x[4], @x[4], @t[7]
659	 veor	@x[5], @x[5], @t[7]
660	 veor	@x[7], @x[7], @t[5]
661___
662	&MixColumns	(@x,@t,1);	# flipped 2<->3 and 4<->6
663}
664
665sub swapmove {
666my ($a,$b,$n,$mask,$t)=@_;
667$code.=<<___;
668	vshr.u64	$t, $b, #$n
669	veor		$t, $t, $a
670	vand		$t, $t, $mask
671	veor		$a, $a, $t
672	vshl.u64	$t, $t, #$n
673	veor		$b, $b, $t
674___
675}
676sub swapmove2x {
677my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
678$code.=<<___;
679	vshr.u64	$t0, $b0, #$n
680	 vshr.u64	$t1, $b1, #$n
681	veor		$t0, $t0, $a0
682	 veor		$t1, $t1, $a1
683	vand		$t0, $t0, $mask
684	 vand		$t1, $t1, $mask
685	veor		$a0, $a0, $t0
686	vshl.u64	$t0, $t0, #$n
687	 veor		$a1, $a1, $t1
688	 vshl.u64	$t1, $t1, #$n
689	veor		$b0, $b0, $t0
690	 veor		$b1, $b1, $t1
691___
692}
693
694sub bitslice {
695my @x=reverse(@_[0..7]);
696my ($t0,$t1,$t2,$t3)=@_[8..11];
697$code.=<<___;
698	vmov.i8	$t0,#0x55			@ compose .LBS0
699	vmov.i8	$t1,#0x33			@ compose .LBS1
700___
701	&swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
702	&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
703$code.=<<___;
704	vmov.i8	$t0,#0x0f			@ compose .LBS2
705___
706	&swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
707	&swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
708
709	&swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
710	&swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
711}
712
713$code.=<<___;
714#ifndef __KERNEL__
715# define VFP_ABI_PUSH	vstmdb	sp!,{d8-d15}
716# define VFP_ABI_POP	vldmia	sp!,{d8-d15}
717# define VFP_ABI_FRAME	0x40
718#else
719# define VFP_ABI_PUSH
720# define VFP_ABI_POP
721# define VFP_ABI_FRAME	0
722# define BSAES_ASM_EXTENDED_KEY
723# define XTS_CHAIN_TWEAK
724# define __ARM_MAX_ARCH__ 7
725#endif
726
727#ifdef __thumb__
728# define adrl adr
729#endif
730
731#if __ARM_MAX_ARCH__>=7
732.arch	armv7-a
733.fpu	neon
734
735.text
736.syntax	unified 	@ ARMv7-capable assembler is expected to handle this
737#if defined(__thumb2__) && !defined(__APPLE__)
738.thumb
739#else
740.code   32
741# undef __thumb2__
742#endif
743
744.type	_bsaes_decrypt8,%function
745.align	4
746_bsaes_decrypt8:
747	adr	$const,.
748	vldmia	$key!, {@XMM[9]}		@ round 0 key
749#if defined(__thumb2__) || defined(__APPLE__)
750	adr	$const,.LM0ISR
751#else
752	add	$const,$const,#.LM0ISR-_bsaes_decrypt8
753#endif
754
755	vldmia	$const!, {@XMM[8]}		@ .LM0ISR
756	veor	@XMM[10], @XMM[0], @XMM[9]	@ xor with round0 key
757	veor	@XMM[11], @XMM[1], @XMM[9]
758	 vtbl.8	`&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
759	 vtbl.8	`&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
760	veor	@XMM[12], @XMM[2], @XMM[9]
761	 vtbl.8	`&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
762	 vtbl.8	`&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
763	veor	@XMM[13], @XMM[3], @XMM[9]
764	 vtbl.8	`&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
765	 vtbl.8	`&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
766	veor	@XMM[14], @XMM[4], @XMM[9]
767	 vtbl.8	`&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
768	 vtbl.8	`&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
769	veor	@XMM[15], @XMM[5], @XMM[9]
770	 vtbl.8	`&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
771	 vtbl.8	`&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
772	veor	@XMM[10], @XMM[6], @XMM[9]
773	 vtbl.8	`&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
774	 vtbl.8	`&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
775	veor	@XMM[11], @XMM[7], @XMM[9]
776	 vtbl.8	`&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
777	 vtbl.8	`&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
778	 vtbl.8	`&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
779	 vtbl.8	`&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
780___
781	&bitslice	(@XMM[0..7, 8..11]);
782$code.=<<___;
783	sub	$rounds,$rounds,#1
784	b	.Ldec_sbox
785.align	4
786.Ldec_loop:
787___
788	&ShiftRows	(@XMM[0..7, 8..12]);
789$code.=".Ldec_sbox:\n";
790	&InvSbox	(@XMM[0..7, 8..15]);
791$code.=<<___;
792	subs	$rounds,$rounds,#1
793	bcc	.Ldec_done
794___
795	&InvMixColumns	(@XMM[0,1,6,4,2,7,3,5, 8..15]);
796$code.=<<___;
797	vldmia	$const, {@XMM[12]}		@ .LISR
798	ite	eq				@ Thumb2 thing, sanity check in ARM
799	addeq	$const,$const,#0x10
800	bne	.Ldec_loop
801	vldmia	$const, {@XMM[12]}		@ .LISRM0
802	b	.Ldec_loop
803.align	4
804.Ldec_done:
805___
806	&bitslice	(@XMM[0,1,6,4,2,7,3,5, 8..11]);
807$code.=<<___;
808	vldmia	$key, {@XMM[8]}			@ last round key
809	veor	@XMM[6], @XMM[6], @XMM[8]
810	veor	@XMM[4], @XMM[4], @XMM[8]
811	veor	@XMM[2], @XMM[2], @XMM[8]
812	veor	@XMM[7], @XMM[7], @XMM[8]
813	veor	@XMM[3], @XMM[3], @XMM[8]
814	veor	@XMM[5], @XMM[5], @XMM[8]
815	veor	@XMM[0], @XMM[0], @XMM[8]
816	veor	@XMM[1], @XMM[1], @XMM[8]
817	bx	lr
818.size	_bsaes_decrypt8,.-_bsaes_decrypt8
819
820.type	_bsaes_const,%object
821.align	6
822_bsaes_const:
823.LM0ISR:	@ InvShiftRows constants
824	.quad	0x0a0e0206070b0f03, 0x0004080c0d010509
825.LISR:
826	.quad	0x0504070602010003, 0x0f0e0d0c080b0a09
827.LISRM0:
828	.quad	0x01040b0e0205080f, 0x0306090c00070a0d
829.LM0SR:		@ ShiftRows constants
830	.quad	0x0a0e02060f03070b, 0x0004080c05090d01
831.LSR:
832	.quad	0x0504070600030201, 0x0f0e0d0c0a09080b
833.LSRM0:
834	.quad	0x0304090e00050a0f, 0x01060b0c0207080d
835.LM0:
836	.quad	0x02060a0e03070b0f, 0x0004080c0105090d
837.LREVM0SR:
838	.quad	0x090d01050c000408, 0x03070b0f060a0e02
839.asciz	"Bit-sliced AES for NEON, CRYPTOGAMS by <appro\@openssl.org>"
840.align	6
841.size	_bsaes_const,.-_bsaes_const
842
843.type	_bsaes_encrypt8,%function
844.align	4
845_bsaes_encrypt8:
846	adr	$const,.
847	vldmia	$key!, {@XMM[9]}		@ round 0 key
848#if defined(__thumb2__) || defined(__APPLE__)
849	adr	$const,.LM0SR
850#else
851	sub	$const,$const,#_bsaes_encrypt8-.LM0SR
852#endif
853
854	vldmia	$const!, {@XMM[8]}		@ .LM0SR
855_bsaes_encrypt8_alt:
856	veor	@XMM[10], @XMM[0], @XMM[9]	@ xor with round0 key
857	veor	@XMM[11], @XMM[1], @XMM[9]
858	 vtbl.8	`&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
859	 vtbl.8	`&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
860	veor	@XMM[12], @XMM[2], @XMM[9]
861	 vtbl.8	`&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
862	 vtbl.8	`&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
863	veor	@XMM[13], @XMM[3], @XMM[9]
864	 vtbl.8	`&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
865	 vtbl.8	`&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
866	veor	@XMM[14], @XMM[4], @XMM[9]
867	 vtbl.8	`&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
868	 vtbl.8	`&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
869	veor	@XMM[15], @XMM[5], @XMM[9]
870	 vtbl.8	`&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
871	 vtbl.8	`&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
872	veor	@XMM[10], @XMM[6], @XMM[9]
873	 vtbl.8	`&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
874	 vtbl.8	`&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
875	veor	@XMM[11], @XMM[7], @XMM[9]
876	 vtbl.8	`&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
877	 vtbl.8	`&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
878	 vtbl.8	`&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
879	 vtbl.8	`&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
880_bsaes_encrypt8_bitslice:
881___
882	&bitslice	(@XMM[0..7, 8..11]);
883$code.=<<___;
884	sub	$rounds,$rounds,#1
885	b	.Lenc_sbox
886.align	4
887.Lenc_loop:
888___
889	&ShiftRows	(@XMM[0..7, 8..12]);
890$code.=".Lenc_sbox:\n";
891	&Sbox		(@XMM[0..7, 8..15]);
892$code.=<<___;
893	subs	$rounds,$rounds,#1
894	bcc	.Lenc_done
895___
896	&MixColumns	(@XMM[0,1,4,6,3,7,2,5, 8..15]);
897$code.=<<___;
898	vldmia	$const, {@XMM[12]}		@ .LSR
899	ite	eq				@ Thumb2 thing, samity check in ARM
900	addeq	$const,$const,#0x10
901	bne	.Lenc_loop
902	vldmia	$const, {@XMM[12]}		@ .LSRM0
903	b	.Lenc_loop
904.align	4
905.Lenc_done:
906___
907	# output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
908	&bitslice	(@XMM[0,1,4,6,3,7,2,5, 8..11]);
909$code.=<<___;
910	vldmia	$key, {@XMM[8]}			@ last round key
911	veor	@XMM[4], @XMM[4], @XMM[8]
912	veor	@XMM[6], @XMM[6], @XMM[8]
913	veor	@XMM[3], @XMM[3], @XMM[8]
914	veor	@XMM[7], @XMM[7], @XMM[8]
915	veor	@XMM[2], @XMM[2], @XMM[8]
916	veor	@XMM[5], @XMM[5], @XMM[8]
917	veor	@XMM[0], @XMM[0], @XMM[8]
918	veor	@XMM[1], @XMM[1], @XMM[8]
919	bx	lr
920.size	_bsaes_encrypt8,.-_bsaes_encrypt8
921___
922}
923{
924my ($out,$inp,$rounds,$const)=("r12","r4","r5","r6");
925
926sub bitslice_key {
927my @x=reverse(@_[0..7]);
928my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
929
930	&swapmove	(@x[0,1],1,$bs0,$t2,$t3);
931$code.=<<___;
932	@ &swapmove(@x[2,3],1,$t0,$t2,$t3);
933	vmov	@x[2], @x[0]
934	vmov	@x[3], @x[1]
935___
936	#&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
937
938	&swapmove2x	(@x[0,2,1,3],2,$bs1,$t2,$t3);
939$code.=<<___;
940	@ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
941	vmov	@x[4], @x[0]
942	vmov	@x[6], @x[2]
943	vmov	@x[5], @x[1]
944	vmov	@x[7], @x[3]
945___
946	&swapmove2x	(@x[0,4,1,5],4,$bs2,$t2,$t3);
947	&swapmove2x	(@x[2,6,3,7],4,$bs2,$t2,$t3);
948}
949
950$code.=<<___;
951.type	_bsaes_key_convert,%function
952.align	4
953_bsaes_key_convert:
954	adr	$const,.
955	vld1.8	{@XMM[7]},  [$inp]!		@ load round 0 key
956#if defined(__thumb2__) || defined(__APPLE__)
957	adr	$const,.LM0
958#else
959	sub	$const,$const,#_bsaes_key_convert-.LM0
960#endif
961	vld1.8	{@XMM[15]}, [$inp]!		@ load round 1 key
962
963	vmov.i8	@XMM[8],  #0x01			@ bit masks
964	vmov.i8	@XMM[9],  #0x02
965	vmov.i8	@XMM[10], #0x04
966	vmov.i8	@XMM[11], #0x08
967	vmov.i8	@XMM[12], #0x10
968	vmov.i8	@XMM[13], #0x20
969	vldmia	$const, {@XMM[14]}		@ .LM0
970
971#ifdef __ARMEL__
972	vrev32.8	@XMM[7],  @XMM[7]
973	vrev32.8	@XMM[15], @XMM[15]
974#endif
975	sub	$rounds,$rounds,#1
976	vstmia	$out!, {@XMM[7]}		@ save round 0 key
977	b	.Lkey_loop
978
979.align	4
980.Lkey_loop:
981	vtbl.8	`&Dlo(@XMM[7])`,{@XMM[15]},`&Dlo(@XMM[14])`
982	vtbl.8	`&Dhi(@XMM[7])`,{@XMM[15]},`&Dhi(@XMM[14])`
983	vmov.i8	@XMM[6],  #0x40
984	vmov.i8	@XMM[15], #0x80
985
986	vtst.8	@XMM[0], @XMM[7], @XMM[8]
987	vtst.8	@XMM[1], @XMM[7], @XMM[9]
988	vtst.8	@XMM[2], @XMM[7], @XMM[10]
989	vtst.8	@XMM[3], @XMM[7], @XMM[11]
990	vtst.8	@XMM[4], @XMM[7], @XMM[12]
991	vtst.8	@XMM[5], @XMM[7], @XMM[13]
992	vtst.8	@XMM[6], @XMM[7], @XMM[6]
993	vtst.8	@XMM[7], @XMM[7], @XMM[15]
994	vld1.8	{@XMM[15]}, [$inp]!		@ load next round key
995	vmvn	@XMM[0], @XMM[0]		@ "pnot"
996	vmvn	@XMM[1], @XMM[1]
997	vmvn	@XMM[5], @XMM[5]
998	vmvn	@XMM[6], @XMM[6]
999#ifdef __ARMEL__
1000	vrev32.8	@XMM[15], @XMM[15]
1001#endif
1002	subs	$rounds,$rounds,#1
1003	vstmia	$out!,{@XMM[0]-@XMM[7]}		@ write bit-sliced round key
1004	bne	.Lkey_loop
1005
1006	vmov.i8	@XMM[7],#0x63			@ compose .L63
1007	@ don't save last round key
1008	bx	lr
1009.size	_bsaes_key_convert,.-_bsaes_key_convert
1010___
1011}
1012
1013if (0) {		# following four functions are unsupported interface
1014			# used for benchmarking...
1015$code.=<<___;
1016.globl	bsaes_enc_key_convert
1017.type	bsaes_enc_key_convert,%function
1018.align	4
1019bsaes_enc_key_convert:
1020	stmdb	sp!,{r4-r6,lr}
1021	vstmdb	sp!,{d8-d15}		@ ABI specification says so
1022
1023	ldr	r5,[$inp,#240]			@ pass rounds
1024	mov	r4,$inp				@ pass key
1025	mov	r12,$out			@ pass key schedule
1026	bl	_bsaes_key_convert
1027	veor	@XMM[7],@XMM[7],@XMM[15]	@ fix up last round key
1028	vstmia	r12, {@XMM[7]}			@ save last round key
1029
1030	vldmia	sp!,{d8-d15}
1031	ldmia	sp!,{r4-r6,pc}
1032.size	bsaes_enc_key_convert,.-bsaes_enc_key_convert
1033
1034.globl	bsaes_encrypt_128
1035.type	bsaes_encrypt_128,%function
1036.align	4
1037bsaes_encrypt_128:
1038	stmdb	sp!,{r4-r6,lr}
1039	vstmdb	sp!,{d8-d15}		@ ABI specification says so
1040.Lenc128_loop:
1041	vld1.8	{@XMM[0]-@XMM[1]}, [$inp]!	@ load input
1042	vld1.8	{@XMM[2]-@XMM[3]}, [$inp]!
1043	mov	r4,$key				@ pass the key
1044	vld1.8	{@XMM[4]-@XMM[5]}, [$inp]!
1045	mov	r5,#10				@ pass rounds
1046	vld1.8	{@XMM[6]-@XMM[7]}, [$inp]!
1047
1048	bl	_bsaes_encrypt8
1049
1050	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1051	vst1.8	{@XMM[4]}, [$out]!
1052	vst1.8	{@XMM[6]}, [$out]!
1053	vst1.8	{@XMM[3]}, [$out]!
1054	vst1.8	{@XMM[7]}, [$out]!
1055	vst1.8	{@XMM[2]}, [$out]!
1056	subs	$len,$len,#0x80
1057	vst1.8	{@XMM[5]}, [$out]!
1058	bhi	.Lenc128_loop
1059
1060	vldmia	sp!,{d8-d15}
1061	ldmia	sp!,{r4-r6,pc}
1062.size	bsaes_encrypt_128,.-bsaes_encrypt_128
1063
1064.globl	bsaes_dec_key_convert
1065.type	bsaes_dec_key_convert,%function
1066.align	4
1067bsaes_dec_key_convert:
1068	stmdb	sp!,{r4-r6,lr}
1069	vstmdb	sp!,{d8-d15}		@ ABI specification says so
1070
1071	ldr	r5,[$inp,#240]			@ pass rounds
1072	mov	r4,$inp				@ pass key
1073	mov	r12,$out			@ pass key schedule
1074	bl	_bsaes_key_convert
1075	vldmia	$out, {@XMM[6]}
1076	vstmia	r12,  {@XMM[15]}		@ save last round key
1077	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
1078	vstmia	$out, {@XMM[7]}
1079
1080	vldmia	sp!,{d8-d15}
1081	ldmia	sp!,{r4-r6,pc}
1082.size	bsaes_dec_key_convert,.-bsaes_dec_key_convert
1083
1084.globl	bsaes_decrypt_128
1085.type	bsaes_decrypt_128,%function
1086.align	4
1087bsaes_decrypt_128:
1088	stmdb	sp!,{r4-r6,lr}
1089	vstmdb	sp!,{d8-d15}		@ ABI specification says so
1090.Ldec128_loop:
1091	vld1.8	{@XMM[0]-@XMM[1]}, [$inp]!	@ load input
1092	vld1.8	{@XMM[2]-@XMM[3]}, [$inp]!
1093	mov	r4,$key				@ pass the key
1094	vld1.8	{@XMM[4]-@XMM[5]}, [$inp]!
1095	mov	r5,#10				@ pass rounds
1096	vld1.8	{@XMM[6]-@XMM[7]}, [$inp]!
1097
1098	bl	_bsaes_decrypt8
1099
1100	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1101	vst1.8	{@XMM[6]}, [$out]!
1102	vst1.8	{@XMM[4]}, [$out]!
1103	vst1.8	{@XMM[2]}, [$out]!
1104	vst1.8	{@XMM[7]}, [$out]!
1105	vst1.8	{@XMM[3]}, [$out]!
1106	subs	$len,$len,#0x80
1107	vst1.8	{@XMM[5]}, [$out]!
1108	bhi	.Ldec128_loop
1109
1110	vldmia	sp!,{d8-d15}
1111	ldmia	sp!,{r4-r6,pc}
1112.size	bsaes_decrypt_128,.-bsaes_decrypt_128
1113___
1114}
1115{
1116my ($inp,$out,$len,$key, $ivp,$fp,$rounds)=map("r$_",(0..3,8..10));
1117my ($keysched)=("sp");
1118
1119$code.=<<___;
1120.global	bsaes_cbc_encrypt
1121.type	bsaes_cbc_encrypt,%function
1122.align	5
1123bsaes_cbc_encrypt:
1124	@ In OpenSSL, this function had a fallback to aes_nohw_cbc_encrypt for
1125	@ short inputs. We patch this out, using bsaes for all input sizes.
1126
1127	@ it is up to the caller to make sure we are called with enc == 0
1128
1129	mov	ip, sp
1130	stmdb	sp!, {r4-r10, lr}
1131	VFP_ABI_PUSH
1132	ldr	$ivp, [ip]			@ IV is 1st arg on the stack
1133	mov	$len, $len, lsr#4		@ len in 16 byte blocks
1134	sub	sp, #0x10			@ scratch space to carry over the IV
1135	mov	$fp, sp				@ save sp
1136
1137	ldr	$rounds, [$key, #240]		@ get # of rounds
1138#ifndef	BSAES_ASM_EXTENDED_KEY
1139	@ allocate the key schedule on the stack
1140	sub	r12, sp, $rounds, lsl#7		@ 128 bytes per inner round key
1141	add	r12, #`128-32`			@ sifze of bit-slices key schedule
1142
1143	@ populate the key schedule
1144	mov	r4, $key			@ pass key
1145	mov	r5, $rounds			@ pass # of rounds
1146	mov	sp, r12				@ sp is $keysched
1147	bl	_bsaes_key_convert
1148	vldmia	$keysched, {@XMM[6]}
1149	vstmia	r12,  {@XMM[15]}		@ save last round key
1150	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
1151	vstmia	$keysched, {@XMM[7]}
1152#else
1153	ldr	r12, [$key, #244]
1154	eors	r12, #1
1155	beq	0f
1156
1157	@ populate the key schedule
1158	str	r12, [$key, #244]
1159	mov	r4, $key			@ pass key
1160	mov	r5, $rounds			@ pass # of rounds
1161	add	r12, $key, #248			@ pass key schedule
1162	bl	_bsaes_key_convert
1163	add	r4, $key, #248
1164	vldmia	r4, {@XMM[6]}
1165	vstmia	r12, {@XMM[15]}			@ save last round key
1166	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
1167	vstmia	r4, {@XMM[7]}
1168
1169.align	2
11700:
1171#endif
1172
1173	vld1.8	{@XMM[15]}, [$ivp]		@ load IV
1174	b	.Lcbc_dec_loop
1175
1176.align	4
1177.Lcbc_dec_loop:
1178	subs	$len, $len, #0x8
1179	bmi	.Lcbc_dec_loop_finish
1180
1181	vld1.8	{@XMM[0]-@XMM[1]}, [$inp]!	@ load input
1182	vld1.8	{@XMM[2]-@XMM[3]}, [$inp]!
1183#ifndef	BSAES_ASM_EXTENDED_KEY
1184	mov	r4, $keysched			@ pass the key
1185#else
1186	add	r4, $key, #248
1187#endif
1188	vld1.8	{@XMM[4]-@XMM[5]}, [$inp]!
1189	mov	r5, $rounds
1190	vld1.8	{@XMM[6]-@XMM[7]}, [$inp]
1191	sub	$inp, $inp, #0x60
1192	vstmia	$fp, {@XMM[15]}			@ put aside IV
1193
1194	bl	_bsaes_decrypt8
1195
1196	vldmia	$fp, {@XMM[14]}			@ reload IV
1197	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
1198	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
1199	vld1.8	{@XMM[10]-@XMM[11]}, [$inp]!
1200	veor	@XMM[1], @XMM[1], @XMM[8]
1201	veor	@XMM[6], @XMM[6], @XMM[9]
1202	vld1.8	{@XMM[12]-@XMM[13]}, [$inp]!
1203	veor	@XMM[4], @XMM[4], @XMM[10]
1204	veor	@XMM[2], @XMM[2], @XMM[11]
1205	vld1.8	{@XMM[14]-@XMM[15]}, [$inp]!
1206	veor	@XMM[7], @XMM[7], @XMM[12]
1207	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1208	veor	@XMM[3], @XMM[3], @XMM[13]
1209	vst1.8	{@XMM[6]}, [$out]!
1210	veor	@XMM[5], @XMM[5], @XMM[14]
1211	vst1.8	{@XMM[4]}, [$out]!
1212	vst1.8	{@XMM[2]}, [$out]!
1213	vst1.8	{@XMM[7]}, [$out]!
1214	vst1.8	{@XMM[3]}, [$out]!
1215	vst1.8	{@XMM[5]}, [$out]!
1216
1217	b	.Lcbc_dec_loop
1218
1219.Lcbc_dec_loop_finish:
1220	adds	$len, $len, #8
1221	beq	.Lcbc_dec_done
1222
1223	@ Set up most parameters for the _bsaes_decrypt8 call.
1224#ifndef	BSAES_ASM_EXTENDED_KEY
1225	mov	r4, $keysched			@ pass the key
1226#else
1227	add	r4, $key, #248
1228#endif
1229	mov	r5, $rounds
1230	vstmia	$fp, {@XMM[15]}			@ put aside IV
1231
1232	vld1.8	{@XMM[0]}, [$inp]!		@ load input
1233	cmp	$len, #2
1234	blo	.Lcbc_dec_one
1235	vld1.8	{@XMM[1]}, [$inp]!
1236	beq	.Lcbc_dec_two
1237	vld1.8	{@XMM[2]}, [$inp]!
1238	cmp	$len, #4
1239	blo	.Lcbc_dec_three
1240	vld1.8	{@XMM[3]}, [$inp]!
1241	beq	.Lcbc_dec_four
1242	vld1.8	{@XMM[4]}, [$inp]!
1243	cmp	$len, #6
1244	blo	.Lcbc_dec_five
1245	vld1.8	{@XMM[5]}, [$inp]!
1246	beq	.Lcbc_dec_six
1247	vld1.8	{@XMM[6]}, [$inp]!
1248	sub	$inp, $inp, #0x70
1249
1250	bl	_bsaes_decrypt8
1251
1252	vldmia	$fp, {@XMM[14]}			@ reload IV
1253	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
1254	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
1255	vld1.8	{@XMM[10]-@XMM[11]}, [$inp]!
1256	veor	@XMM[1], @XMM[1], @XMM[8]
1257	veor	@XMM[6], @XMM[6], @XMM[9]
1258	vld1.8	{@XMM[12]-@XMM[13]}, [$inp]!
1259	veor	@XMM[4], @XMM[4], @XMM[10]
1260	veor	@XMM[2], @XMM[2], @XMM[11]
1261	vld1.8	{@XMM[15]}, [$inp]!
1262	veor	@XMM[7], @XMM[7], @XMM[12]
1263	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1264	veor	@XMM[3], @XMM[3], @XMM[13]
1265	vst1.8	{@XMM[6]}, [$out]!
1266	vst1.8	{@XMM[4]}, [$out]!
1267	vst1.8	{@XMM[2]}, [$out]!
1268	vst1.8	{@XMM[7]}, [$out]!
1269	vst1.8	{@XMM[3]}, [$out]!
1270	b	.Lcbc_dec_done
1271.align	4
1272.Lcbc_dec_six:
1273	sub	$inp, $inp, #0x60
1274	bl	_bsaes_decrypt8
1275	vldmia	$fp,{@XMM[14]}			@ reload IV
1276	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
1277	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
1278	vld1.8	{@XMM[10]-@XMM[11]}, [$inp]!
1279	veor	@XMM[1], @XMM[1], @XMM[8]
1280	veor	@XMM[6], @XMM[6], @XMM[9]
1281	vld1.8	{@XMM[12]}, [$inp]!
1282	veor	@XMM[4], @XMM[4], @XMM[10]
1283	veor	@XMM[2], @XMM[2], @XMM[11]
1284	vld1.8	{@XMM[15]}, [$inp]!
1285	veor	@XMM[7], @XMM[7], @XMM[12]
1286	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1287	vst1.8	{@XMM[6]}, [$out]!
1288	vst1.8	{@XMM[4]}, [$out]!
1289	vst1.8	{@XMM[2]}, [$out]!
1290	vst1.8	{@XMM[7]}, [$out]!
1291	b	.Lcbc_dec_done
1292.align	4
1293.Lcbc_dec_five:
1294	sub	$inp, $inp, #0x50
1295	bl	_bsaes_decrypt8
1296	vldmia	$fp, {@XMM[14]}			@ reload IV
1297	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
1298	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
1299	vld1.8	{@XMM[10]-@XMM[11]}, [$inp]!
1300	veor	@XMM[1], @XMM[1], @XMM[8]
1301	veor	@XMM[6], @XMM[6], @XMM[9]
1302	vld1.8	{@XMM[15]}, [$inp]!
1303	veor	@XMM[4], @XMM[4], @XMM[10]
1304	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1305	veor	@XMM[2], @XMM[2], @XMM[11]
1306	vst1.8	{@XMM[6]}, [$out]!
1307	vst1.8	{@XMM[4]}, [$out]!
1308	vst1.8	{@XMM[2]}, [$out]!
1309	b	.Lcbc_dec_done
1310.align	4
1311.Lcbc_dec_four:
1312	sub	$inp, $inp, #0x40
1313	bl	_bsaes_decrypt8
1314	vldmia	$fp, {@XMM[14]}			@ reload IV
1315	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
1316	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
1317	vld1.8	{@XMM[10]}, [$inp]!
1318	veor	@XMM[1], @XMM[1], @XMM[8]
1319	veor	@XMM[6], @XMM[6], @XMM[9]
1320	vld1.8	{@XMM[15]}, [$inp]!
1321	veor	@XMM[4], @XMM[4], @XMM[10]
1322	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1323	vst1.8	{@XMM[6]}, [$out]!
1324	vst1.8	{@XMM[4]}, [$out]!
1325	b	.Lcbc_dec_done
1326.align	4
1327.Lcbc_dec_three:
1328	sub	$inp, $inp, #0x30
1329	bl	_bsaes_decrypt8
1330	vldmia	$fp, {@XMM[14]}			@ reload IV
1331	vld1.8	{@XMM[8]-@XMM[9]}, [$inp]!	@ reload input
1332	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
1333	vld1.8	{@XMM[15]}, [$inp]!
1334	veor	@XMM[1], @XMM[1], @XMM[8]
1335	veor	@XMM[6], @XMM[6], @XMM[9]
1336	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1337	vst1.8	{@XMM[6]}, [$out]!
1338	b	.Lcbc_dec_done
1339.align	4
1340.Lcbc_dec_two:
1341	sub	$inp, $inp, #0x20
1342	bl	_bsaes_decrypt8
1343	vldmia	$fp, {@XMM[14]}			@ reload IV
1344	vld1.8	{@XMM[8]}, [$inp]!		@ reload input
1345	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
1346	vld1.8	{@XMM[15]}, [$inp]!		@ reload input
1347	veor	@XMM[1], @XMM[1], @XMM[8]
1348	vst1.8	{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1349	b	.Lcbc_dec_done
1350.align	4
1351.Lcbc_dec_one:
1352	sub	$inp, $inp, #0x10
1353	bl	_bsaes_decrypt8
1354	vldmia	$fp, {@XMM[14]}			@ reload IV
1355	vld1.8	{@XMM[15]}, [$inp]!		@ reload input
1356	veor	@XMM[0], @XMM[0], @XMM[14]	@ ^= IV
1357	vst1.8	{@XMM[0]}, [$out]!		@ write output
1358
1359.Lcbc_dec_done:
1360#ifndef	BSAES_ASM_EXTENDED_KEY
1361	vmov.i32	q0, #0
1362	vmov.i32	q1, #0
1363.Lcbc_dec_bzero:				@ wipe key schedule [if any]
1364	vstmia		$keysched!, {q0-q1}
1365	cmp		$keysched, $fp
1366	bne		.Lcbc_dec_bzero
1367#endif
1368
1369	mov	sp, $fp
1370	add	sp, #0x10			@ add sp,$fp,#0x10 is no good for thumb
1371	vst1.8	{@XMM[15]}, [$ivp]		@ return IV
1372	VFP_ABI_POP
1373	ldmia	sp!, {r4-r10, pc}
1374.size	bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
1375___
1376}
1377{
1378my ($inp,$out,$len,$key, $ctr,$fp,$rounds)=(map("r$_",(0..3,8..10)));
1379my $const = "r6";	# shared with _bsaes_encrypt8_alt
1380my $keysched = "sp";
1381
1382$code.=<<___;
1383.global	bsaes_ctr32_encrypt_blocks
1384.type	bsaes_ctr32_encrypt_blocks,%function
1385.align	5
1386bsaes_ctr32_encrypt_blocks:
1387	@ In OpenSSL, short inputs fall back to aes_nohw_* here. We patch this
1388	@ out to retain a constant-time implementation.
1389	mov	ip, sp
1390	stmdb	sp!, {r4-r10, lr}
1391	VFP_ABI_PUSH
1392	ldr	$ctr, [ip]			@ ctr is 1st arg on the stack
1393	sub	sp, sp, #0x10			@ scratch space to carry over the ctr
1394	mov	$fp, sp				@ save sp
1395
1396	ldr	$rounds, [$key, #240]		@ get # of rounds
1397#ifndef	BSAES_ASM_EXTENDED_KEY
1398	@ allocate the key schedule on the stack
1399	sub	r12, sp, $rounds, lsl#7		@ 128 bytes per inner round key
1400	add	r12, #`128-32`			@ size of bit-sliced key schedule
1401
1402	@ populate the key schedule
1403	mov	r4, $key			@ pass key
1404	mov	r5, $rounds			@ pass # of rounds
1405	mov	sp, r12				@ sp is $keysched
1406	bl	_bsaes_key_convert
1407	veor	@XMM[7],@XMM[7],@XMM[15]	@ fix up last round key
1408	vstmia	r12, {@XMM[7]}			@ save last round key
1409
1410	vld1.8	{@XMM[0]}, [$ctr]		@ load counter
1411#ifdef	__APPLE__
1412	mov	$ctr, #:lower16:(.LREVM0SR-.LM0)
1413	add	$ctr, $const, $ctr
1414#else
1415	add	$ctr, $const, #.LREVM0SR-.LM0	@ borrow $ctr
1416#endif
1417	vldmia	$keysched, {@XMM[4]}		@ load round0 key
1418#else
1419	ldr	r12, [$key, #244]
1420	eors	r12, #1
1421	beq	0f
1422
1423	@ populate the key schedule
1424	str	r12, [$key, #244]
1425	mov	r4, $key			@ pass key
1426	mov	r5, $rounds			@ pass # of rounds
1427	add	r12, $key, #248			@ pass key schedule
1428	bl	_bsaes_key_convert
1429	veor	@XMM[7],@XMM[7],@XMM[15]	@ fix up last round key
1430	vstmia	r12, {@XMM[7]}			@ save last round key
1431
1432.align	2
14330:	add	r12, $key, #248
1434	vld1.8	{@XMM[0]}, [$ctr]		@ load counter
1435	adrl	$ctr, .LREVM0SR			@ borrow $ctr
1436	vldmia	r12, {@XMM[4]}			@ load round0 key
1437	sub	sp, #0x10			@ place for adjusted round0 key
1438#endif
1439
1440	vmov.i32	@XMM[8],#1		@ compose 1<<96
1441	veor		@XMM[9],@XMM[9],@XMM[9]
1442	vrev32.8	@XMM[0],@XMM[0]
1443	vext.8		@XMM[8],@XMM[9],@XMM[8],#4
1444	vrev32.8	@XMM[4],@XMM[4]
1445	vadd.u32	@XMM[9],@XMM[8],@XMM[8]	@ compose 2<<96
1446	vstmia	$keysched, {@XMM[4]}		@ save adjusted round0 key
1447	b	.Lctr_enc_loop
1448
1449.align	4
1450.Lctr_enc_loop:
1451	vadd.u32	@XMM[10], @XMM[8], @XMM[9]	@ compose 3<<96
1452	vadd.u32	@XMM[1], @XMM[0], @XMM[8]	@ +1
1453	vadd.u32	@XMM[2], @XMM[0], @XMM[9]	@ +2
1454	vadd.u32	@XMM[3], @XMM[0], @XMM[10]	@ +3
1455	vadd.u32	@XMM[4], @XMM[1], @XMM[10]
1456	vadd.u32	@XMM[5], @XMM[2], @XMM[10]
1457	vadd.u32	@XMM[6], @XMM[3], @XMM[10]
1458	vadd.u32	@XMM[7], @XMM[4], @XMM[10]
1459	vadd.u32	@XMM[10], @XMM[5], @XMM[10]	@ next counter
1460
1461	@ Borrow prologue from _bsaes_encrypt8 to use the opportunity
1462	@ to flip byte order in 32-bit counter
1463
1464	vldmia		$keysched, {@XMM[9]}		@ load round0 key
1465#ifndef	BSAES_ASM_EXTENDED_KEY
1466	add		r4, $keysched, #0x10		@ pass next round key
1467#else
1468	add		r4, $key, #`248+16`
1469#endif
1470	vldmia		$ctr, {@XMM[8]}			@ .LREVM0SR
1471	mov		r5, $rounds			@ pass rounds
1472	vstmia		$fp, {@XMM[10]}			@ save next counter
1473#ifdef	__APPLE__
1474	mov		$const, #:lower16:(.LREVM0SR-.LSR)
1475	sub		$const, $ctr, $const
1476#else
1477	sub		$const, $ctr, #.LREVM0SR-.LSR	@ pass constants
1478#endif
1479
1480	bl		_bsaes_encrypt8_alt
1481
1482	subs		$len, $len, #8
1483	blo		.Lctr_enc_loop_done
1484
1485	vld1.8		{@XMM[8]-@XMM[9]}, [$inp]!	@ load input
1486	vld1.8		{@XMM[10]-@XMM[11]}, [$inp]!
1487	veor		@XMM[0], @XMM[8]
1488	veor		@XMM[1], @XMM[9]
1489	vld1.8		{@XMM[12]-@XMM[13]}, [$inp]!
1490	veor		@XMM[4], @XMM[10]
1491	veor		@XMM[6], @XMM[11]
1492	vld1.8		{@XMM[14]-@XMM[15]}, [$inp]!
1493	veor		@XMM[3], @XMM[12]
1494	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!	@ write output
1495	veor		@XMM[7], @XMM[13]
1496	veor		@XMM[2], @XMM[14]
1497	vst1.8		{@XMM[4]}, [$out]!
1498	veor		@XMM[5], @XMM[15]
1499	vst1.8		{@XMM[6]}, [$out]!
1500	vmov.i32	@XMM[8], #1			@ compose 1<<96
1501	vst1.8		{@XMM[3]}, [$out]!
1502	veor		@XMM[9], @XMM[9], @XMM[9]
1503	vst1.8		{@XMM[7]}, [$out]!
1504	vext.8		@XMM[8], @XMM[9], @XMM[8], #4
1505	vst1.8		{@XMM[2]}, [$out]!
1506	vadd.u32	@XMM[9],@XMM[8],@XMM[8]		@ compose 2<<96
1507	vst1.8		{@XMM[5]}, [$out]!
1508	vldmia		$fp, {@XMM[0]}			@ load counter
1509
1510	bne		.Lctr_enc_loop
1511	b		.Lctr_enc_done
1512
1513.align	4
1514.Lctr_enc_loop_done:
1515	add		$len, $len, #8
1516	vld1.8		{@XMM[8]}, [$inp]!	@ load input
1517	veor		@XMM[0], @XMM[8]
1518	vst1.8		{@XMM[0]}, [$out]!	@ write output
1519	cmp		$len, #2
1520	blo		.Lctr_enc_done
1521	vld1.8		{@XMM[9]}, [$inp]!
1522	veor		@XMM[1], @XMM[9]
1523	vst1.8		{@XMM[1]}, [$out]!
1524	beq		.Lctr_enc_done
1525	vld1.8		{@XMM[10]}, [$inp]!
1526	veor		@XMM[4], @XMM[10]
1527	vst1.8		{@XMM[4]}, [$out]!
1528	cmp		$len, #4
1529	blo		.Lctr_enc_done
1530	vld1.8		{@XMM[11]}, [$inp]!
1531	veor		@XMM[6], @XMM[11]
1532	vst1.8		{@XMM[6]}, [$out]!
1533	beq		.Lctr_enc_done
1534	vld1.8		{@XMM[12]}, [$inp]!
1535	veor		@XMM[3], @XMM[12]
1536	vst1.8		{@XMM[3]}, [$out]!
1537	cmp		$len, #6
1538	blo		.Lctr_enc_done
1539	vld1.8		{@XMM[13]}, [$inp]!
1540	veor		@XMM[7], @XMM[13]
1541	vst1.8		{@XMM[7]}, [$out]!
1542	beq		.Lctr_enc_done
1543	vld1.8		{@XMM[14]}, [$inp]
1544	veor		@XMM[2], @XMM[14]
1545	vst1.8		{@XMM[2]}, [$out]!
1546
1547.Lctr_enc_done:
1548	vmov.i32	q0, #0
1549	vmov.i32	q1, #0
1550#ifndef	BSAES_ASM_EXTENDED_KEY
1551.Lctr_enc_bzero:			@ wipe key schedule [if any]
1552	vstmia		$keysched!, {q0-q1}
1553	cmp		$keysched, $fp
1554	bne		.Lctr_enc_bzero
1555#else
1556	vstmia		$keysched, {q0-q1}
1557#endif
1558
1559	mov	sp, $fp
1560	add	sp, #0x10		@ add sp,$fp,#0x10 is no good for thumb
1561	VFP_ABI_POP
1562	ldmia	sp!, {r4-r10, pc}	@ return
1563
1564	@ OpenSSL contains aes_nohw_* fallback code here. We patch this
1565	@ out to retain a constant-time implementation.
1566.size	bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
1567___
1568}
1569# In BorinSSL, we patch XTS support out.
1570if (0) {
1571######################################################################
1572# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len,
1573#	const AES_KEY *key1, const AES_KEY *key2,
1574#	const unsigned char iv[16]);
1575#
1576my ($inp,$out,$len,$key,$rounds,$magic,$fp)=(map("r$_",(7..10,1..3)));
1577my $const="r6";		# returned by _bsaes_key_convert
1578my $twmask=@XMM[5];
1579my @T=@XMM[6..7];
1580
1581$code.=<<___;
1582.globl	bsaes_xts_encrypt
1583.type	bsaes_xts_encrypt,%function
1584.align	4
1585bsaes_xts_encrypt:
1586	mov	ip, sp
1587	stmdb	sp!, {r4-r10, lr}		@ 0x20
1588	VFP_ABI_PUSH
1589	mov	r6, sp				@ future $fp
1590
1591	mov	$inp, r0
1592	mov	$out, r1
1593	mov	$len, r2
1594	mov	$key, r3
1595
1596	sub	r0, sp, #0x10			@ 0x10
1597	bic	r0, #0xf			@ align at 16 bytes
1598	mov	sp, r0
1599
1600#ifdef	XTS_CHAIN_TWEAK
1601	ldr	r0, [ip]			@ pointer to input tweak
1602#else
1603	@ generate initial tweak
1604	ldr	r0, [ip, #4]			@ iv[]
1605	mov	r1, sp
1606	ldr	r2, [ip, #0]			@ key2
1607	bl	aes_nohw_encrypt
1608	mov	r0,sp				@ pointer to initial tweak
1609#endif
1610
1611	ldr	$rounds, [$key, #240]		@ get # of rounds
1612	mov	$fp, r6
1613#ifndef	BSAES_ASM_EXTENDED_KEY
1614	@ allocate the key schedule on the stack
1615	sub	r12, sp, $rounds, lsl#7		@ 128 bytes per inner round key
1616	@ add	r12, #`128-32`			@ size of bit-sliced key schedule
1617	sub	r12, #`32+16`			@ place for tweak[9]
1618
1619	@ populate the key schedule
1620	mov	r4, $key			@ pass key
1621	mov	r5, $rounds			@ pass # of rounds
1622	mov	sp, r12
1623	add	r12, #0x90			@ pass key schedule
1624	bl	_bsaes_key_convert
1625	veor	@XMM[7], @XMM[7], @XMM[15]	@ fix up last round key
1626	vstmia	r12, {@XMM[7]}			@ save last round key
1627#else
1628	ldr	r12, [$key, #244]
1629	eors	r12, #1
1630	beq	0f
1631
1632	str	r12, [$key, #244]
1633	mov	r4, $key			@ pass key
1634	mov	r5, $rounds			@ pass # of rounds
1635	add	r12, $key, #248			@ pass key schedule
1636	bl	_bsaes_key_convert
1637	veor	@XMM[7], @XMM[7], @XMM[15]	@ fix up last round key
1638	vstmia	r12, {@XMM[7]}
1639
1640.align	2
16410:	sub	sp, #0x90			@ place for tweak[9]
1642#endif
1643
1644	vld1.8	{@XMM[8]}, [r0]			@ initial tweak
1645	adr	$magic, .Lxts_magic
1646
1647	subs	$len, #0x80
1648	blo	.Lxts_enc_short
1649	b	.Lxts_enc_loop
1650
1651.align	4
1652.Lxts_enc_loop:
1653	vldmia		$magic, {$twmask}	@ load XTS magic
1654	vshr.s64	@T[0], @XMM[8], #63
1655	mov		r0, sp
1656	vand		@T[0], @T[0], $twmask
1657___
1658for($i=9;$i<16;$i++) {
1659$code.=<<___;
1660	vadd.u64	@XMM[$i], @XMM[$i-1], @XMM[$i-1]
1661	vst1.64		{@XMM[$i-1]}, [r0,:128]!
1662	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
1663	vshr.s64	@T[1], @XMM[$i], #63
1664	veor		@XMM[$i], @XMM[$i], @T[0]
1665	vand		@T[1], @T[1], $twmask
1666___
1667	@T=reverse(@T);
1668
1669$code.=<<___ if ($i>=10);
1670	vld1.8		{@XMM[$i-10]}, [$inp]!
1671___
1672$code.=<<___ if ($i>=11);
1673	veor		@XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
1674___
1675}
1676$code.=<<___;
1677	vadd.u64	@XMM[8], @XMM[15], @XMM[15]
1678	vst1.64		{@XMM[15]}, [r0,:128]!
1679	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
1680	veor		@XMM[8], @XMM[8], @T[0]
1681	vst1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
1682
1683	vld1.8		{@XMM[6]-@XMM[7]}, [$inp]!
1684	veor		@XMM[5], @XMM[5], @XMM[13]
1685#ifndef	BSAES_ASM_EXTENDED_KEY
1686	add		r4, sp, #0x90			@ pass key schedule
1687#else
1688	add		r4, $key, #248			@ pass key schedule
1689#endif
1690	veor		@XMM[6], @XMM[6], @XMM[14]
1691	mov		r5, $rounds			@ pass rounds
1692	veor		@XMM[7], @XMM[7], @XMM[15]
1693	mov		r0, sp
1694
1695	bl		_bsaes_encrypt8
1696
1697	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1698	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
1699	veor		@XMM[0], @XMM[0], @XMM[ 8]
1700	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
1701	veor		@XMM[1], @XMM[1], @XMM[ 9]
1702	veor		@XMM[8], @XMM[4], @XMM[10]
1703	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
1704	veor		@XMM[9], @XMM[6], @XMM[11]
1705	vld1.64		{@XMM[14]-@XMM[15]}, [r0,:128]!
1706	veor		@XMM[10], @XMM[3], @XMM[12]
1707	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
1708	veor		@XMM[11], @XMM[7], @XMM[13]
1709	veor		@XMM[12], @XMM[2], @XMM[14]
1710	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
1711	veor		@XMM[13], @XMM[5], @XMM[15]
1712	vst1.8		{@XMM[12]-@XMM[13]}, [$out]!
1713
1714	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
1715
1716	subs		$len, #0x80
1717	bpl		.Lxts_enc_loop
1718
1719.Lxts_enc_short:
1720	adds		$len, #0x70
1721	bmi		.Lxts_enc_done
1722
1723	vldmia		$magic, {$twmask}	@ load XTS magic
1724	vshr.s64	@T[0], @XMM[8], #63
1725	mov		r0, sp
1726	vand		@T[0], @T[0], $twmask
1727___
1728for($i=9;$i<16;$i++) {
1729$code.=<<___;
1730	vadd.u64	@XMM[$i], @XMM[$i-1], @XMM[$i-1]
1731	vst1.64		{@XMM[$i-1]}, [r0,:128]!
1732	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
1733	vshr.s64	@T[1], @XMM[$i], #63
1734	veor		@XMM[$i], @XMM[$i], @T[0]
1735	vand		@T[1], @T[1], $twmask
1736___
1737	@T=reverse(@T);
1738
1739$code.=<<___ if ($i>=10);
1740	vld1.8		{@XMM[$i-10]}, [$inp]!
1741	subs		$len, #0x10
1742	bmi		.Lxts_enc_`$i-9`
1743___
1744$code.=<<___ if ($i>=11);
1745	veor		@XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
1746___
1747}
1748$code.=<<___;
1749	sub		$len, #0x10
1750	vst1.64		{@XMM[15]}, [r0,:128]		@ next round tweak
1751
1752	vld1.8		{@XMM[6]}, [$inp]!
1753	veor		@XMM[5], @XMM[5], @XMM[13]
1754#ifndef	BSAES_ASM_EXTENDED_KEY
1755	add		r4, sp, #0x90			@ pass key schedule
1756#else
1757	add		r4, $key, #248			@ pass key schedule
1758#endif
1759	veor		@XMM[6], @XMM[6], @XMM[14]
1760	mov		r5, $rounds			@ pass rounds
1761	mov		r0, sp
1762
1763	bl		_bsaes_encrypt8
1764
1765	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1766	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
1767	veor		@XMM[0], @XMM[0], @XMM[ 8]
1768	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
1769	veor		@XMM[1], @XMM[1], @XMM[ 9]
1770	veor		@XMM[8], @XMM[4], @XMM[10]
1771	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
1772	veor		@XMM[9], @XMM[6], @XMM[11]
1773	vld1.64		{@XMM[14]}, [r0,:128]!
1774	veor		@XMM[10], @XMM[3], @XMM[12]
1775	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
1776	veor		@XMM[11], @XMM[7], @XMM[13]
1777	veor		@XMM[12], @XMM[2], @XMM[14]
1778	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
1779	vst1.8		{@XMM[12]}, [$out]!
1780
1781	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
1782	b		.Lxts_enc_done
1783.align	4
1784.Lxts_enc_6:
1785	veor		@XMM[4], @XMM[4], @XMM[12]
1786#ifndef	BSAES_ASM_EXTENDED_KEY
1787	add		r4, sp, #0x90			@ pass key schedule
1788#else
1789	add		r4, $key, #248			@ pass key schedule
1790#endif
1791	veor		@XMM[5], @XMM[5], @XMM[13]
1792	mov		r5, $rounds			@ pass rounds
1793	mov		r0, sp
1794
1795	bl		_bsaes_encrypt8
1796
1797	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1798	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
1799	veor		@XMM[0], @XMM[0], @XMM[ 8]
1800	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
1801	veor		@XMM[1], @XMM[1], @XMM[ 9]
1802	veor		@XMM[8], @XMM[4], @XMM[10]
1803	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
1804	veor		@XMM[9], @XMM[6], @XMM[11]
1805	veor		@XMM[10], @XMM[3], @XMM[12]
1806	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
1807	veor		@XMM[11], @XMM[7], @XMM[13]
1808	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
1809
1810	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
1811	b		.Lxts_enc_done
1812
1813@ put this in range for both ARM and Thumb mode adr instructions
1814.align	5
1815.Lxts_magic:
1816	.quad	1, 0x87
1817
1818.align	5
1819.Lxts_enc_5:
1820	veor		@XMM[3], @XMM[3], @XMM[11]
1821#ifndef	BSAES_ASM_EXTENDED_KEY
1822	add		r4, sp, #0x90			@ pass key schedule
1823#else
1824	add		r4, $key, #248			@ pass key schedule
1825#endif
1826	veor		@XMM[4], @XMM[4], @XMM[12]
1827	mov		r5, $rounds			@ pass rounds
1828	mov		r0, sp
1829
1830	bl		_bsaes_encrypt8
1831
1832	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1833	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
1834	veor		@XMM[0], @XMM[0], @XMM[ 8]
1835	vld1.64		{@XMM[12]}, [r0,:128]!
1836	veor		@XMM[1], @XMM[1], @XMM[ 9]
1837	veor		@XMM[8], @XMM[4], @XMM[10]
1838	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
1839	veor		@XMM[9], @XMM[6], @XMM[11]
1840	veor		@XMM[10], @XMM[3], @XMM[12]
1841	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
1842	vst1.8		{@XMM[10]}, [$out]!
1843
1844	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
1845	b		.Lxts_enc_done
1846.align	4
1847.Lxts_enc_4:
1848	veor		@XMM[2], @XMM[2], @XMM[10]
1849#ifndef	BSAES_ASM_EXTENDED_KEY
1850	add		r4, sp, #0x90			@ pass key schedule
1851#else
1852	add		r4, $key, #248			@ pass key schedule
1853#endif
1854	veor		@XMM[3], @XMM[3], @XMM[11]
1855	mov		r5, $rounds			@ pass rounds
1856	mov		r0, sp
1857
1858	bl		_bsaes_encrypt8
1859
1860	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1861	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
1862	veor		@XMM[0], @XMM[0], @XMM[ 8]
1863	veor		@XMM[1], @XMM[1], @XMM[ 9]
1864	veor		@XMM[8], @XMM[4], @XMM[10]
1865	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
1866	veor		@XMM[9], @XMM[6], @XMM[11]
1867	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
1868
1869	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
1870	b		.Lxts_enc_done
1871.align	4
1872.Lxts_enc_3:
1873	veor		@XMM[1], @XMM[1], @XMM[9]
1874#ifndef	BSAES_ASM_EXTENDED_KEY
1875	add		r4, sp, #0x90			@ pass key schedule
1876#else
1877	add		r4, $key, #248			@ pass key schedule
1878#endif
1879	veor		@XMM[2], @XMM[2], @XMM[10]
1880	mov		r5, $rounds			@ pass rounds
1881	mov		r0, sp
1882
1883	bl		_bsaes_encrypt8
1884
1885	vld1.64		{@XMM[8]-@XMM[9]}, [r0,:128]!
1886	vld1.64		{@XMM[10]}, [r0,:128]!
1887	veor		@XMM[0], @XMM[0], @XMM[ 8]
1888	veor		@XMM[1], @XMM[1], @XMM[ 9]
1889	veor		@XMM[8], @XMM[4], @XMM[10]
1890	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
1891	vst1.8		{@XMM[8]}, [$out]!
1892
1893	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
1894	b		.Lxts_enc_done
1895.align	4
1896.Lxts_enc_2:
1897	veor		@XMM[0], @XMM[0], @XMM[8]
1898#ifndef	BSAES_ASM_EXTENDED_KEY
1899	add		r4, sp, #0x90			@ pass key schedule
1900#else
1901	add		r4, $key, #248			@ pass key schedule
1902#endif
1903	veor		@XMM[1], @XMM[1], @XMM[9]
1904	mov		r5, $rounds			@ pass rounds
1905	mov		r0, sp
1906
1907	bl		_bsaes_encrypt8
1908
1909	vld1.64		{@XMM[8]-@XMM[9]}, [r0,:128]!
1910	veor		@XMM[0], @XMM[0], @XMM[ 8]
1911	veor		@XMM[1], @XMM[1], @XMM[ 9]
1912	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
1913
1914	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
1915	b		.Lxts_enc_done
1916.align	4
1917.Lxts_enc_1:
1918	mov		r0, sp
1919	veor		@XMM[0], @XMM[0], @XMM[8]
1920	mov		r1, sp
1921	vst1.8		{@XMM[0]}, [sp,:128]
1922	mov		r2, $key
1923	mov		r4, $fp				@ preserve fp
1924
1925	bl		aes_nohw_encrypt
1926
1927	vld1.8		{@XMM[0]}, [sp,:128]
1928	veor		@XMM[0], @XMM[0], @XMM[8]
1929	vst1.8		{@XMM[0]}, [$out]!
1930	mov		$fp, r4
1931
1932	vmov		@XMM[8], @XMM[9]		@ next round tweak
1933
1934.Lxts_enc_done:
1935#ifndef	XTS_CHAIN_TWEAK
1936	adds		$len, #0x10
1937	beq		.Lxts_enc_ret
1938	sub		r6, $out, #0x10
1939
1940.Lxts_enc_steal:
1941	ldrb		r0, [$inp], #1
1942	ldrb		r1, [$out, #-0x10]
1943	strb		r0, [$out, #-0x10]
1944	strb		r1, [$out], #1
1945
1946	subs		$len, #1
1947	bhi		.Lxts_enc_steal
1948
1949	vld1.8		{@XMM[0]}, [r6]
1950	mov		r0, sp
1951	veor		@XMM[0], @XMM[0], @XMM[8]
1952	mov		r1, sp
1953	vst1.8		{@XMM[0]}, [sp,:128]
1954	mov		r2, $key
1955	mov		r4, $fp			@ preserve fp
1956
1957	bl		aes_nohw_encrypt
1958
1959	vld1.8		{@XMM[0]}, [sp,:128]
1960	veor		@XMM[0], @XMM[0], @XMM[8]
1961	vst1.8		{@XMM[0]}, [r6]
1962	mov		$fp, r4
1963#endif
1964
1965.Lxts_enc_ret:
1966	bic		r0, $fp, #0xf
1967	vmov.i32	q0, #0
1968	vmov.i32	q1, #0
1969#ifdef	XTS_CHAIN_TWEAK
1970	ldr		r1, [$fp, #0x20+VFP_ABI_FRAME]	@ chain tweak
1971#endif
1972.Lxts_enc_bzero:				@ wipe key schedule [if any]
1973	vstmia		sp!, {q0-q1}
1974	cmp		sp, r0
1975	bne		.Lxts_enc_bzero
1976
1977	mov		sp, $fp
1978#ifdef	XTS_CHAIN_TWEAK
1979	vst1.8		{@XMM[8]}, [r1]
1980#endif
1981	VFP_ABI_POP
1982	ldmia		sp!, {r4-r10, pc}	@ return
1983
1984.size	bsaes_xts_encrypt,.-bsaes_xts_encrypt
1985
1986.globl	bsaes_xts_decrypt
1987.type	bsaes_xts_decrypt,%function
1988.align	4
1989bsaes_xts_decrypt:
1990	mov	ip, sp
1991	stmdb	sp!, {r4-r10, lr}		@ 0x20
1992	VFP_ABI_PUSH
1993	mov	r6, sp				@ future $fp
1994
1995	mov	$inp, r0
1996	mov	$out, r1
1997	mov	$len, r2
1998	mov	$key, r3
1999
2000	sub	r0, sp, #0x10			@ 0x10
2001	bic	r0, #0xf			@ align at 16 bytes
2002	mov	sp, r0
2003
2004#ifdef	XTS_CHAIN_TWEAK
2005	ldr	r0, [ip]			@ pointer to input tweak
2006#else
2007	@ generate initial tweak
2008	ldr	r0, [ip, #4]			@ iv[]
2009	mov	r1, sp
2010	ldr	r2, [ip, #0]			@ key2
2011	bl	aes_nohw_encrypt
2012	mov	r0, sp				@ pointer to initial tweak
2013#endif
2014
2015	ldr	$rounds, [$key, #240]		@ get # of rounds
2016	mov	$fp, r6
2017#ifndef	BSAES_ASM_EXTENDED_KEY
2018	@ allocate the key schedule on the stack
2019	sub	r12, sp, $rounds, lsl#7		@ 128 bytes per inner round key
2020	@ add	r12, #`128-32`			@ size of bit-sliced key schedule
2021	sub	r12, #`32+16`			@ place for tweak[9]
2022
2023	@ populate the key schedule
2024	mov	r4, $key			@ pass key
2025	mov	r5, $rounds			@ pass # of rounds
2026	mov	sp, r12
2027	add	r12, #0x90			@ pass key schedule
2028	bl	_bsaes_key_convert
2029	add	r4, sp, #0x90
2030	vldmia	r4, {@XMM[6]}
2031	vstmia	r12,  {@XMM[15]}		@ save last round key
2032	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
2033	vstmia	r4, {@XMM[7]}
2034#else
2035	ldr	r12, [$key, #244]
2036	eors	r12, #1
2037	beq	0f
2038
2039	str	r12, [$key, #244]
2040	mov	r4, $key			@ pass key
2041	mov	r5, $rounds			@ pass # of rounds
2042	add	r12, $key, #248			@ pass key schedule
2043	bl	_bsaes_key_convert
2044	add	r4, $key, #248
2045	vldmia	r4, {@XMM[6]}
2046	vstmia	r12,  {@XMM[15]}		@ save last round key
2047	veor	@XMM[7], @XMM[7], @XMM[6]	@ fix up round 0 key
2048	vstmia	r4, {@XMM[7]}
2049
2050.align	2
20510:	sub	sp, #0x90			@ place for tweak[9]
2052#endif
2053	vld1.8	{@XMM[8]}, [r0]			@ initial tweak
2054	adr	$magic, .Lxts_magic
2055
2056#ifndef	XTS_CHAIN_TWEAK
2057	tst	$len, #0xf			@ if not multiple of 16
2058	it	ne				@ Thumb2 thing, sanity check in ARM
2059	subne	$len, #0x10			@ subtract another 16 bytes
2060#endif
2061	subs	$len, #0x80
2062
2063	blo	.Lxts_dec_short
2064	b	.Lxts_dec_loop
2065
2066.align	4
2067.Lxts_dec_loop:
2068	vldmia		$magic, {$twmask}	@ load XTS magic
2069	vshr.s64	@T[0], @XMM[8], #63
2070	mov		r0, sp
2071	vand		@T[0], @T[0], $twmask
2072___
2073for($i=9;$i<16;$i++) {
2074$code.=<<___;
2075	vadd.u64	@XMM[$i], @XMM[$i-1], @XMM[$i-1]
2076	vst1.64		{@XMM[$i-1]}, [r0,:128]!
2077	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
2078	vshr.s64	@T[1], @XMM[$i], #63
2079	veor		@XMM[$i], @XMM[$i], @T[0]
2080	vand		@T[1], @T[1], $twmask
2081___
2082	@T=reverse(@T);
2083
2084$code.=<<___ if ($i>=10);
2085	vld1.8		{@XMM[$i-10]}, [$inp]!
2086___
2087$code.=<<___ if ($i>=11);
2088	veor		@XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
2089___
2090}
2091$code.=<<___;
2092	vadd.u64	@XMM[8], @XMM[15], @XMM[15]
2093	vst1.64		{@XMM[15]}, [r0,:128]!
2094	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
2095	veor		@XMM[8], @XMM[8], @T[0]
2096	vst1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
2097
2098	vld1.8		{@XMM[6]-@XMM[7]}, [$inp]!
2099	veor		@XMM[5], @XMM[5], @XMM[13]
2100#ifndef	BSAES_ASM_EXTENDED_KEY
2101	add		r4, sp, #0x90			@ pass key schedule
2102#else
2103	add		r4, $key, #248			@ pass key schedule
2104#endif
2105	veor		@XMM[6], @XMM[6], @XMM[14]
2106	mov		r5, $rounds			@ pass rounds
2107	veor		@XMM[7], @XMM[7], @XMM[15]
2108	mov		r0, sp
2109
2110	bl		_bsaes_decrypt8
2111
2112	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
2113	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
2114	veor		@XMM[0], @XMM[0], @XMM[ 8]
2115	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
2116	veor		@XMM[1], @XMM[1], @XMM[ 9]
2117	veor		@XMM[8], @XMM[6], @XMM[10]
2118	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
2119	veor		@XMM[9], @XMM[4], @XMM[11]
2120	vld1.64		{@XMM[14]-@XMM[15]}, [r0,:128]!
2121	veor		@XMM[10], @XMM[2], @XMM[12]
2122	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
2123	veor		@XMM[11], @XMM[7], @XMM[13]
2124	veor		@XMM[12], @XMM[3], @XMM[14]
2125	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
2126	veor		@XMM[13], @XMM[5], @XMM[15]
2127	vst1.8		{@XMM[12]-@XMM[13]}, [$out]!
2128
2129	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
2130
2131	subs		$len, #0x80
2132	bpl		.Lxts_dec_loop
2133
2134.Lxts_dec_short:
2135	adds		$len, #0x70
2136	bmi		.Lxts_dec_done
2137
2138	vldmia		$magic, {$twmask}	@ load XTS magic
2139	vshr.s64	@T[0], @XMM[8], #63
2140	mov		r0, sp
2141	vand		@T[0], @T[0], $twmask
2142___
2143for($i=9;$i<16;$i++) {
2144$code.=<<___;
2145	vadd.u64	@XMM[$i], @XMM[$i-1], @XMM[$i-1]
2146	vst1.64		{@XMM[$i-1]}, [r0,:128]!
2147	vswp		`&Dhi("@T[0]")`,`&Dlo("@T[0]")`
2148	vshr.s64	@T[1], @XMM[$i], #63
2149	veor		@XMM[$i], @XMM[$i], @T[0]
2150	vand		@T[1], @T[1], $twmask
2151___
2152	@T=reverse(@T);
2153
2154$code.=<<___ if ($i>=10);
2155	vld1.8		{@XMM[$i-10]}, [$inp]!
2156	subs		$len, #0x10
2157	bmi		.Lxts_dec_`$i-9`
2158___
2159$code.=<<___ if ($i>=11);
2160	veor		@XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
2161___
2162}
2163$code.=<<___;
2164	sub		$len, #0x10
2165	vst1.64		{@XMM[15]}, [r0,:128]		@ next round tweak
2166
2167	vld1.8		{@XMM[6]}, [$inp]!
2168	veor		@XMM[5], @XMM[5], @XMM[13]
2169#ifndef	BSAES_ASM_EXTENDED_KEY
2170	add		r4, sp, #0x90			@ pass key schedule
2171#else
2172	add		r4, $key, #248			@ pass key schedule
2173#endif
2174	veor		@XMM[6], @XMM[6], @XMM[14]
2175	mov		r5, $rounds			@ pass rounds
2176	mov		r0, sp
2177
2178	bl		_bsaes_decrypt8
2179
2180	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
2181	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
2182	veor		@XMM[0], @XMM[0], @XMM[ 8]
2183	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
2184	veor		@XMM[1], @XMM[1], @XMM[ 9]
2185	veor		@XMM[8], @XMM[6], @XMM[10]
2186	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
2187	veor		@XMM[9], @XMM[4], @XMM[11]
2188	vld1.64		{@XMM[14]}, [r0,:128]!
2189	veor		@XMM[10], @XMM[2], @XMM[12]
2190	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
2191	veor		@XMM[11], @XMM[7], @XMM[13]
2192	veor		@XMM[12], @XMM[3], @XMM[14]
2193	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
2194	vst1.8		{@XMM[12]}, [$out]!
2195
2196	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
2197	b		.Lxts_dec_done
2198.align	4
2199.Lxts_dec_6:
2200	vst1.64		{@XMM[14]}, [r0,:128]		@ next round tweak
2201
2202	veor		@XMM[4], @XMM[4], @XMM[12]
2203#ifndef	BSAES_ASM_EXTENDED_KEY
2204	add		r4, sp, #0x90			@ pass key schedule
2205#else
2206	add		r4, $key, #248			@ pass key schedule
2207#endif
2208	veor		@XMM[5], @XMM[5], @XMM[13]
2209	mov		r5, $rounds			@ pass rounds
2210	mov		r0, sp
2211
2212	bl		_bsaes_decrypt8
2213
2214	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
2215	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
2216	veor		@XMM[0], @XMM[0], @XMM[ 8]
2217	vld1.64		{@XMM[12]-@XMM[13]}, [r0,:128]!
2218	veor		@XMM[1], @XMM[1], @XMM[ 9]
2219	veor		@XMM[8], @XMM[6], @XMM[10]
2220	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
2221	veor		@XMM[9], @XMM[4], @XMM[11]
2222	veor		@XMM[10], @XMM[2], @XMM[12]
2223	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
2224	veor		@XMM[11], @XMM[7], @XMM[13]
2225	vst1.8		{@XMM[10]-@XMM[11]}, [$out]!
2226
2227	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
2228	b		.Lxts_dec_done
2229.align	4
2230.Lxts_dec_5:
2231	veor		@XMM[3], @XMM[3], @XMM[11]
2232#ifndef	BSAES_ASM_EXTENDED_KEY
2233	add		r4, sp, #0x90			@ pass key schedule
2234#else
2235	add		r4, $key, #248			@ pass key schedule
2236#endif
2237	veor		@XMM[4], @XMM[4], @XMM[12]
2238	mov		r5, $rounds			@ pass rounds
2239	mov		r0, sp
2240
2241	bl		_bsaes_decrypt8
2242
2243	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
2244	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
2245	veor		@XMM[0], @XMM[0], @XMM[ 8]
2246	vld1.64		{@XMM[12]}, [r0,:128]!
2247	veor		@XMM[1], @XMM[1], @XMM[ 9]
2248	veor		@XMM[8], @XMM[6], @XMM[10]
2249	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
2250	veor		@XMM[9], @XMM[4], @XMM[11]
2251	veor		@XMM[10], @XMM[2], @XMM[12]
2252	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
2253	vst1.8		{@XMM[10]}, [$out]!
2254
2255	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
2256	b		.Lxts_dec_done
2257.align	4
2258.Lxts_dec_4:
2259	veor		@XMM[2], @XMM[2], @XMM[10]
2260#ifndef	BSAES_ASM_EXTENDED_KEY
2261	add		r4, sp, #0x90			@ pass key schedule
2262#else
2263	add		r4, $key, #248			@ pass key schedule
2264#endif
2265	veor		@XMM[3], @XMM[3], @XMM[11]
2266	mov		r5, $rounds			@ pass rounds
2267	mov		r0, sp
2268
2269	bl		_bsaes_decrypt8
2270
2271	vld1.64		{@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
2272	vld1.64		{@XMM[10]-@XMM[11]}, [r0,:128]!
2273	veor		@XMM[0], @XMM[0], @XMM[ 8]
2274	veor		@XMM[1], @XMM[1], @XMM[ 9]
2275	veor		@XMM[8], @XMM[6], @XMM[10]
2276	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
2277	veor		@XMM[9], @XMM[4], @XMM[11]
2278	vst1.8		{@XMM[8]-@XMM[9]}, [$out]!
2279
2280	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
2281	b		.Lxts_dec_done
2282.align	4
2283.Lxts_dec_3:
2284	veor		@XMM[1], @XMM[1], @XMM[9]
2285#ifndef	BSAES_ASM_EXTENDED_KEY
2286	add		r4, sp, #0x90			@ pass key schedule
2287#else
2288	add		r4, $key, #248			@ pass key schedule
2289#endif
2290	veor		@XMM[2], @XMM[2], @XMM[10]
2291	mov		r5, $rounds			@ pass rounds
2292	mov		r0, sp
2293
2294	bl		_bsaes_decrypt8
2295
2296	vld1.64		{@XMM[8]-@XMM[9]}, [r0,:128]!
2297	vld1.64		{@XMM[10]}, [r0,:128]!
2298	veor		@XMM[0], @XMM[0], @XMM[ 8]
2299	veor		@XMM[1], @XMM[1], @XMM[ 9]
2300	veor		@XMM[8], @XMM[6], @XMM[10]
2301	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
2302	vst1.8		{@XMM[8]}, [$out]!
2303
2304	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
2305	b		.Lxts_dec_done
2306.align	4
2307.Lxts_dec_2:
2308	veor		@XMM[0], @XMM[0], @XMM[8]
2309#ifndef	BSAES_ASM_EXTENDED_KEY
2310	add		r4, sp, #0x90			@ pass key schedule
2311#else
2312	add		r4, $key, #248			@ pass key schedule
2313#endif
2314	veor		@XMM[1], @XMM[1], @XMM[9]
2315	mov		r5, $rounds			@ pass rounds
2316	mov		r0, sp
2317
2318	bl		_bsaes_decrypt8
2319
2320	vld1.64		{@XMM[8]-@XMM[9]}, [r0,:128]!
2321	veor		@XMM[0], @XMM[0], @XMM[ 8]
2322	veor		@XMM[1], @XMM[1], @XMM[ 9]
2323	vst1.8		{@XMM[0]-@XMM[1]}, [$out]!
2324
2325	vld1.64		{@XMM[8]}, [r0,:128]		@ next round tweak
2326	b		.Lxts_dec_done
2327.align	4
2328.Lxts_dec_1:
2329	mov		r0, sp
2330	veor		@XMM[0], @XMM[0], @XMM[8]
2331	mov		r1, sp
2332	vst1.8		{@XMM[0]}, [sp,:128]
2333	mov		r5, $magic			@ preserve magic
2334	mov		r2, $key
2335	mov		r4, $fp				@ preserve fp
2336
2337	bl		aes_nohw_decrypt
2338
2339	vld1.8		{@XMM[0]}, [sp,:128]
2340	veor		@XMM[0], @XMM[0], @XMM[8]
2341	vst1.8		{@XMM[0]}, [$out]!
2342	mov		$fp, r4
2343	mov		$magic, r5
2344
2345	vmov		@XMM[8], @XMM[9]		@ next round tweak
2346
2347.Lxts_dec_done:
2348#ifndef	XTS_CHAIN_TWEAK
2349	adds		$len, #0x10
2350	beq		.Lxts_dec_ret
2351
2352	@ calculate one round of extra tweak for the stolen ciphertext
2353	vldmia		$magic, {$twmask}
2354	vshr.s64	@XMM[6], @XMM[8], #63
2355	vand		@XMM[6], @XMM[6], $twmask
2356	vadd.u64	@XMM[9], @XMM[8], @XMM[8]
2357	vswp		`&Dhi("@XMM[6]")`,`&Dlo("@XMM[6]")`
2358	veor		@XMM[9], @XMM[9], @XMM[6]
2359
2360	@ perform the final decryption with the last tweak value
2361	vld1.8		{@XMM[0]}, [$inp]!
2362	mov		r0, sp
2363	veor		@XMM[0], @XMM[0], @XMM[9]
2364	mov		r1, sp
2365	vst1.8		{@XMM[0]}, [sp,:128]
2366	mov		r2, $key
2367	mov		r4, $fp			@ preserve fp
2368
2369	bl		aes_nohw_decrypt
2370
2371	vld1.8		{@XMM[0]}, [sp,:128]
2372	veor		@XMM[0], @XMM[0], @XMM[9]
2373	vst1.8		{@XMM[0]}, [$out]
2374
2375	mov		r6, $out
2376.Lxts_dec_steal:
2377	ldrb		r1, [$out]
2378	ldrb		r0, [$inp], #1
2379	strb		r1, [$out, #0x10]
2380	strb		r0, [$out], #1
2381
2382	subs		$len, #1
2383	bhi		.Lxts_dec_steal
2384
2385	vld1.8		{@XMM[0]}, [r6]
2386	mov		r0, sp
2387	veor		@XMM[0], @XMM[8]
2388	mov		r1, sp
2389	vst1.8		{@XMM[0]}, [sp,:128]
2390	mov		r2, $key
2391
2392	bl		aes_nohw_decrypt
2393
2394	vld1.8		{@XMM[0]}, [sp,:128]
2395	veor		@XMM[0], @XMM[0], @XMM[8]
2396	vst1.8		{@XMM[0]}, [r6]
2397	mov		$fp, r4
2398#endif
2399
2400.Lxts_dec_ret:
2401	bic		r0, $fp, #0xf
2402	vmov.i32	q0, #0
2403	vmov.i32	q1, #0
2404#ifdef	XTS_CHAIN_TWEAK
2405	ldr		r1, [$fp, #0x20+VFP_ABI_FRAME]	@ chain tweak
2406#endif
2407.Lxts_dec_bzero:				@ wipe key schedule [if any]
2408	vstmia		sp!, {q0-q1}
2409	cmp		sp, r0
2410	bne		.Lxts_dec_bzero
2411
2412	mov		sp, $fp
2413#ifdef	XTS_CHAIN_TWEAK
2414	vst1.8		{@XMM[8]}, [r1]
2415#endif
2416	VFP_ABI_POP
2417	ldmia		sp!, {r4-r10, pc}	@ return
2418
2419.size	bsaes_xts_decrypt,.-bsaes_xts_decrypt
2420___
2421}
2422$code.=<<___;
2423#endif
2424___
2425
2426$code =~ s/\`([^\`]*)\`/eval($1)/gem;
2427
2428open SELF,$0;
2429while(<SELF>) {
2430	next if (/^#!/);
2431        last if (!s/^#/@/ and !/^$/);
2432        print;
2433}
2434close SELF;
2435
2436print $code;
2437
2438close STDOUT or die "error closing STDOUT: $!";
2439