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