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