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 # ====================================================================
10 # Bit-sliced AES for ARM NEON
14 # This implementation is direct adaptation of bsaes-x86_64 module for
15 # ARM NEON. Except that this module is endian-neutral [in sense that
16 # it can be compiled for either endianness] by courtesy of vld1.8's
17 # neutrality. Initial version doesn't implement interface to OpenSSL,
18 # only low-level primitives and unsupported entry points, just enough
19 # to collect performance results, which for Cortex-A8 core are:
21 # encrypt 19.5 cycles per byte processed with 128-bit key
22 # decrypt 24.0 cycles per byte processed with 128-bit key
23 # key conv. 440 cycles per 128-bit key/0.18 of 8x block
25 # Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 22.6,
26 # which is [much] worse than anticipated (for further details see
27 # http://www.openssl.org/~appro/Snapdragon-S4.html).
29 # Cortex-A15 manages in 14.2/19.6 cycles [when integer-only code
30 # manages in 20.0 cycles].
32 # When comparing to x86_64 results keep in mind that NEON unit is
33 # [mostly] single-issue and thus can't [fully] benefit from
34 # instruction-level parallelism. And when comparing to aes-armv4
35 # results keep in mind key schedule conversion overhead (see
36 # bsaes-x86_64.pl for further details)...
40 while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
41 open STDOUT,">$output";
43 my ($inp,$out,$len,$key)=("r0","r1","r2","r3");
44 my @XMM=map("q$_",(0..15));
47 my ($key,$rounds,$const)=("r4","r5","r6");
49 sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; }
50 sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; }
53 # input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
54 # output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
59 &Inv_GF256 (@b[6,5,0,3,7,1,4,2],@t,@s);
60 &OutBasisChange (@b[7,1,4,2,6,5,0,3]);
64 # input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
65 # output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
68 veor @b[2], @b[2], @b[1]
69 veor @b[5], @b[5], @b[6]
70 veor @b[3], @b[3], @b[0]
71 veor @b[6], @b[6], @b[2]
72 veor @b[5], @b[5], @b[0]
74 veor @b[6], @b[6], @b[3]
75 veor @b[3], @b[3], @b[7]
76 veor @b[7], @b[7], @b[5]
77 veor @b[3], @b[3], @b[4]
78 veor @b[4], @b[4], @b[5]
80 veor @b[2], @b[2], @b[7]
81 veor @b[3], @b[3], @b[1]
82 veor @b[1], @b[1], @b[5]
87 # input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
88 # output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
91 veor @b[0], @b[0], @b[6]
92 veor @b[1], @b[1], @b[4]
93 veor @b[4], @b[4], @b[6]
94 veor @b[2], @b[2], @b[0]
95 veor @b[6], @b[6], @b[1]
97 veor @b[1], @b[1], @b[5]
98 veor @b[5], @b[5], @b[3]
99 veor @b[3], @b[3], @b[7]
100 veor @b[7], @b[7], @b[5]
101 veor @b[2], @b[2], @b[5]
103 veor @b[4], @b[4], @b[7]
108 # input in lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
109 # output in lsb > [b0, b1, b6, b4, b2, b7, b3, b5] < msb
113 &InvInBasisChange (@b);
114 &Inv_GF256 (@b[5,1,2,6,3,7,0,4],@t,@s);
115 &InvOutBasisChange (@b[3,7,0,4,5,1,2,6]);
118 sub InvInBasisChange { # OutBasisChange in reverse (with twist)
119 my @b=@_[5,1,2,6,3,7,0,4];
121 veor @b[1], @b[1], @b[7]
122 veor @b[4], @b[4], @b[7]
124 veor @b[7], @b[7], @b[5]
125 veor @b[1], @b[1], @b[3]
126 veor @b[2], @b[2], @b[5]
127 veor @b[3], @b[3], @b[7]
129 veor @b[6], @b[6], @b[1]
130 veor @b[2], @b[2], @b[0]
131 veor @b[5], @b[5], @b[3]
132 veor @b[4], @b[4], @b[6]
133 veor @b[0], @b[0], @b[6]
134 veor @b[1], @b[1], @b[4]
138 sub InvOutBasisChange { # InBasisChange in reverse
139 my @b=@_[2,5,7,3,6,1,0,4];
141 veor @b[1], @b[1], @b[5]
142 veor @b[2], @b[2], @b[7]
144 veor @b[3], @b[3], @b[1]
145 veor @b[4], @b[4], @b[5]
146 veor @b[7], @b[7], @b[5]
147 veor @b[3], @b[3], @b[4]
148 veor @b[5], @b[5], @b[0]
149 veor @b[3], @b[3], @b[7]
150 veor @b[6], @b[6], @b[2]
151 veor @b[2], @b[2], @b[1]
152 veor @b[6], @b[6], @b[3]
154 veor @b[3], @b[3], @b[0]
155 veor @b[5], @b[5], @b[6]
160 #;*************************************************************
161 #;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
162 #;*************************************************************
163 my ($x0,$x1,$y0,$y1,$t0,$t1)=@_;
175 sub Mul_GF4_N { # not used, see next subroutine
176 # multiply and scale by N
177 my ($x0,$x1,$y0,$y1,$t0)=@_;
190 # interleaved Mul_GF4_N and Mul_GF4
191 my ($x0,$x1,$y0,$y1,$t0,
192 $x2,$x3,$y2,$y3,$t1)=@_;
215 veor @t[0], @x[0], @x[2]
216 veor @t[1], @x[1], @x[3]
218 &Mul_GF4 (@x[0], @x[1], @y[0], @y[1], @t[2..3]);
220 veor @y[0], @y[0], @y[2]
221 veor @y[1], @y[1], @y[3]
223 Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
224 @x[2], @x[3], @y[2], @y[3], @t[2]);
226 veor @x[0], @x[0], @t[0]
227 veor @x[2], @x[2], @t[0]
228 veor @x[1], @x[1], @t[1]
229 veor @x[3], @x[3], @t[1]
231 veor @t[0], @x[4], @x[6]
232 veor @t[1], @x[5], @x[7]
234 &Mul_GF4_N_GF4 (@t[0], @t[1], @y[0], @y[1], @t[3],
235 @x[6], @x[7], @y[2], @y[3], @t[2]);
237 veor @y[0], @y[0], @y[2]
238 veor @y[1], @y[1], @y[3]
240 &Mul_GF4 (@x[4], @x[5], @y[0], @y[1], @t[2..3]);
242 veor @x[4], @x[4], @t[0]
243 veor @x[6], @x[6], @t[0]
244 veor @x[5], @x[5], @t[1]
245 veor @x[7], @x[7], @t[1]
249 #;********************************************************************
250 #;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144) *
251 #;********************************************************************
255 # direct optimizations from hardware
257 veor @t[3], @x[4], @x[6]
258 veor @t[2], @x[5], @x[7]
259 veor @t[1], @x[1], @x[3]
260 veor @s[1], @x[7], @x[6]
262 veor @s[0], @x[0], @x[2]
264 vorr @t[2], @t[2], @t[1]
265 veor @s[3], @t[3], @t[0]
266 vand @s[2], @t[3], @s[0]
267 vorr @t[3], @t[3], @s[0]
268 veor @s[0], @s[0], @t[1]
269 vand @t[0], @t[0], @t[1]
270 veor @t[1], @x[3], @x[2]
271 vand @s[3], @s[3], @s[0]
272 vand @s[1], @s[1], @t[1]
273 veor @t[1], @x[4], @x[5]
274 veor @s[0], @x[1], @x[0]
275 veor @t[3], @t[3], @s[1]
276 veor @t[2], @t[2], @s[1]
277 vand @s[1], @t[1], @s[0]
278 vorr @t[1], @t[1], @s[0]
279 veor @t[3], @t[3], @s[3]
280 veor @t[0], @t[0], @s[1]
281 veor @t[2], @t[2], @s[2]
282 veor @t[1], @t[1], @s[3]
283 veor @t[0], @t[0], @s[2]
284 vand @s[0], @x[7], @x[3]
285 veor @t[1], @t[1], @s[2]
286 vand @s[1], @x[6], @x[2]
287 vand @s[2], @x[5], @x[1]
288 vorr @s[3], @x[4], @x[0]
289 veor @t[3], @t[3], @s[0]
290 veor @t[1], @t[1], @s[2]
291 veor @t[0], @t[0], @s[3]
292 veor @t[2], @t[2], @s[1]
294 @ Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
296 @ new smaller inversion
298 vand @s[2], @t[3], @t[1]
301 veor @s[1], @t[2], @s[2]
302 veor @s[3], @t[0], @s[2]
303 veor @s[2], @t[0], @s[2] @ @s[2]=@s[3]
305 vbsl @s[1], @t[1], @t[0]
306 vbsl @s[3], @t[3], @t[2]
307 veor @t[3], @t[3], @t[2]
309 vbsl @s[0], @s[1], @s[2]
310 vbsl @t[0], @s[2], @s[1]
312 vand @s[2], @s[0], @s[3]
313 veor @t[1], @t[1], @t[0]
315 veor @s[2], @s[2], @t[3]
317 # output in s3, s2, s1, t1
319 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
321 # Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
322 &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
324 ### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
327 # AES linear components
334 vldmia $key!, {@t[0]-@t[3]}
335 veor @t[0], @t[0], @x[0]
336 veor @t[1], @t[1], @x[1]
337 vtbl.8 `&Dlo(@x[0])`, {@t[0]}, `&Dlo($mask)`
338 vtbl.8 `&Dhi(@x[0])`, {@t[0]}, `&Dhi($mask)`
339 vldmia $key!, {@t[0]}
340 veor @t[2], @t[2], @x[2]
341 vtbl.8 `&Dlo(@x[1])`, {@t[1]}, `&Dlo($mask)`
342 vtbl.8 `&Dhi(@x[1])`, {@t[1]}, `&Dhi($mask)`
343 vldmia $key!, {@t[1]}
344 veor @t[3], @t[3], @x[3]
345 vtbl.8 `&Dlo(@x[2])`, {@t[2]}, `&Dlo($mask)`
346 vtbl.8 `&Dhi(@x[2])`, {@t[2]}, `&Dhi($mask)`
347 vldmia $key!, {@t[2]}
348 vtbl.8 `&Dlo(@x[3])`, {@t[3]}, `&Dlo($mask)`
349 vtbl.8 `&Dhi(@x[3])`, {@t[3]}, `&Dhi($mask)`
350 vldmia $key!, {@t[3]}
351 veor @t[0], @t[0], @x[4]
352 veor @t[1], @t[1], @x[5]
353 vtbl.8 `&Dlo(@x[4])`, {@t[0]}, `&Dlo($mask)`
354 vtbl.8 `&Dhi(@x[4])`, {@t[0]}, `&Dhi($mask)`
355 veor @t[2], @t[2], @x[6]
356 vtbl.8 `&Dlo(@x[5])`, {@t[1]}, `&Dlo($mask)`
357 vtbl.8 `&Dhi(@x[5])`, {@t[1]}, `&Dhi($mask)`
358 veor @t[3], @t[3], @x[7]
359 vtbl.8 `&Dlo(@x[6])`, {@t[2]}, `&Dlo($mask)`
360 vtbl.8 `&Dhi(@x[6])`, {@t[2]}, `&Dhi($mask)`
361 vtbl.8 `&Dlo(@x[7])`, {@t[3]}, `&Dlo($mask)`
362 vtbl.8 `&Dhi(@x[7])`, {@t[3]}, `&Dhi($mask)`
367 # modified to emit output in order suitable for feeding back to aesenc[last]
371 vext.8 @t[0], @x[0], @x[0], #12 @ x0 <<< 32
372 vext.8 @t[1], @x[1], @x[1], #12
373 veor @x[0], @x[0], @t[0] @ x0 ^ (x0 <<< 32)
374 vext.8 @t[2], @x[2], @x[2], #12
375 veor @x[1], @x[1], @t[1]
376 vext.8 @t[3], @x[3], @x[3], #12
377 veor @x[2], @x[2], @t[2]
378 vext.8 @t[4], @x[4], @x[4], #12
379 veor @x[3], @x[3], @t[3]
380 vext.8 @t[5], @x[5], @x[5], #12
381 veor @x[4], @x[4], @t[4]
382 vext.8 @t[6], @x[6], @x[6], #12
383 veor @x[5], @x[5], @t[5]
384 vext.8 @t[7], @x[7], @x[7], #12
385 veor @x[6], @x[6], @t[6]
387 veor @t[1], @t[1], @x[0]
388 veor @x[7], @x[7], @t[7]
389 vext.8 @x[0], @x[0], @x[0], #8 @ (x0 ^ (x0 <<< 32)) <<< 64)
390 veor @t[2], @t[2], @x[1]
391 veor @t[0], @t[0], @x[7]
392 veor @t[1], @t[1], @x[7]
393 vext.8 @x[1], @x[1], @x[1], #8
394 veor @t[5], @t[5], @x[4]
395 veor @x[0], @x[0], @t[0]
396 veor @t[6], @t[6], @x[5]
397 veor @x[1], @x[1], @t[1]
398 vext.8 @t[0], @x[4], @x[4], #8
399 veor @t[4], @t[4], @x[3]
400 vext.8 @t[1], @x[5], @x[5], #8
401 veor @t[7], @t[7], @x[6]
402 vext.8 @x[4], @x[3], @x[3], #8
403 veor @t[3], @t[3], @x[2]
404 vext.8 @x[5], @x[7], @x[7], #8
405 veor @t[4], @t[4], @x[7]
406 vext.8 @x[3], @x[6], @x[6], #8
407 veor @t[3], @t[3], @x[7]
408 vext.8 @x[6], @x[2], @x[2], #8
409 veor @x[7], @t[1], @t[5]
410 veor @x[2], @t[0], @t[4]
412 veor @x[4], @x[4], @t[3]
413 veor @x[5], @x[5], @t[7]
414 veor @x[3], @x[3], @t[6]
416 veor @x[6], @x[6], @t[2]
426 @ multiplication by 0x0e
427 vext.8 @t[7], @x[7], @x[7], #12
429 veor @x[2], @x[2], @x[5] @ 2 5
430 veor @x[7], @x[7], @x[5] @ 7 5
431 vext.8 @t[0], @x[0], @x[0], #12
433 veor @x[5], @x[5], @x[0] @ 5 0 [1]
434 veor @x[0], @x[0], @x[1] @ 0 1
435 vext.8 @t[1], @x[1], @x[1], #12
436 veor @x[1], @x[1], @x[2] @ 1 25
437 veor @x[0], @x[0], @x[6] @ 01 6 [2]
438 vext.8 @t[3], @x[3], @x[3], #12
439 veor @x[1], @x[1], @x[3] @ 125 3 [4]
440 veor @x[2], @x[2], @x[0] @ 25 016 [3]
441 veor @x[3], @x[3], @x[7] @ 3 75
442 veor @x[7], @x[7], @x[6] @ 75 6 [0]
443 vext.8 @t[6], @x[6], @x[6], #12
445 veor @x[6], @x[6], @x[4] @ 6 4
446 veor @x[4], @x[4], @x[3] @ 4 375 [6]
447 veor @x[3], @x[3], @x[7] @ 375 756=36
448 veor @x[6], @x[6], @t[5] @ 64 5 [7]
449 veor @x[3], @x[3], @t[2] @ 36 2
450 vext.8 @t[5], @t[5], @t[5], #12
451 veor @x[3], @x[3], @t[4] @ 362 4 [5]
453 my @y = @x[7,5,0,2,1,3,4,6];
455 @ multiplication by 0x0b
456 veor @y[1], @y[1], @y[0]
457 veor @y[0], @y[0], @t[0]
458 vext.8 @t[2], @t[2], @t[2], #12
459 veor @y[1], @y[1], @t[1]
460 veor @y[0], @y[0], @t[5]
461 vext.8 @t[4], @t[4], @t[4], #12
462 veor @y[1], @y[1], @t[6]
463 veor @y[0], @y[0], @t[7]
464 veor @t[7], @t[7], @t[6] @ clobber t[7]
466 veor @y[3], @y[3], @t[0]
467 veor @y[1], @y[1], @y[0]
468 vext.8 @t[0], @t[0], @t[0], #12
469 veor @y[2], @y[2], @t[1]
470 veor @y[4], @y[4], @t[1]
471 vext.8 @t[1], @t[1], @t[1], #12
472 veor @y[2], @y[2], @t[2]
473 veor @y[3], @y[3], @t[2]
474 veor @y[5], @y[5], @t[2]
475 veor @y[2], @y[2], @t[7]
476 vext.8 @t[2], @t[2], @t[2], #12
477 veor @y[3], @y[3], @t[3]
478 veor @y[6], @y[6], @t[3]
479 veor @y[4], @y[4], @t[3]
480 veor @y[7], @y[7], @t[4]
481 vext.8 @t[3], @t[3], @t[3], #12
482 veor @y[5], @y[5], @t[4]
483 veor @y[7], @y[7], @t[7]
484 veor @t[7], @t[7], @t[5] @ clobber t[7] even more
485 veor @y[3], @y[3], @t[5]
486 veor @y[4], @y[4], @t[4]
488 veor @y[5], @y[5], @t[7]
489 vext.8 @t[4], @t[4], @t[4], #12
490 veor @y[6], @y[6], @t[7]
491 veor @y[4], @y[4], @t[7]
493 veor @t[7], @t[7], @t[5]
494 vext.8 @t[5], @t[5], @t[5], #12
496 @ multiplication by 0x0d
497 veor @y[4], @y[4], @y[7]
498 veor @t[7], @t[7], @t[6] @ restore t[7]
499 veor @y[7], @y[7], @t[4]
500 vext.8 @t[6], @t[6], @t[6], #12
501 veor @y[2], @y[2], @t[0]
502 veor @y[7], @y[7], @t[5]
503 vext.8 @t[7], @t[7], @t[7], #12
504 veor @y[2], @y[2], @t[2]
506 veor @y[3], @y[3], @y[1]
507 veor @y[1], @y[1], @t[1]
508 veor @y[0], @y[0], @t[0]
509 veor @y[3], @y[3], @t[0]
510 veor @y[1], @y[1], @t[5]
511 veor @y[0], @y[0], @t[5]
512 vext.8 @t[0], @t[0], @t[0], #12
513 veor @y[1], @y[1], @t[7]
514 veor @y[0], @y[0], @t[6]
515 veor @y[3], @y[3], @y[1]
516 veor @y[4], @y[4], @t[1]
517 vext.8 @t[1], @t[1], @t[1], #12
519 veor @y[7], @y[7], @t[7]
520 veor @y[4], @y[4], @t[2]
521 veor @y[5], @y[5], @t[2]
522 veor @y[2], @y[2], @t[6]
523 veor @t[6], @t[6], @t[3] @ clobber t[6]
524 vext.8 @t[2], @t[2], @t[2], #12
525 veor @y[4], @y[4], @y[7]
526 veor @y[3], @y[3], @t[6]
528 veor @y[6], @y[6], @t[6]
529 veor @y[5], @y[5], @t[5]
530 vext.8 @t[5], @t[5], @t[5], #12
531 veor @y[6], @y[6], @t[4]
532 vext.8 @t[4], @t[4], @t[4], #12
533 veor @y[5], @y[5], @t[6]
534 veor @y[6], @y[6], @t[7]
535 vext.8 @t[7], @t[7], @t[7], #12
536 veor @t[6], @t[6], @t[3] @ restore t[6]
537 vext.8 @t[3], @t[3], @t[3], #12
539 @ multiplication by 0x09
540 veor @y[4], @y[4], @y[1]
541 veor @t[1], @t[1], @y[1] @ t[1]=y[1]
542 veor @t[0], @t[0], @t[5] @ clobber t[0]
543 vext.8 @t[6], @t[6], @t[6], #12
544 veor @t[1], @t[1], @t[5]
545 veor @y[3], @y[3], @t[0]
546 veor @t[0], @t[0], @y[0] @ t[0]=y[0]
547 veor @t[1], @t[1], @t[6]
548 veor @t[6], @t[6], @t[7] @ clobber t[6]
549 veor @y[4], @y[4], @t[1]
550 veor @y[7], @y[7], @t[4]
551 veor @y[6], @y[6], @t[3]
552 veor @y[5], @y[5], @t[2]
553 veor @t[4], @t[4], @y[4] @ t[4]=y[4]
554 veor @t[3], @t[3], @y[3] @ t[3]=y[3]
555 veor @t[5], @t[5], @y[5] @ t[5]=y[5]
556 veor @t[2], @t[2], @y[2] @ t[2]=y[2]
557 veor @t[3], @t[3], @t[7]
558 veor @XMM[5], @t[5], @t[6]
559 veor @XMM[6], @t[6], @y[6] @ t[6]=y[6]
560 veor @XMM[2], @t[2], @t[6]
561 veor @XMM[7], @t[7], @y[7] @ t[7]=y[7]
565 @ vmov @XMM[2], @t[2]
568 @ vmov @XMM[5], @t[5]
569 @ vmov @XMM[6], @t[6]
570 @ vmov @XMM[7], @t[7]
575 my ($a,$b,$n,$mask,$t)=@_;
586 my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
588 vshr.u64 $t0, $b0, #$n
589 vshr.u64 $t1, $b1, #$n
595 vshl.u64 $t0, $t0, #$n
597 vshl.u64 $t1, $t1, #$n
604 my @x=reverse(@_[0..7]);
605 my ($t0,$t1,$t2,$t3)=@_[8..11];
607 vmov.i8 $t0,#0x55 @ compose .LBS0
608 vmov.i8 $t1,#0x33 @ compose .LBS1
610 &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
611 &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
613 vmov.i8 $t0,#0x0f @ compose .LBS2
615 &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
616 &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
618 &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
619 &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
623 #include "arm_arch.h"
630 .type _bsaes_decrypt8,%function
633 sub $const,pc,#8 @ _bsaes_decrypt8
634 vldmia $key!, {@XMM[9]} @ round 0 key
635 add $const,$const,#.LM0ISR-_bsaes_decrypt8
637 vldmia $const!, {@XMM[8]} @ .LM0ISR
638 veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key
639 veor @XMM[11], @XMM[1], @XMM[9]
640 vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
641 vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
642 veor @XMM[12], @XMM[2], @XMM[9]
643 vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
644 vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
645 veor @XMM[13], @XMM[3], @XMM[9]
646 vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
647 vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
648 veor @XMM[14], @XMM[4], @XMM[9]
649 vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
650 vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
651 veor @XMM[15], @XMM[5], @XMM[9]
652 vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
653 vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
654 veor @XMM[10], @XMM[6], @XMM[9]
655 vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
656 vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
657 veor @XMM[11], @XMM[7], @XMM[9]
658 vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
659 vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
660 vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
661 vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
663 &bitslice (@XMM[0..7, 8..11]);
665 sub $rounds,$rounds,#1
670 &ShiftRows (@XMM[0..7, 8..12]);
671 $code.=".Ldec_sbox:\n";
672 &InvSbox (@XMM[0..7, 8..15]);
674 subs $rounds,$rounds,#1
677 &InvMixColumns (@XMM[0,1,6,4,2,7,3,5, 8..15]);
679 vldmia $const, {@XMM[12]} @ .LISR
680 addeq $const,$const,#0x10
682 vldmia $const, {@XMM[12]} @ .LISRM0
687 &bitslice (@XMM[0,1,6,4,2,7,3,5, 8..11]);
689 vldmia $key, {@XMM[8]} @ last round key
690 veor @XMM[6], @XMM[6], @XMM[8]
691 veor @XMM[4], @XMM[4], @XMM[8]
692 veor @XMM[2], @XMM[2], @XMM[8]
693 veor @XMM[7], @XMM[7], @XMM[8]
694 veor @XMM[3], @XMM[3], @XMM[8]
695 veor @XMM[5], @XMM[5], @XMM[8]
696 veor @XMM[0], @XMM[0], @XMM[8]
697 veor @XMM[1], @XMM[1], @XMM[8]
699 .size _bsaes_decrypt8,.-_bsaes_decrypt8
701 .type _bsaes_const,%object
704 .LM0ISR: @ InvShiftRows constants
705 .quad 0x0a0e0206070b0f03, 0x0004080c0d010509
707 .quad 0x0504070602010003, 0x0f0e0d0c080b0a09
709 .quad 0x01040b0e0205080f, 0x0306090c00070a0d
710 .LM0SR: @ ShiftRows constants
711 .quad 0x0a0e02060f03070b, 0x0004080c05090d01
713 .quad 0x0504070600030201, 0x0f0e0d0c0a09080b
715 .quad 0x0304090e00050a0f, 0x01060b0c0207080d
717 .quad 0x02060a0e03070b0f, 0x0004080c0105090d
719 .quad 0x090d01050c000408, 0x03070b0f060a0e02
722 .asciz "Bit-sliced AES for NEON, CRYPTOGAMS by <appro\@openssl.org>"
724 .size _bsaes_const,.-_bsaes_const
726 .type _bsaes_encrypt8,%function
729 sub $const,pc,#8 @ _bsaes_encrypt8
730 vldmia $key!, {@XMM[9]} @ round 0 key
731 sub $const,$const,#_bsaes_encrypt8-.LM0SR
733 vldmia $const!, {@XMM[8]} @ .LM0SR
735 veor @XMM[10], @XMM[0], @XMM[9] @ xor with round0 key
736 veor @XMM[11], @XMM[1], @XMM[9]
737 vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
738 vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
739 veor @XMM[12], @XMM[2], @XMM[9]
740 vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
741 vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
742 veor @XMM[13], @XMM[3], @XMM[9]
743 vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
744 vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
745 veor @XMM[14], @XMM[4], @XMM[9]
746 vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
747 vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
748 veor @XMM[15], @XMM[5], @XMM[9]
749 vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
750 vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
751 veor @XMM[10], @XMM[6], @XMM[9]
752 vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
753 vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
754 veor @XMM[11], @XMM[7], @XMM[9]
755 vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
756 vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
757 vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
758 vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
759 _bsaes_encrypt8_bitslice:
761 &bitslice (@XMM[0..7, 8..11]);
763 sub $rounds,$rounds,#1
768 &ShiftRows (@XMM[0..7, 8..12]);
769 $code.=".Lenc_sbox:\n";
770 &Sbox (@XMM[0..7, 8..15]);
772 subs $rounds,$rounds,#1
775 &MixColumns (@XMM[0,1,4,6,3,7,2,5, 8..15]);
777 vldmia $const, {@XMM[12]} @ .LSR
778 addeq $const,$const,#0x10
780 vldmia $const, {@XMM[12]} @ .LSRM0
785 # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
786 &bitslice (@XMM[0,1,4,6,3,7,2,5, 8..11]);
788 vldmia $key, {@XMM[8]} @ last round key
789 veor @XMM[4], @XMM[4], @XMM[8]
790 veor @XMM[6], @XMM[6], @XMM[8]
791 veor @XMM[3], @XMM[3], @XMM[8]
792 veor @XMM[7], @XMM[7], @XMM[8]
793 veor @XMM[2], @XMM[2], @XMM[8]
794 veor @XMM[5], @XMM[5], @XMM[8]
795 veor @XMM[0], @XMM[0], @XMM[8]
796 veor @XMM[1], @XMM[1], @XMM[8]
798 .size _bsaes_encrypt8,.-_bsaes_encrypt8
802 my ($out,$inp,$rounds,$const)=("r12","r4","r5","r6");
805 my @x=reverse(@_[0..7]);
806 my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
808 &swapmove (@x[0,1],1,$bs0,$t2,$t3);
810 @ &swapmove(@x[2,3],1,$t0,$t2,$t3);
814 #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
816 &swapmove2x (@x[0,2,1,3],2,$bs1,$t2,$t3);
818 @ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
824 &swapmove2x (@x[0,4,1,5],4,$bs2,$t2,$t3);
825 &swapmove2x (@x[2,6,3,7],4,$bs2,$t2,$t3);
829 .type _bsaes_key_convert,%function
832 sub $const,pc,#8 @ _bsaes_key_convert
833 vld1.8 {@XMM[7]}, [$inp]! @ load round 0 key
834 sub $const,$const,#_bsaes_key_convert-.LM0
835 vld1.8 {@XMM[15]}, [$inp]! @ load round 1 key
837 vmov.i8 @XMM[8], #0x01 @ bit masks
838 vmov.i8 @XMM[9], #0x02
839 vmov.i8 @XMM[10], #0x04
840 vmov.i8 @XMM[11], #0x08
841 vmov.i8 @XMM[12], #0x10
842 vmov.i8 @XMM[13], #0x20
843 vldmia $const, {@XMM[14]} @ .LM0
846 vrev32.8 @XMM[7], @XMM[7]
847 vrev32.8 @XMM[15], @XMM[15]
849 sub $rounds,$rounds,#1
850 vstmia $out!, {@XMM[7]} @ save round 0 key
855 vtbl.8 `&Dlo(@XMM[7])`,{@XMM[15]},`&Dlo(@XMM[14])`
856 vtbl.8 `&Dhi(@XMM[7])`,{@XMM[15]},`&Dhi(@XMM[14])`
857 vmov.i8 @XMM[6], #0x40
858 vmov.i8 @XMM[15], #0x80
860 vtst.8 @XMM[0], @XMM[7], @XMM[8]
861 vtst.8 @XMM[1], @XMM[7], @XMM[9]
862 vtst.8 @XMM[2], @XMM[7], @XMM[10]
863 vtst.8 @XMM[3], @XMM[7], @XMM[11]
864 vtst.8 @XMM[4], @XMM[7], @XMM[12]
865 vtst.8 @XMM[5], @XMM[7], @XMM[13]
866 vtst.8 @XMM[6], @XMM[7], @XMM[6]
867 vtst.8 @XMM[7], @XMM[7], @XMM[15]
868 vld1.8 {@XMM[15]}, [$inp]! @ load next round key
869 vmvn @XMM[0], @XMM[0] @ "pnot"
870 vmvn @XMM[1], @XMM[1]
871 vmvn @XMM[5], @XMM[5]
872 vmvn @XMM[6], @XMM[6]
874 vrev32.8 @XMM[15], @XMM[15]
876 subs $rounds,$rounds,#1
877 vstmia $out!,{@XMM[0]-@XMM[7]} @ write bit-sliced round key
880 vmov.i8 @XMM[7],#0x63 @ compose .L63
881 @ don't save last round key
883 .size _bsaes_key_convert,.-_bsaes_key_convert
887 if (0) { # following four functions are unsupported interface
888 # used for benchmarking...
890 .globl bsaes_enc_key_convert
891 .type bsaes_enc_key_convert,%function
893 bsaes_enc_key_convert:
895 vstmdb sp!,{d8-d15} @ ABI specification says so
897 ldr r5,[$inp,#240] @ pass rounds
898 mov r4,$inp @ pass key
899 mov r12,$out @ pass key schedule
900 bl _bsaes_key_convert
901 veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key
902 vstmia r12, {@XMM[7]} @ save last round key
906 .size bsaes_enc_key_convert,.-bsaes_enc_key_convert
908 .globl bsaes_encrypt_128
909 .type bsaes_encrypt_128,%function
913 vstmdb sp!,{d8-d15} @ ABI specification says so
915 vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input
916 vld1.8 {@XMM[2]-@XMM[3]}, [$inp]!
917 mov r4,$key @ pass the key
918 vld1.8 {@XMM[4]-@XMM[5]}, [$inp]!
919 mov r5,#10 @ pass rounds
920 vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
924 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
925 vst1.8 {@XMM[4]}, [$out]!
926 vst1.8 {@XMM[6]}, [$out]!
927 vst1.8 {@XMM[3]}, [$out]!
928 vst1.8 {@XMM[7]}, [$out]!
929 vst1.8 {@XMM[2]}, [$out]!
931 vst1.8 {@XMM[5]}, [$out]!
936 .size bsaes_encrypt_128,.-bsaes_encrypt_128
938 .globl bsaes_dec_key_convert
939 .type bsaes_dec_key_convert,%function
941 bsaes_dec_key_convert:
943 vstmdb sp!,{d8-d15} @ ABI specification says so
945 ldr r5,[$inp,#240] @ pass rounds
946 mov r4,$inp @ pass key
947 mov r12,$out @ pass key schedule
948 bl _bsaes_key_convert
949 vldmia $out, {@XMM[6]}
950 vstmia r12, {@XMM[15]} @ save last round key
951 veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
952 vstmia $out, {@XMM[7]}
956 .size bsaes_dec_key_convert,.-bsaes_dec_key_convert
958 .globl bsaes_decrypt_128
959 .type bsaes_decrypt_128,%function
963 vstmdb sp!,{d8-d15} @ ABI specification says so
965 vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input
966 vld1.8 {@XMM[2]-@XMM[3]}, [$inp]!
967 mov r4,$key @ pass the key
968 vld1.8 {@XMM[4]-@XMM[5]}, [$inp]!
969 mov r5,#10 @ pass rounds
970 vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
974 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
975 vst1.8 {@XMM[6]}, [$out]!
976 vst1.8 {@XMM[4]}, [$out]!
977 vst1.8 {@XMM[2]}, [$out]!
978 vst1.8 {@XMM[7]}, [$out]!
979 vst1.8 {@XMM[3]}, [$out]!
981 vst1.8 {@XMM[5]}, [$out]!
986 .size bsaes_decrypt_128,.-bsaes_decrypt_128
990 my ($inp,$out,$len,$key, $ivp,$fp,$rounds)=map("r$_",(0..3,8..10));
991 my ($keysched)=("sp");
994 .extern AES_cbc_encrypt
997 .global bsaes_cbc_encrypt
998 .type bsaes_cbc_encrypt,%function
1004 @ it is up to the caller to make sure we are called with enc == 0
1006 stmdb sp!, {r4-r10, lr}
1007 vstmdb sp!, {d8-d15} @ ABI specification says so
1008 ldr $ivp, [sp, #0x60] @ IV is 1st arg on the stack
1009 mov $len, $len, lsr#4 @ len in 16 byte blocks
1010 sub sp, #0x10 @ scratch space to carry over the IV
1011 mov $fp, sp @ save sp
1013 @ allocate the key schedule on the stack
1014 ldr $rounds, [$key, #240] @ get # of rounds
1015 sub sp, sp, $rounds, lsl#7 @ 128 bytes per inner round key
1016 add sp, sp, #`128-32` @ size of bit-sliced key schedule
1018 @ populate the key schedule
1019 mov r4, $key @ pass key
1020 mov r5, $rounds @ pass # of rounds
1021 mov r12, $keysched @ pass key schedule
1022 bl _bsaes_key_convert
1023 vldmia $keysched, {@XMM[6]}
1024 vstmia r12, {@XMM[15]} @ save last round key
1025 veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
1026 vstmia $keysched, {@XMM[7]}
1028 vld1.8 {@XMM[15]}, [$ivp] @ load IV
1033 subs $len, $len, #0x8
1034 bmi .Lcbc_dec_loop_finish
1036 vld1.8 {@XMM[0]-@XMM[1]}, [$inp]! @ load input
1037 vld1.8 {@XMM[2]-@XMM[3]}, [$inp]!
1038 mov r4, $keysched @ pass the key
1039 vld1.8 {@XMM[4]-@XMM[5]}, [$inp]!
1041 vld1.8 {@XMM[6]-@XMM[7]}, [$inp]
1042 sub $inp, $inp, #0x60
1043 vstmia $fp, {@XMM[15]} @ put aside IV
1047 vldmia $fp, {@XMM[14]} @ reload IV
1048 vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
1049 veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
1050 vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
1051 veor @XMM[1], @XMM[1], @XMM[8]
1052 veor @XMM[6], @XMM[6], @XMM[9]
1053 vld1.8 {@XMM[12]-@XMM[13]}, [$inp]!
1054 veor @XMM[4], @XMM[4], @XMM[10]
1055 veor @XMM[2], @XMM[2], @XMM[11]
1056 vld1.8 {@XMM[14]-@XMM[15]}, [$inp]!
1057 veor @XMM[7], @XMM[7], @XMM[12]
1058 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
1059 veor @XMM[3], @XMM[3], @XMM[13]
1060 vst1.8 {@XMM[6]}, [$out]!
1061 veor @XMM[5], @XMM[5], @XMM[14]
1062 vst1.8 {@XMM[4]}, [$out]!
1063 vst1.8 {@XMM[2]}, [$out]!
1064 vst1.8 {@XMM[7]}, [$out]!
1065 vst1.8 {@XMM[3]}, [$out]!
1066 vst1.8 {@XMM[5]}, [$out]!
1070 .Lcbc_dec_loop_finish:
1074 vld1.8 {@XMM[0]}, [$inp]! @ load input
1077 vld1.8 {@XMM[1]}, [$inp]!
1078 mov r4, $keysched @ pass the key
1080 vstmia $fp, {@XMM[15]} @ put aside IV
1082 vld1.8 {@XMM[2]}, [$inp]!
1085 vld1.8 {@XMM[3]}, [$inp]!
1087 vld1.8 {@XMM[4]}, [$inp]!
1090 vld1.8 {@XMM[5]}, [$inp]!
1092 vld1.8 {@XMM[6]}, [$inp]!
1093 sub $inp, $inp, #0x70
1097 vldmia $fp, {@XMM[14]} @ reload IV
1098 vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
1099 veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
1100 vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
1101 veor @XMM[1], @XMM[1], @XMM[8]
1102 veor @XMM[6], @XMM[6], @XMM[9]
1103 vld1.8 {@XMM[12]-@XMM[13]}, [$inp]!
1104 veor @XMM[4], @XMM[4], @XMM[10]
1105 veor @XMM[2], @XMM[2], @XMM[11]
1106 vld1.8 {@XMM[15]}, [$inp]!
1107 veor @XMM[7], @XMM[7], @XMM[12]
1108 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
1109 veor @XMM[3], @XMM[3], @XMM[13]
1110 vst1.8 {@XMM[6]}, [$out]!
1111 vst1.8 {@XMM[4]}, [$out]!
1112 vst1.8 {@XMM[2]}, [$out]!
1113 vst1.8 {@XMM[7]}, [$out]!
1114 vst1.8 {@XMM[3]}, [$out]!
1118 sub $inp, $inp, #0x60
1120 vldmia $fp,{@XMM[14]} @ reload IV
1121 vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
1122 veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
1123 vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
1124 veor @XMM[1], @XMM[1], @XMM[8]
1125 veor @XMM[6], @XMM[6], @XMM[9]
1126 vld1.8 {@XMM[12]}, [$inp]!
1127 veor @XMM[4], @XMM[4], @XMM[10]
1128 veor @XMM[2], @XMM[2], @XMM[11]
1129 vld1.8 {@XMM[15]}, [$inp]!
1130 veor @XMM[7], @XMM[7], @XMM[12]
1131 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
1132 vst1.8 {@XMM[6]}, [$out]!
1133 vst1.8 {@XMM[4]}, [$out]!
1134 vst1.8 {@XMM[2]}, [$out]!
1135 vst1.8 {@XMM[7]}, [$out]!
1139 sub $inp, $inp, #0x50
1141 vldmia $fp, {@XMM[14]} @ reload IV
1142 vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
1143 veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
1144 vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
1145 veor @XMM[1], @XMM[1], @XMM[8]
1146 veor @XMM[6], @XMM[6], @XMM[9]
1147 vld1.8 {@XMM[15]}, [$inp]!
1148 veor @XMM[4], @XMM[4], @XMM[10]
1149 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
1150 veor @XMM[2], @XMM[2], @XMM[11]
1151 vst1.8 {@XMM[6]}, [$out]!
1152 vst1.8 {@XMM[4]}, [$out]!
1153 vst1.8 {@XMM[2]}, [$out]!
1157 sub $inp, $inp, #0x40
1159 vldmia $fp, {@XMM[14]} @ reload IV
1160 vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
1161 veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
1162 vld1.8 {@XMM[10]}, [$inp]!
1163 veor @XMM[1], @XMM[1], @XMM[8]
1164 veor @XMM[6], @XMM[6], @XMM[9]
1165 vld1.8 {@XMM[15]}, [$inp]!
1166 veor @XMM[4], @XMM[4], @XMM[10]
1167 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
1168 vst1.8 {@XMM[6]}, [$out]!
1169 vst1.8 {@XMM[4]}, [$out]!
1173 sub $inp, $inp, #0x30
1175 vldmia $fp, {@XMM[14]} @ reload IV
1176 vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ reload input
1177 veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
1178 vld1.8 {@XMM[15]}, [$inp]!
1179 veor @XMM[1], @XMM[1], @XMM[8]
1180 veor @XMM[6], @XMM[6], @XMM[9]
1181 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
1182 vst1.8 {@XMM[6]}, [$out]!
1186 sub $inp, $inp, #0x20
1188 vldmia $fp, {@XMM[14]} @ reload IV
1189 vld1.8 {@XMM[8]}, [$inp]! @ reload input
1190 veor @XMM[0], @XMM[0], @XMM[14] @ ^= IV
1191 vld1.8 {@XMM[15]}, [$inp]! @ reload input
1192 veor @XMM[1], @XMM[1], @XMM[8]
1193 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
1197 sub $inp, $inp, #0x10
1198 mov $rounds, $out @ save original out pointer
1199 mov $out, $fp @ use the iv scratch space as out buffer
1201 vmov @XMM[4],@XMM[15] @ just in case ensure that IV
1202 vmov @XMM[5],@XMM[0] @ and input are preserved
1204 vld1.8 {@XMM[0]}, [$fp,:64] @ load result
1205 veor @XMM[0], @XMM[0], @XMM[4] @ ^= IV
1206 vmov @XMM[15], @XMM[5] @ @XMM[5] holds input
1207 vst1.8 {@XMM[0]}, [$rounds] @ write output
1212 .Lcbc_dec_bzero: @ wipe key schedule [if any]
1213 vstmia $keysched!, {q0-q1}
1218 vst1.8 {@XMM[15]}, [$ivp] @ return IV
1219 vldmia sp!, {d8-d15}
1220 ldmia sp!, {r4-r10, pc}
1221 .size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
1225 my ($inp,$out,$len,$key, $ctr,$fp,$rounds)=(map("r$_",(0..3,8..10)));
1226 my $const = "r6"; # shared with _bsaes_encrypt8_alt
1227 my $keysched = "sp";
1231 .global bsaes_ctr32_encrypt_blocks
1232 .type bsaes_ctr32_encrypt_blocks,%function
1234 bsaes_ctr32_encrypt_blocks:
1235 cmp $len, #8 @ use plain AES for
1236 blo .Lctr_enc_short @ small sizes
1238 stmdb sp!, {r4-r10, lr}
1239 vstmdb sp!, {d8-d15} @ ABI specification says so
1240 ldr $ctr, [sp, #0x60] @ ctr is 1st arg on the stack
1241 sub sp, sp, #0x10 @ scratch space to carry over the ctr
1242 mov $fp, sp @ save sp
1244 @ allocate the key schedule on the stack
1245 ldr $rounds, [$key, #240] @ get # of rounds
1246 sub sp, sp, $rounds, lsl#7 @ 128 bytes per inner round key
1247 add sp, sp, #`128-32` @ size of bit-sliced key schedule
1249 @ populate the key schedule
1250 mov r4, $key @ pass key
1251 mov r5, $rounds @ pass # of rounds
1252 mov r12, $keysched @ pass key schedule
1253 bl _bsaes_key_convert
1254 veor @XMM[7],@XMM[7],@XMM[15] @ fix up last round key
1255 vstmia r12, {@XMM[7]} @ save last round key
1257 vld1.8 {@XMM[0]}, [$ctr] @ load counter
1258 add $ctr, $const, #.LREVM0SR-.LM0 @ borrow $ctr
1259 vldmia $keysched, {@XMM[4]} @ load round0 key
1261 vmov.i32 @XMM[8],#1 @ compose 1<<96
1262 veor @XMM[9],@XMM[9],@XMM[9]
1263 vrev32.8 @XMM[0],@XMM[0]
1264 vext.8 @XMM[8],@XMM[9],@XMM[8],#4
1265 vrev32.8 @XMM[4],@XMM[4]
1266 vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96
1267 vstmia $keysched, {@XMM[4]} @ save adjusted round0 key
1272 vadd.u32 @XMM[10], @XMM[8], @XMM[9] @ compose 3<<96
1273 vadd.u32 @XMM[1], @XMM[0], @XMM[8] @ +1
1274 vadd.u32 @XMM[2], @XMM[0], @XMM[9] @ +2
1275 vadd.u32 @XMM[3], @XMM[0], @XMM[10] @ +3
1276 vadd.u32 @XMM[4], @XMM[1], @XMM[10]
1277 vadd.u32 @XMM[5], @XMM[2], @XMM[10]
1278 vadd.u32 @XMM[6], @XMM[3], @XMM[10]
1279 vadd.u32 @XMM[7], @XMM[4], @XMM[10]
1280 vadd.u32 @XMM[10], @XMM[5], @XMM[10] @ next counter
1282 @ Borrow prologue from _bsaes_encrypt8 to use the opportunity
1283 @ to flip byte order in 32-bit counter
1285 vldmia $keysched, {@XMM[9]} @ load round0 key
1286 add r4, $keysched, #0x10 @ pass next round key
1287 vldmia $ctr, {@XMM[8]} @ .LREVM0SR
1288 mov r5, $rounds @ pass rounds
1289 vstmia $fp, {@XMM[10]} @ save next counter
1290 sub $const, $ctr, #.LREVM0SR-.LSR @ pass constants
1292 bl _bsaes_encrypt8_alt
1295 blo .Lctr_enc_loop_done
1297 vld1.8 {@XMM[8]-@XMM[9]}, [$inp]! @ load input
1298 vld1.8 {@XMM[10]-@XMM[11]}, [$inp]!
1299 veor @XMM[0], @XMM[8]
1300 veor @XMM[1], @XMM[9]
1301 vld1.8 {@XMM[12]-@XMM[13]}, [$inp]!
1302 veor @XMM[4], @XMM[10]
1303 veor @XMM[6], @XMM[11]
1304 vld1.8 {@XMM[14]-@XMM[15]}, [$inp]!
1305 veor @XMM[3], @XMM[12]
1306 vst1.8 {@XMM[0]-@XMM[1]}, [$out]! @ write output
1307 veor @XMM[7], @XMM[13]
1308 veor @XMM[2], @XMM[14]
1309 vst1.8 {@XMM[4]}, [$out]!
1310 veor @XMM[5], @XMM[15]
1311 vst1.8 {@XMM[6]}, [$out]!
1312 vmov.i32 @XMM[8], #1 @ compose 1<<96
1313 vst1.8 {@XMM[3]}, [$out]!
1314 veor @XMM[9], @XMM[9], @XMM[9]
1315 vst1.8 {@XMM[7]}, [$out]!
1316 vext.8 @XMM[8], @XMM[9], @XMM[8], #4
1317 vst1.8 {@XMM[2]}, [$out]!
1318 vadd.u32 @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96
1319 vst1.8 {@XMM[5]}, [$out]!
1320 vldmia $fp, {@XMM[0]} @ load counter
1326 .Lctr_enc_loop_done:
1328 vld1.8 {@XMM[8]}, [$inp]! @ load input
1329 veor @XMM[0], @XMM[8]
1330 vst1.8 {@XMM[0]}, [$out]! @ write output
1333 vld1.8 {@XMM[9]}, [$inp]!
1334 veor @XMM[1], @XMM[9]
1335 vst1.8 {@XMM[1]}, [$out]!
1337 vld1.8 {@XMM[10]}, [$inp]!
1338 veor @XMM[4], @XMM[10]
1339 vst1.8 {@XMM[4]}, [$out]!
1342 vld1.8 {@XMM[11]}, [$inp]!
1343 veor @XMM[6], @XMM[11]
1344 vst1.8 {@XMM[6]}, [$out]!
1346 vld1.8 {@XMM[12]}, [$inp]!
1347 veor @XMM[3], @XMM[12]
1348 vst1.8 {@XMM[3]}, [$out]!
1351 vld1.8 {@XMM[13]}, [$inp]!
1352 veor @XMM[7], @XMM[13]
1353 vst1.8 {@XMM[7]}, [$out]!
1355 vld1.8 {@XMM[14]}, [$inp]
1356 veor @XMM[2], @XMM[14]
1357 vst1.8 {@XMM[2]}, [$out]!
1362 .Lctr_enc_bzero: @ wipe key schedule [if any]
1363 vstmia $keysched!, {q0-q1}
1368 vldmia sp!, {d8-d15}
1369 ldmia sp!, {r4-r10, pc} @ return
1373 ldr ip, [sp] @ ctr pointer is passed on stack
1374 stmdb sp!, {r4-r8, lr}
1376 mov r4, $inp @ copy arguments
1380 ldr r8, [ip, #12] @ load counter LSW
1381 vld1.8 {@XMM[1]}, [ip] @ load whole counter value
1386 vst1.8 {@XMM[1]}, [sp,:64] @ copy counter value
1389 .Lctr_enc_short_loop:
1390 add r0, sp, #0x10 @ input counter value
1391 mov r1, sp @ output on the stack
1396 vld1.8 {@XMM[0]}, [r4]! @ load input
1397 vld1.8 {@XMM[1]}, [sp,:64] @ load encrypted counter
1401 str r0, [sp, #0x1c] @ next counter value
1403 str r8, [sp, #0x1c] @ next counter value
1405 veor @XMM[0],@XMM[0],@XMM[1]
1406 vst1.8 {@XMM[0]}, [r5]! @ store output
1408 bne .Lctr_enc_short_loop
1411 ldmia sp!, {r4-r8, pc}
1412 .size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
1416 ######################################################################
1417 # void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len,
1418 # const AES_KEY *key1, const AES_KEY *key2,
1419 # const unsigned char iv[16]);
1421 my ($inp,$out,$len,$key,$rounds,$magic,$fp)=(map("r$_",(7..10,1..3)));
1422 my $const="r6"; # returned by _bsaes_key_convert
1427 .globl bsaes_xts_encrypt
1428 .type bsaes_xts_encrypt,%function
1431 stmdb sp!, {r4-r10, lr} @ 0x20
1432 vstmdb sp!, {d8-d15} @ 0x40
1433 mov r6, sp @ future $fp
1434 sub sp, #0x10 @ 0x10
1440 bic sp, #0xf @ align at 16 bytes
1442 @ generate initial tweak
1443 ldr r0, [r6, #0x64] @ iv[]
1445 ldr r2, [r6, #0x60] @ key2
1448 @ allocate the key schedule on the stack
1449 ldr $rounds, [$key, #240] @ get # of rounds
1451 mov r0, sp @ pointer to initial tweak
1452 sub sp, sp, $rounds, lsl#7 @ 128 bytes per inner round key
1453 @ add sp, sp, #`128-32` @ size of bit-sliced key schedule
1454 sub sp, sp, #`32+16` @ place for tweak[9]
1456 @ populate the key schedule
1457 mov r4, $key @ pass key
1458 mov r5, $rounds @ pass # of rounds
1459 add r12, sp, #0x90 @ pass key schedule
1460 bl _bsaes_key_convert
1461 veor @XMM[7], @XMM[7], @XMM[15] @ fix up last round key
1462 vstmia r12, {@XMM[7]} @ save last round key
1464 vld1.8 {@XMM[8]}, [r0] @ initial tweak
1465 add $magic, $const, #.Lxts_magic-.LM0
1473 vldmia $magic, {$twmask} @ load XTS magic
1474 vshr.s64 @T[0], @XMM[8], #63
1476 vand @T[0], @T[0], $twmask
1478 for($i=9;$i<16;$i++) {
1480 vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
1481 vst1.64 {@XMM[$i-1]}, [r0,:128]!
1482 vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
1483 vshr.s64 @T[1], @XMM[$i], #63
1484 veor @XMM[$i], @XMM[$i], @T[0]
1485 vand @T[1], @T[1], $twmask
1489 $code.=<<___ if ($i>=10);
1490 vld1.8 {@XMM[$i-10]}, [$inp]!
1492 $code.=<<___ if ($i>=11);
1493 veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
1497 vadd.u64 @XMM[8], @XMM[15], @XMM[15]
1498 vst1.64 {@XMM[15]}, [r0,:128]!
1499 vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
1500 veor @XMM[8], @XMM[8], @T[0]
1501 vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1503 vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
1504 veor @XMM[5], @XMM[5], @XMM[13]
1505 add r4, sp, #0x90 @ pass key schedule
1506 veor @XMM[6], @XMM[6], @XMM[14]
1507 mov r5, $rounds @ pass rounds
1508 veor @XMM[7], @XMM[7], @XMM[15]
1513 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1514 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
1515 veor @XMM[0], @XMM[0], @XMM[ 8]
1516 vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
1517 veor @XMM[1], @XMM[1], @XMM[ 9]
1518 veor @XMM[8], @XMM[4], @XMM[10]
1519 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1520 veor @XMM[9], @XMM[6], @XMM[11]
1521 vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]!
1522 veor @XMM[10], @XMM[3], @XMM[12]
1523 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
1524 veor @XMM[11], @XMM[7], @XMM[13]
1525 veor @XMM[12], @XMM[2], @XMM[14]
1526 vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
1527 veor @XMM[13], @XMM[5], @XMM[15]
1528 vst1.8 {@XMM[12]-@XMM[13]}, [$out]!
1530 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1539 vldmia $magic, {$twmask} @ load XTS magic
1540 vshr.s64 @T[0], @XMM[8], #63
1542 vand @T[0], @T[0], $twmask
1544 for($i=9;$i<16;$i++) {
1546 vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
1547 vst1.64 {@XMM[$i-1]}, [r0,:128]!
1548 vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
1549 vshr.s64 @T[1], @XMM[$i], #63
1550 veor @XMM[$i], @XMM[$i], @T[0]
1551 vand @T[1], @T[1], $twmask
1555 $code.=<<___ if ($i>=10);
1556 vld1.8 {@XMM[$i-10]}, [$inp]!
1558 bmi .Lxts_enc_`$i-9`
1560 $code.=<<___ if ($i>=11);
1561 veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
1566 vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak
1568 vld1.8 {@XMM[6]}, [$inp]!
1569 veor @XMM[5], @XMM[5], @XMM[13]
1570 add r4, sp, #0x90 @ pass key schedule
1571 veor @XMM[6], @XMM[6], @XMM[14]
1572 mov r5, $rounds @ pass rounds
1577 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1578 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
1579 veor @XMM[0], @XMM[0], @XMM[ 8]
1580 vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
1581 veor @XMM[1], @XMM[1], @XMM[ 9]
1582 veor @XMM[8], @XMM[4], @XMM[10]
1583 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1584 veor @XMM[9], @XMM[6], @XMM[11]
1585 vld1.64 {@XMM[14]}, [r0,:128]!
1586 veor @XMM[10], @XMM[3], @XMM[12]
1587 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
1588 veor @XMM[11], @XMM[7], @XMM[13]
1589 veor @XMM[12], @XMM[2], @XMM[14]
1590 vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
1591 vst1.8 {@XMM[12]}, [$out]!
1593 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1597 vst1.64 {@XMM[14]}, [r0,:128] @ next round tweak
1599 veor @XMM[4], @XMM[4], @XMM[12]
1600 add r4, sp, #0x90 @ pass key schedule
1601 veor @XMM[5], @XMM[5], @XMM[13]
1602 mov r5, $rounds @ pass rounds
1607 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1608 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
1609 veor @XMM[0], @XMM[0], @XMM[ 8]
1610 vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
1611 veor @XMM[1], @XMM[1], @XMM[ 9]
1612 veor @XMM[8], @XMM[4], @XMM[10]
1613 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1614 veor @XMM[9], @XMM[6], @XMM[11]
1615 veor @XMM[10], @XMM[3], @XMM[12]
1616 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
1617 veor @XMM[11], @XMM[7], @XMM[13]
1618 vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
1620 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1624 vst1.64 {@XMM[13]}, [r0,:128] @ next round tweak
1626 veor @XMM[3], @XMM[3], @XMM[11]
1627 add r4, sp, #0x90 @ pass key schedule
1628 veor @XMM[4], @XMM[4], @XMM[12]
1629 mov r5, $rounds @ pass rounds
1634 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1635 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
1636 veor @XMM[0], @XMM[0], @XMM[ 8]
1637 vld1.64 {@XMM[12]}, [r0,:128]!
1638 veor @XMM[1], @XMM[1], @XMM[ 9]
1639 veor @XMM[8], @XMM[4], @XMM[10]
1640 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1641 veor @XMM[9], @XMM[6], @XMM[11]
1642 veor @XMM[10], @XMM[3], @XMM[12]
1643 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
1644 vst1.8 {@XMM[10]}, [$out]!
1646 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1650 vst1.64 {@XMM[12]}, [r0,:128] @ next round tweak
1652 veor @XMM[2], @XMM[2], @XMM[10]
1653 add r4, sp, #0x90 @ pass key schedule
1654 veor @XMM[3], @XMM[3], @XMM[11]
1655 mov r5, $rounds @ pass rounds
1660 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1661 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
1662 veor @XMM[0], @XMM[0], @XMM[ 8]
1663 veor @XMM[1], @XMM[1], @XMM[ 9]
1664 veor @XMM[8], @XMM[4], @XMM[10]
1665 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1666 veor @XMM[9], @XMM[6], @XMM[11]
1667 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
1669 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1673 vst1.64 {@XMM[11]}, [r0,:128] @ next round tweak
1675 veor @XMM[1], @XMM[1], @XMM[9]
1676 add r4, sp, #0x90 @ pass key schedule
1677 veor @XMM[2], @XMM[2], @XMM[10]
1678 mov r5, $rounds @ pass rounds
1683 vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
1684 vld1.64 {@XMM[10]}, [r0,:128]!
1685 veor @XMM[0], @XMM[0], @XMM[ 8]
1686 veor @XMM[1], @XMM[1], @XMM[ 9]
1687 veor @XMM[8], @XMM[4], @XMM[10]
1688 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1689 vst1.8 {@XMM[8]}, [$out]!
1691 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1695 vst1.64 {@XMM[10]}, [r0,:128] @ next round tweak
1697 veor @XMM[0], @XMM[0], @XMM[8]
1698 add r4, sp, #0x90 @ pass key schedule
1699 veor @XMM[1], @XMM[1], @XMM[9]
1700 mov r5, $rounds @ pass rounds
1705 vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
1706 veor @XMM[0], @XMM[0], @XMM[ 8]
1707 veor @XMM[1], @XMM[1], @XMM[ 9]
1708 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1710 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1715 veor @XMM[0], @XMM[8]
1717 vst1.8 {@XMM[0]}, [sp,:128]
1719 mov r4, $fp @ preserve fp
1723 vld1.8 {@XMM[0]}, [sp,:128]
1724 veor @XMM[0], @XMM[0], @XMM[8]
1725 vst1.8 {@XMM[0]}, [$out]!
1728 vmov @XMM[8], @XMM[9] @ next round tweak
1737 ldrb r1, [$out, #-0x10]
1738 strb r0, [$out, #-0x10]
1744 vld1.8 {@XMM[0]}, [r6]
1746 veor @XMM[0], @XMM[0], @XMM[8]
1748 vst1.8 {@XMM[0]}, [sp,:128]
1750 mov r4, $fp @ preserve fp
1754 vld1.8 {@XMM[0]}, [sp,:128]
1755 veor @XMM[0], @XMM[0], @XMM[8]
1756 vst1.8 {@XMM[0]}, [r6]
1763 .Lxts_enc_bzero: @ wipe key schedule [if any]
1769 vldmia sp!, {d8-d15}
1770 ldmia sp!, {r4-r10, pc} @ return
1772 .size bsaes_xts_encrypt,.-bsaes_xts_encrypt
1774 .globl bsaes_xts_decrypt
1775 .type bsaes_xts_decrypt,%function
1778 stmdb sp!, {r4-r10, lr} @ 0x20
1779 vstmdb sp!, {d8-d15} @ 0x40
1780 mov r6, sp @ future $fp
1781 sub sp, #0x10 @ 0x10
1787 bic sp, #0xf @ align at 16 bytes
1789 @ generate initial tweak
1790 ldr r0, [r6, #0x64] @ iv[]
1792 ldr r2, [r6, #0x60] @ key2
1795 @ allocate the key schedule on the stack
1796 ldr $rounds, [$key, #240] @ get # of rounds
1798 mov r0, sp @ pointer to initial tweak
1799 sub sp, sp, $rounds, lsl#7 @ 128 bytes per inner round key
1800 @ add sp, sp, #`128-32` @ size of bit-sliced key schedule
1801 sub sp, sp, #`32+16` @ place for tweak[9]
1803 @ populate the key schedule
1804 mov r4, $key @ pass key
1805 mov r5, $rounds @ pass # of rounds
1806 add r12, sp, #0x90 @ pass key schedule
1807 bl _bsaes_key_convert
1809 vldmia r4, {@XMM[6]}
1810 vstmia r12, {@XMM[15]} @ save last round key
1811 veor @XMM[7], @XMM[7], @XMM[6] @ fix up round 0 key
1812 vstmia r4, {@XMM[7]}
1814 vld1.8 {@XMM[8]}, [r0] @ initial tweak
1815 add $magic, $const, #.Lxts_magic-.LM0
1817 tst $len, #0xf @ if not multiple of 16
1818 subne $len, #0x10 @ subtract another 16 bytes
1826 vldmia $magic, {$twmask} @ load XTS magic
1827 vshr.s64 @T[0], @XMM[8], #63
1829 vand @T[0], @T[0], $twmask
1831 for($i=9;$i<16;$i++) {
1833 vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
1834 vst1.64 {@XMM[$i-1]}, [r0,:128]!
1835 vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
1836 vshr.s64 @T[1], @XMM[$i], #63
1837 veor @XMM[$i], @XMM[$i], @T[0]
1838 vand @T[1], @T[1], $twmask
1842 $code.=<<___ if ($i>=10);
1843 vld1.8 {@XMM[$i-10]}, [$inp]!
1845 $code.=<<___ if ($i>=11);
1846 veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
1850 vadd.u64 @XMM[8], @XMM[15], @XMM[15]
1851 vst1.64 {@XMM[15]}, [r0,:128]!
1852 vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
1853 veor @XMM[8], @XMM[8], @T[0]
1854 vst1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1856 vld1.8 {@XMM[6]-@XMM[7]}, [$inp]!
1857 veor @XMM[5], @XMM[5], @XMM[13]
1858 add r4, sp, #0x90 @ pass key schedule
1859 veor @XMM[6], @XMM[6], @XMM[14]
1860 mov r5, $rounds @ pass rounds
1861 veor @XMM[7], @XMM[7], @XMM[15]
1866 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1867 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
1868 veor @XMM[0], @XMM[0], @XMM[ 8]
1869 vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
1870 veor @XMM[1], @XMM[1], @XMM[ 9]
1871 veor @XMM[8], @XMM[6], @XMM[10]
1872 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1873 veor @XMM[9], @XMM[4], @XMM[11]
1874 vld1.64 {@XMM[14]-@XMM[15]}, [r0,:128]!
1875 veor @XMM[10], @XMM[2], @XMM[12]
1876 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
1877 veor @XMM[11], @XMM[7], @XMM[13]
1878 veor @XMM[12], @XMM[3], @XMM[14]
1879 vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
1880 veor @XMM[13], @XMM[5], @XMM[15]
1881 vst1.8 {@XMM[12]-@XMM[13]}, [$out]!
1883 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1892 vldmia $magic, {$twmask} @ load XTS magic
1893 vshr.s64 @T[0], @XMM[8], #63
1895 vand @T[0], @T[0], $twmask
1897 for($i=9;$i<16;$i++) {
1899 vadd.u64 @XMM[$i], @XMM[$i-1], @XMM[$i-1]
1900 vst1.64 {@XMM[$i-1]}, [r0,:128]!
1901 vswp `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
1902 vshr.s64 @T[1], @XMM[$i], #63
1903 veor @XMM[$i], @XMM[$i], @T[0]
1904 vand @T[1], @T[1], $twmask
1908 $code.=<<___ if ($i>=10);
1909 vld1.8 {@XMM[$i-10]}, [$inp]!
1911 bmi .Lxts_dec_`$i-9`
1913 $code.=<<___ if ($i>=11);
1914 veor @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
1919 vst1.64 {@XMM[15]}, [r0,:128] @ next round tweak
1921 vld1.8 {@XMM[6]}, [$inp]!
1922 veor @XMM[5], @XMM[5], @XMM[13]
1923 add r4, sp, #0x90 @ pass key schedule
1924 veor @XMM[6], @XMM[6], @XMM[14]
1925 mov r5, $rounds @ pass rounds
1930 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1931 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
1932 veor @XMM[0], @XMM[0], @XMM[ 8]
1933 vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
1934 veor @XMM[1], @XMM[1], @XMM[ 9]
1935 veor @XMM[8], @XMM[6], @XMM[10]
1936 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1937 veor @XMM[9], @XMM[4], @XMM[11]
1938 vld1.64 {@XMM[14]}, [r0,:128]!
1939 veor @XMM[10], @XMM[2], @XMM[12]
1940 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
1941 veor @XMM[11], @XMM[7], @XMM[13]
1942 veor @XMM[12], @XMM[3], @XMM[14]
1943 vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
1944 vst1.8 {@XMM[12]}, [$out]!
1946 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1950 vst1.64 {@XMM[14]}, [r0,:128] @ next round tweak
1952 veor @XMM[4], @XMM[4], @XMM[12]
1953 add r4, sp, #0x90 @ pass key schedule
1954 veor @XMM[5], @XMM[5], @XMM[13]
1955 mov r5, $rounds @ pass rounds
1960 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1961 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
1962 veor @XMM[0], @XMM[0], @XMM[ 8]
1963 vld1.64 {@XMM[12]-@XMM[13]}, [r0,:128]!
1964 veor @XMM[1], @XMM[1], @XMM[ 9]
1965 veor @XMM[8], @XMM[6], @XMM[10]
1966 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1967 veor @XMM[9], @XMM[4], @XMM[11]
1968 veor @XMM[10], @XMM[2], @XMM[12]
1969 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
1970 veor @XMM[11], @XMM[7], @XMM[13]
1971 vst1.8 {@XMM[10]-@XMM[11]}, [$out]!
1973 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
1977 vst1.64 {@XMM[13]}, [r0,:128] @ next round tweak
1979 veor @XMM[3], @XMM[3], @XMM[11]
1980 add r4, sp, #0x90 @ pass key schedule
1981 veor @XMM[4], @XMM[4], @XMM[12]
1982 mov r5, $rounds @ pass rounds
1987 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
1988 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
1989 veor @XMM[0], @XMM[0], @XMM[ 8]
1990 vld1.64 {@XMM[12]}, [r0,:128]!
1991 veor @XMM[1], @XMM[1], @XMM[ 9]
1992 veor @XMM[8], @XMM[6], @XMM[10]
1993 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
1994 veor @XMM[9], @XMM[4], @XMM[11]
1995 veor @XMM[10], @XMM[2], @XMM[12]
1996 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
1997 vst1.8 {@XMM[10]}, [$out]!
1999 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
2003 vst1.64 {@XMM[12]}, [r0,:128] @ next round tweak
2005 veor @XMM[2], @XMM[2], @XMM[10]
2006 add r4, sp, #0x90 @ pass key schedule
2007 veor @XMM[3], @XMM[3], @XMM[11]
2008 mov r5, $rounds @ pass rounds
2013 vld1.64 {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
2014 vld1.64 {@XMM[10]-@XMM[11]}, [r0,:128]!
2015 veor @XMM[0], @XMM[0], @XMM[ 8]
2016 veor @XMM[1], @XMM[1], @XMM[ 9]
2017 veor @XMM[8], @XMM[6], @XMM[10]
2018 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
2019 veor @XMM[9], @XMM[4], @XMM[11]
2020 vst1.8 {@XMM[8]-@XMM[9]}, [$out]!
2022 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
2026 vst1.64 {@XMM[11]}, [r0,:128] @ next round tweak
2028 veor @XMM[1], @XMM[1], @XMM[9]
2029 add r4, sp, #0x90 @ pass key schedule
2030 veor @XMM[2], @XMM[2], @XMM[10]
2031 mov r5, $rounds @ pass rounds
2036 vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
2037 vld1.64 {@XMM[10]}, [r0,:128]!
2038 veor @XMM[0], @XMM[0], @XMM[ 8]
2039 veor @XMM[1], @XMM[1], @XMM[ 9]
2040 veor @XMM[8], @XMM[6], @XMM[10]
2041 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
2042 vst1.8 {@XMM[8]}, [$out]!
2044 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
2048 vst1.64 {@XMM[10]}, [r0,:128] @ next round tweak
2050 veor @XMM[0], @XMM[0], @XMM[8]
2051 add r4, sp, #0x90 @ pass key schedule
2052 veor @XMM[1], @XMM[1], @XMM[9]
2053 mov r5, $rounds @ pass rounds
2058 vld1.64 {@XMM[8]-@XMM[9]}, [r0,:128]!
2059 veor @XMM[0], @XMM[0], @XMM[ 8]
2060 veor @XMM[1], @XMM[1], @XMM[ 9]
2061 vst1.8 {@XMM[0]-@XMM[1]}, [$out]!
2063 vld1.64 {@XMM[8]}, [r0,:128] @ next round tweak
2068 veor @XMM[0], @XMM[8]
2070 vst1.8 {@XMM[0]}, [sp,:128]
2072 mov r4, $fp @ preserve fp
2073 mov r5, $magic @ preserve magic
2077 vld1.8 {@XMM[0]}, [sp,:128]
2078 veor @XMM[0], @XMM[0], @XMM[8]
2079 vst1.8 {@XMM[0]}, [$out]!
2083 vmov @XMM[8], @XMM[9] @ next round tweak
2089 @ calculate one round of extra tweak for the stolen ciphertext
2090 vldmia $magic, {$twmask}
2091 vshr.s64 @XMM[6], @XMM[8], #63
2092 vand @XMM[6], @XMM[6], $twmask
2093 vadd.u64 @XMM[9], @XMM[8], @XMM[8]
2094 vswp `&Dhi("@XMM[6]")`,`&Dlo("@XMM[6]")`
2095 veor @XMM[9], @XMM[9], @XMM[6]
2097 @ perform the final decryption with the last tweak value
2098 vld1.8 {@XMM[0]}, [$inp]!
2100 veor @XMM[0], @XMM[0], @XMM[9]
2102 vst1.8 {@XMM[0]}, [sp,:128]
2104 mov r4, $fp @ preserve fp
2108 vld1.8 {@XMM[0]}, [sp,:128]
2109 veor @XMM[0], @XMM[0], @XMM[9]
2110 vst1.8 {@XMM[0]}, [$out]
2116 strb r1, [$out, #0x10]
2122 vld1.8 {@XMM[0]}, [r6]
2124 veor @XMM[0], @XMM[8]
2126 vst1.8 {@XMM[0]}, [sp,:128]
2131 vld1.8 {@XMM[0]}, [sp,:128]
2132 veor @XMM[0], @XMM[0], @XMM[8]
2133 vst1.8 {@XMM[0]}, [r6]
2140 .Lxts_dec_bzero: @ wipe key schedule [if any]
2146 vldmia sp!, {d8-d15}
2147 ldmia sp!, {r4-r10, pc} @ return
2149 .size bsaes_xts_decrypt,.-bsaes_xts_decrypt
2156 $code =~ s/\`([^\`]*)\`/eval($1)/gem;