On Thu, 3 Oct 2013, Ard Biesheuvel wrote: > Bit sliced AES gives around 45% speedup on Cortex-A15 for encryption > and around 25% for decryption. This implementation of the AES algorithm > does not rely on any lookup tables so it is believed to be invulnerable > to cache timing attacks. > > This algorithm processes up to 8 blocks in parallel in constant time. This > means that it is not usable by chaining modes that are strictly sequential > in nature, such as CBC encryption. CBC decryption, however, can benefit from > this implementation and runs about 25% faster. The other chaining modes > implemented in this module, XTS and CTR, can execute fully in parallel in > both directions. > > The core code has been adopted from the OpenSSL project (in collaboration > with the original author, on cc). For ease of maintenance, this version is > identical to the upstream OpenSSL code, i.e., all modifications that were > required to make it suitable for inclusion into the kernel have been made > upstream. The original [called bsaes-armv7.pl] can be found here: > > http://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=6f6a6130 > > Note to integrators: > While this implementation is significantly faster than the existing table > based ones (generic or ARM asm), especially in CTR mode, the effects on > power efficiency are unclear as of yet. This code does fundamentally more > work, by calculating values that the table based code obtains by a simple > lookup; only by doing all of that work in a SIMD fashion, it manages to > perform better. > > Cc: Andy Polyakov <appro@xxxxxxxxxxx> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> Acked-by: Nicolas Pitre <nico@xxxxxxxxxx> > --- > arch/arm/crypto/Makefile | 6 +- > arch/arm/crypto/aesbs-core.S | 2544 ++++++++++++++++++++++++++++++++++++++++++ > arch/arm/crypto/aesbs-glue.c | 435 ++++++++ > crypto/Kconfig | 16 + > 4 files changed, 2999 insertions(+), 2 deletions(-) > create mode 100644 arch/arm/crypto/aesbs-core.S > create mode 100644 arch/arm/crypto/aesbs-glue.c > > diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile > index a2c8385..bda5848 100644 > --- a/arch/arm/crypto/Makefile > +++ b/arch/arm/crypto/Makefile > @@ -3,7 +3,9 @@ > # > > obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o > +obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o > obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o > > -aes-arm-y := aes-armv4.o aes_glue.o > -sha1-arm-y := sha1-armv4-large.o sha1_glue.o > +aes-arm-y := aes-armv4.o aes_glue.o > +aes-arm-bs-y := aesbs-core.o aesbs-glue.o > +sha1-arm-y := sha1-armv4-large.o sha1_glue.o > diff --git a/arch/arm/crypto/aesbs-core.S b/arch/arm/crypto/aesbs-core.S > new file mode 100644 > index 0000000..64205d4 > --- /dev/null > +++ b/arch/arm/crypto/aesbs-core.S > @@ -0,0 +1,2544 @@ > + > +@ ==================================================================== > +@ Written by Andy Polyakov <appro@xxxxxxxxxxx> for the OpenSSL > +@ project. The module is, however, dual licensed under OpenSSL and > +@ CRYPTOGAMS licenses depending on where you obtain it. For further > +@ details see http://www.openssl.org/~appro/cryptogams/. > +@ > +@ Specific modes and adaptation for Linux kernel by Ard Biesheuvel > +@ <ard.biesheuvel@xxxxxxxxxx>. Permission to use under GPL terms is > +@ granted. > +@ ==================================================================== > + > +@ Bit-sliced AES for ARM NEON > +@ > +@ February 2012. > +@ > +@ This implementation is direct adaptation of bsaes-x86_64 module for > +@ ARM NEON. Except that this module is endian-neutral [in sense that > +@ it can be compiled for either endianness] by courtesy of vld1.8's > +@ neutrality. Initial version doesn't implement interface to OpenSSL, > +@ only low-level primitives and unsupported entry points, just enough > +@ to collect performance results, which for Cortex-A8 core are: > +@ > +@ encrypt 19.5 cycles per byte processed with 128-bit key > +@ decrypt 22.1 cycles per byte processed with 128-bit key > +@ key conv. 440 cycles per 128-bit key/0.18 of 8x block > +@ > +@ Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7, > +@ which is [much] worse than anticipated (for further details see > +@ http://www.openssl.org/~appro/Snapdragon-S4.html). > +@ > +@ Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code > +@ manages in 20.0 cycles]. > +@ > +@ When comparing to x86_64 results keep in mind that NEON unit is > +@ [mostly] single-issue and thus can't [fully] benefit from > +@ instruction-level parallelism. And when comparing to aes-armv4 > +@ results keep in mind key schedule conversion overhead (see > +@ bsaes-x86_64.pl for further details)... > +@ > +@ <appro@xxxxxxxxxxx> > + > +@ April-August 2013 > +@ > +@ Add CBC, CTR and XTS subroutines, adapt for kernel use. > +@ > +@ <ard.biesheuvel@xxxxxxxxxx> > + > +#ifndef __KERNEL__ > +# include "arm_arch.h" > + > +# define VFP_ABI_PUSH vstmdb sp!,{d8-d15} > +# define VFP_ABI_POP vldmia sp!,{d8-d15} > +# define VFP_ABI_FRAME 0x40 > +#else > +# define VFP_ABI_PUSH > +# define VFP_ABI_POP > +# define VFP_ABI_FRAME 0 > +# define BSAES_ASM_EXTENDED_KEY > +# define XTS_CHAIN_TWEAK > +# define __ARM_ARCH__ __LINUX_ARM_ARCH__ > +#endif > + > +#ifdef __thumb__ > +# define adrl adr > +#endif > + > +#if __ARM_ARCH__>=7 > +.text > +.syntax unified @ ARMv7-capable assembler is expected to handle this > +#ifdef __thumb2__ > +.thumb > +#else > +.code 32 > +#endif > + > +.fpu neon > + > +.type _bsaes_decrypt8,%function > +.align 4 > +_bsaes_decrypt8: > + adr r6,_bsaes_decrypt8 > + vldmia r4!, {q9} @ round 0 key > + add r6,r6,#.LM0ISR-_bsaes_decrypt8 > + > + vldmia r6!, {q8} @ .LM0ISR > + veor q10, q0, q9 @ xor with round0 key > + veor q11, q1, q9 > + vtbl.8 d0, {q10}, d16 > + vtbl.8 d1, {q10}, d17 > + veor q12, q2, q9 > + vtbl.8 d2, {q11}, d16 > + vtbl.8 d3, {q11}, d17 > + veor q13, q3, q9 > + vtbl.8 d4, {q12}, d16 > + vtbl.8 d5, {q12}, d17 > + veor q14, q4, q9 > + vtbl.8 d6, {q13}, d16 > + vtbl.8 d7, {q13}, d17 > + veor q15, q5, q9 > + vtbl.8 d8, {q14}, d16 > + vtbl.8 d9, {q14}, d17 > + veor q10, q6, q9 > + vtbl.8 d10, {q15}, d16 > + vtbl.8 d11, {q15}, d17 > + veor q11, q7, q9 > + vtbl.8 d12, {q10}, d16 > + vtbl.8 d13, {q10}, d17 > + vtbl.8 d14, {q11}, d16 > + vtbl.8 d15, {q11}, d17 > + vmov.i8 q8,#0x55 @ compose .LBS0 > + vmov.i8 q9,#0x33 @ compose .LBS1 > + vshr.u64 q10, q6, #1 > + vshr.u64 q11, q4, #1 > + veor q10, q10, q7 > + veor q11, q11, q5 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q7, q7, q10 > + vshl.u64 q10, q10, #1 > + veor q5, q5, q11 > + vshl.u64 q11, q11, #1 > + veor q6, q6, q10 > + veor q4, q4, q11 > + vshr.u64 q10, q2, #1 > + vshr.u64 q11, q0, #1 > + veor q10, q10, q3 > + veor q11, q11, q1 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q3, q3, q10 > + vshl.u64 q10, q10, #1 > + veor q1, q1, q11 > + vshl.u64 q11, q11, #1 > + veor q2, q2, q10 > + veor q0, q0, q11 > + vmov.i8 q8,#0x0f @ compose .LBS2 > + vshr.u64 q10, q5, #2 > + vshr.u64 q11, q4, #2 > + veor q10, q10, q7 > + veor q11, q11, q6 > + vand q10, q10, q9 > + vand q11, q11, q9 > + veor q7, q7, q10 > + vshl.u64 q10, q10, #2 > + veor q6, q6, q11 > + vshl.u64 q11, q11, #2 > + veor q5, q5, q10 > + veor q4, q4, q11 > + vshr.u64 q10, q1, #2 > + vshr.u64 q11, q0, #2 > + veor q10, q10, q3 > + veor q11, q11, q2 > + vand q10, q10, q9 > + vand q11, q11, q9 > + veor q3, q3, q10 > + vshl.u64 q10, q10, #2 > + veor q2, q2, q11 > + vshl.u64 q11, q11, #2 > + veor q1, q1, q10 > + veor q0, q0, q11 > + vshr.u64 q10, q3, #4 > + vshr.u64 q11, q2, #4 > + veor q10, q10, q7 > + veor q11, q11, q6 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q7, q7, q10 > + vshl.u64 q10, q10, #4 > + veor q6, q6, q11 > + vshl.u64 q11, q11, #4 > + veor q3, q3, q10 > + veor q2, q2, q11 > + vshr.u64 q10, q1, #4 > + vshr.u64 q11, q0, #4 > + veor q10, q10, q5 > + veor q11, q11, q4 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q5, q5, q10 > + vshl.u64 q10, q10, #4 > + veor q4, q4, q11 > + vshl.u64 q11, q11, #4 > + veor q1, q1, q10 > + veor q0, q0, q11 > + sub r5,r5,#1 > + b .Ldec_sbox > +.align 4 > +.Ldec_loop: > + vldmia r4!, {q8-q11} > + veor q8, q8, q0 > + veor q9, q9, q1 > + vtbl.8 d0, {q8}, d24 > + vtbl.8 d1, {q8}, d25 > + vldmia r4!, {q8} > + veor q10, q10, q2 > + vtbl.8 d2, {q9}, d24 > + vtbl.8 d3, {q9}, d25 > + vldmia r4!, {q9} > + veor q11, q11, q3 > + vtbl.8 d4, {q10}, d24 > + vtbl.8 d5, {q10}, d25 > + vldmia r4!, {q10} > + vtbl.8 d6, {q11}, d24 > + vtbl.8 d7, {q11}, d25 > + vldmia r4!, {q11} > + veor q8, q8, q4 > + veor q9, q9, q5 > + vtbl.8 d8, {q8}, d24 > + vtbl.8 d9, {q8}, d25 > + veor q10, q10, q6 > + vtbl.8 d10, {q9}, d24 > + vtbl.8 d11, {q9}, d25 > + veor q11, q11, q7 > + vtbl.8 d12, {q10}, d24 > + vtbl.8 d13, {q10}, d25 > + vtbl.8 d14, {q11}, d24 > + vtbl.8 d15, {q11}, d25 > +.Ldec_sbox: > + veor q1, q1, q4 > + veor q3, q3, q4 > + > + veor q4, q4, q7 > + veor q1, q1, q6 > + veor q2, q2, q7 > + veor q6, q6, q4 > + > + veor q0, q0, q1 > + veor q2, q2, q5 > + veor q7, q7, q6 > + veor q3, q3, q0 > + veor q5, q5, q0 > + veor q1, q1, q3 > + veor q11, q3, q0 > + veor q10, q7, q4 > + veor q9, q1, q6 > + veor q13, q4, q0 > + vmov q8, q10 > + veor q12, q5, q2 > + > + vorr q10, q10, q9 > + veor q15, q11, q8 > + vand q14, q11, q12 > + vorr q11, q11, q12 > + veor q12, q12, q9 > + vand q8, q8, q9 > + veor q9, q6, q2 > + vand q15, q15, q12 > + vand q13, q13, q9 > + veor q9, q3, q7 > + veor q12, q1, q5 > + veor q11, q11, q13 > + veor q10, q10, q13 > + vand q13, q9, q12 > + vorr q9, q9, q12 > + veor q11, q11, q15 > + veor q8, q8, q13 > + veor q10, q10, q14 > + veor q9, q9, q15 > + veor q8, q8, q14 > + vand q12, q4, q6 > + veor q9, q9, q14 > + vand q13, q0, q2 > + vand q14, q7, q1 > + vorr q15, q3, q5 > + veor q11, q11, q12 > + veor q9, q9, q14 > + veor q8, q8, q15 > + veor q10, q10, q13 > + > + @ Inv_GF16 0, 1, 2, 3, s0, s1, s2, s3 > + > + @ new smaller inversion > + > + vand q14, q11, q9 > + vmov q12, q8 > + > + veor q13, q10, q14 > + veor q15, q8, q14 > + veor q14, q8, q14 @ q14=q15 > + > + vbsl q13, q9, q8 > + vbsl q15, q11, q10 > + veor q11, q11, q10 > + > + vbsl q12, q13, q14 > + vbsl q8, q14, q13 > + > + vand q14, q12, q15 > + veor q9, q9, q8 > + > + veor q14, q14, q11 > + veor q12, q5, q2 > + veor q8, q1, q6 > + veor q10, q15, q14 > + vand q10, q10, q5 > + veor q5, q5, q1 > + vand q11, q1, q15 > + vand q5, q5, q14 > + veor q1, q11, q10 > + veor q5, q5, q11 > + veor q15, q15, q13 > + veor q14, q14, q9 > + veor q11, q15, q14 > + veor q10, q13, q9 > + vand q11, q11, q12 > + vand q10, q10, q2 > + veor q12, q12, q8 > + veor q2, q2, q6 > + vand q8, q8, q15 > + vand q6, q6, q13 > + vand q12, q12, q14 > + vand q2, q2, q9 > + veor q8, q8, q12 > + veor q2, q2, q6 > + veor q12, q12, q11 > + veor q6, q6, q10 > + veor q5, q5, q12 > + veor q2, q2, q12 > + veor q1, q1, q8 > + veor q6, q6, q8 > + > + veor q12, q3, q0 > + veor q8, q7, q4 > + veor q11, q15, q14 > + veor q10, q13, q9 > + vand q11, q11, q12 > + vand q10, q10, q0 > + veor q12, q12, q8 > + veor q0, q0, q4 > + vand q8, q8, q15 > + vand q4, q4, q13 > + vand q12, q12, q14 > + vand q0, q0, q9 > + veor q8, q8, q12 > + veor q0, q0, q4 > + veor q12, q12, q11 > + veor q4, q4, q10 > + veor q15, q15, q13 > + veor q14, q14, q9 > + veor q10, q15, q14 > + vand q10, q10, q3 > + veor q3, q3, q7 > + vand q11, q7, q15 > + vand q3, q3, q14 > + veor q7, q11, q10 > + veor q3, q3, q11 > + veor q3, q3, q12 > + veor q0, q0, q12 > + veor q7, q7, q8 > + veor q4, q4, q8 > + veor q1, q1, q7 > + veor q6, q6, q5 > + > + veor q4, q4, q1 > + veor q2, q2, q7 > + veor q5, q5, q7 > + veor q4, q4, q2 > + veor q7, q7, q0 > + veor q4, q4, q5 > + veor q3, q3, q6 > + veor q6, q6, q1 > + veor q3, q3, q4 > + > + veor q4, q4, q0 > + veor q7, q7, q3 > + subs r5,r5,#1 > + bcc .Ldec_done > + @ multiplication by 0x05-0x00-0x04-0x00 > + vext.8 q8, q0, q0, #8 > + vext.8 q14, q3, q3, #8 > + vext.8 q15, q5, q5, #8 > + veor q8, q8, q0 > + vext.8 q9, q1, q1, #8 > + veor q14, q14, q3 > + vext.8 q10, q6, q6, #8 > + veor q15, q15, q5 > + vext.8 q11, q4, q4, #8 > + veor q9, q9, q1 > + vext.8 q12, q2, q2, #8 > + veor q10, q10, q6 > + vext.8 q13, q7, q7, #8 > + veor q11, q11, q4 > + veor q12, q12, q2 > + veor q13, q13, q7 > + > + veor q0, q0, q14 > + veor q1, q1, q14 > + veor q6, q6, q8 > + veor q2, q2, q10 > + veor q4, q4, q9 > + veor q1, q1, q15 > + veor q6, q6, q15 > + veor q2, q2, q14 > + veor q7, q7, q11 > + veor q4, q4, q14 > + veor q3, q3, q12 > + veor q2, q2, q15 > + veor q7, q7, q15 > + veor q5, q5, q13 > + vext.8 q8, q0, q0, #12 @ x0 <<< 32 > + vext.8 q9, q1, q1, #12 > + veor q0, q0, q8 @ x0 ^ (x0 <<< 32) > + vext.8 q10, q6, q6, #12 > + veor q1, q1, q9 > + vext.8 q11, q4, q4, #12 > + veor q6, q6, q10 > + vext.8 q12, q2, q2, #12 > + veor q4, q4, q11 > + vext.8 q13, q7, q7, #12 > + veor q2, q2, q12 > + vext.8 q14, q3, q3, #12 > + veor q7, q7, q13 > + vext.8 q15, q5, q5, #12 > + veor q3, q3, q14 > + > + veor q9, q9, q0 > + veor q5, q5, q15 > + vext.8 q0, q0, q0, #8 @ (x0 ^ (x0 <<< 32)) <<< 64) > + veor q10, q10, q1 > + veor q8, q8, q5 > + veor q9, q9, q5 > + vext.8 q1, q1, q1, #8 > + veor q13, q13, q2 > + veor q0, q0, q8 > + veor q14, q14, q7 > + veor q1, q1, q9 > + vext.8 q8, q2, q2, #8 > + veor q12, q12, q4 > + vext.8 q9, q7, q7, #8 > + veor q15, q15, q3 > + vext.8 q2, q4, q4, #8 > + veor q11, q11, q6 > + vext.8 q7, q5, q5, #8 > + veor q12, q12, q5 > + vext.8 q4, q3, q3, #8 > + veor q11, q11, q5 > + vext.8 q3, q6, q6, #8 > + veor q5, q9, q13 > + veor q11, q11, q2 > + veor q7, q7, q15 > + veor q6, q4, q14 > + veor q4, q8, q12 > + veor q2, q3, q10 > + vmov q3, q11 > + @ vmov q5, q9 > + vldmia r6, {q12} @ .LISR > + ite eq @ Thumb2 thing, sanity check in ARM > + addeq r6,r6,#0x10 > + bne .Ldec_loop > + vldmia r6, {q12} @ .LISRM0 > + b .Ldec_loop > +.align 4 > +.Ldec_done: > + vmov.i8 q8,#0x55 @ compose .LBS0 > + vmov.i8 q9,#0x33 @ compose .LBS1 > + vshr.u64 q10, q3, #1 > + vshr.u64 q11, q2, #1 > + veor q10, q10, q5 > + veor q11, q11, q7 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q5, q5, q10 > + vshl.u64 q10, q10, #1 > + veor q7, q7, q11 > + vshl.u64 q11, q11, #1 > + veor q3, q3, q10 > + veor q2, q2, q11 > + vshr.u64 q10, q6, #1 > + vshr.u64 q11, q0, #1 > + veor q10, q10, q4 > + veor q11, q11, q1 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q4, q4, q10 > + vshl.u64 q10, q10, #1 > + veor q1, q1, q11 > + vshl.u64 q11, q11, #1 > + veor q6, q6, q10 > + veor q0, q0, q11 > + vmov.i8 q8,#0x0f @ compose .LBS2 > + vshr.u64 q10, q7, #2 > + vshr.u64 q11, q2, #2 > + veor q10, q10, q5 > + veor q11, q11, q3 > + vand q10, q10, q9 > + vand q11, q11, q9 > + veor q5, q5, q10 > + vshl.u64 q10, q10, #2 > + veor q3, q3, q11 > + vshl.u64 q11, q11, #2 > + veor q7, q7, q10 > + veor q2, q2, q11 > + vshr.u64 q10, q1, #2 > + vshr.u64 q11, q0, #2 > + veor q10, q10, q4 > + veor q11, q11, q6 > + vand q10, q10, q9 > + vand q11, q11, q9 > + veor q4, q4, q10 > + vshl.u64 q10, q10, #2 > + veor q6, q6, q11 > + vshl.u64 q11, q11, #2 > + veor q1, q1, q10 > + veor q0, q0, q11 > + vshr.u64 q10, q4, #4 > + vshr.u64 q11, q6, #4 > + veor q10, q10, q5 > + veor q11, q11, q3 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q5, q5, q10 > + vshl.u64 q10, q10, #4 > + veor q3, q3, q11 > + vshl.u64 q11, q11, #4 > + veor q4, q4, q10 > + veor q6, q6, q11 > + vshr.u64 q10, q1, #4 > + vshr.u64 q11, q0, #4 > + veor q10, q10, q7 > + veor q11, q11, q2 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q7, q7, q10 > + vshl.u64 q10, q10, #4 > + veor q2, q2, q11 > + vshl.u64 q11, q11, #4 > + veor q1, q1, q10 > + veor q0, q0, q11 > + vldmia r4, {q8} @ last round key > + veor q6, q6, q8 > + veor q4, q4, q8 > + veor q2, q2, q8 > + veor q7, q7, q8 > + veor q3, q3, q8 > + veor q5, q5, q8 > + veor q0, q0, q8 > + veor q1, q1, q8 > + bx lr > +.size _bsaes_decrypt8,.-_bsaes_decrypt8 > + > +.type _bsaes_const,%object > +.align 6 > +_bsaes_const: > +.LM0ISR: @ InvShiftRows constants > + .quad 0x0a0e0206070b0f03, 0x0004080c0d010509 > +.LISR: > + .quad 0x0504070602010003, 0x0f0e0d0c080b0a09 > +.LISRM0: > + .quad 0x01040b0e0205080f, 0x0306090c00070a0d > +.LM0SR: @ ShiftRows constants > + .quad 0x0a0e02060f03070b, 0x0004080c05090d01 > +.LSR: > + .quad 0x0504070600030201, 0x0f0e0d0c0a09080b > +.LSRM0: > + .quad 0x0304090e00050a0f, 0x01060b0c0207080d > +.LM0: > + .quad 0x02060a0e03070b0f, 0x0004080c0105090d > +.LREVM0SR: > + .quad 0x090d01050c000408, 0x03070b0f060a0e02 > +.asciz "Bit-sliced AES for NEON, CRYPTOGAMS by <appro@xxxxxxxxxxx>" > +.align 6 > +.size _bsaes_const,.-_bsaes_const > + > +.type _bsaes_encrypt8,%function > +.align 4 > +_bsaes_encrypt8: > + adr r6,_bsaes_encrypt8 > + vldmia r4!, {q9} @ round 0 key > + sub r6,r6,#_bsaes_encrypt8-.LM0SR > + > + vldmia r6!, {q8} @ .LM0SR > +_bsaes_encrypt8_alt: > + veor q10, q0, q9 @ xor with round0 key > + veor q11, q1, q9 > + vtbl.8 d0, {q10}, d16 > + vtbl.8 d1, {q10}, d17 > + veor q12, q2, q9 > + vtbl.8 d2, {q11}, d16 > + vtbl.8 d3, {q11}, d17 > + veor q13, q3, q9 > + vtbl.8 d4, {q12}, d16 > + vtbl.8 d5, {q12}, d17 > + veor q14, q4, q9 > + vtbl.8 d6, {q13}, d16 > + vtbl.8 d7, {q13}, d17 > + veor q15, q5, q9 > + vtbl.8 d8, {q14}, d16 > + vtbl.8 d9, {q14}, d17 > + veor q10, q6, q9 > + vtbl.8 d10, {q15}, d16 > + vtbl.8 d11, {q15}, d17 > + veor q11, q7, q9 > + vtbl.8 d12, {q10}, d16 > + vtbl.8 d13, {q10}, d17 > + vtbl.8 d14, {q11}, d16 > + vtbl.8 d15, {q11}, d17 > +_bsaes_encrypt8_bitslice: > + vmov.i8 q8,#0x55 @ compose .LBS0 > + vmov.i8 q9,#0x33 @ compose .LBS1 > + vshr.u64 q10, q6, #1 > + vshr.u64 q11, q4, #1 > + veor q10, q10, q7 > + veor q11, q11, q5 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q7, q7, q10 > + vshl.u64 q10, q10, #1 > + veor q5, q5, q11 > + vshl.u64 q11, q11, #1 > + veor q6, q6, q10 > + veor q4, q4, q11 > + vshr.u64 q10, q2, #1 > + vshr.u64 q11, q0, #1 > + veor q10, q10, q3 > + veor q11, q11, q1 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q3, q3, q10 > + vshl.u64 q10, q10, #1 > + veor q1, q1, q11 > + vshl.u64 q11, q11, #1 > + veor q2, q2, q10 > + veor q0, q0, q11 > + vmov.i8 q8,#0x0f @ compose .LBS2 > + vshr.u64 q10, q5, #2 > + vshr.u64 q11, q4, #2 > + veor q10, q10, q7 > + veor q11, q11, q6 > + vand q10, q10, q9 > + vand q11, q11, q9 > + veor q7, q7, q10 > + vshl.u64 q10, q10, #2 > + veor q6, q6, q11 > + vshl.u64 q11, q11, #2 > + veor q5, q5, q10 > + veor q4, q4, q11 > + vshr.u64 q10, q1, #2 > + vshr.u64 q11, q0, #2 > + veor q10, q10, q3 > + veor q11, q11, q2 > + vand q10, q10, q9 > + vand q11, q11, q9 > + veor q3, q3, q10 > + vshl.u64 q10, q10, #2 > + veor q2, q2, q11 > + vshl.u64 q11, q11, #2 > + veor q1, q1, q10 > + veor q0, q0, q11 > + vshr.u64 q10, q3, #4 > + vshr.u64 q11, q2, #4 > + veor q10, q10, q7 > + veor q11, q11, q6 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q7, q7, q10 > + vshl.u64 q10, q10, #4 > + veor q6, q6, q11 > + vshl.u64 q11, q11, #4 > + veor q3, q3, q10 > + veor q2, q2, q11 > + vshr.u64 q10, q1, #4 > + vshr.u64 q11, q0, #4 > + veor q10, q10, q5 > + veor q11, q11, q4 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q5, q5, q10 > + vshl.u64 q10, q10, #4 > + veor q4, q4, q11 > + vshl.u64 q11, q11, #4 > + veor q1, q1, q10 > + veor q0, q0, q11 > + sub r5,r5,#1 > + b .Lenc_sbox > +.align 4 > +.Lenc_loop: > + vldmia r4!, {q8-q11} > + veor q8, q8, q0 > + veor q9, q9, q1 > + vtbl.8 d0, {q8}, d24 > + vtbl.8 d1, {q8}, d25 > + vldmia r4!, {q8} > + veor q10, q10, q2 > + vtbl.8 d2, {q9}, d24 > + vtbl.8 d3, {q9}, d25 > + vldmia r4!, {q9} > + veor q11, q11, q3 > + vtbl.8 d4, {q10}, d24 > + vtbl.8 d5, {q10}, d25 > + vldmia r4!, {q10} > + vtbl.8 d6, {q11}, d24 > + vtbl.8 d7, {q11}, d25 > + vldmia r4!, {q11} > + veor q8, q8, q4 > + veor q9, q9, q5 > + vtbl.8 d8, {q8}, d24 > + vtbl.8 d9, {q8}, d25 > + veor q10, q10, q6 > + vtbl.8 d10, {q9}, d24 > + vtbl.8 d11, {q9}, d25 > + veor q11, q11, q7 > + vtbl.8 d12, {q10}, d24 > + vtbl.8 d13, {q10}, d25 > + vtbl.8 d14, {q11}, d24 > + vtbl.8 d15, {q11}, d25 > +.Lenc_sbox: > + veor q2, q2, q1 > + veor q5, q5, q6 > + veor q3, q3, q0 > + veor q6, q6, q2 > + veor q5, q5, q0 > + > + veor q6, q6, q3 > + veor q3, q3, q7 > + veor q7, q7, q5 > + veor q3, q3, q4 > + veor q4, q4, q5 > + > + veor q2, q2, q7 > + veor q3, q3, q1 > + veor q1, q1, q5 > + veor q11, q7, q4 > + veor q10, q1, q2 > + veor q9, q5, q3 > + veor q13, q2, q4 > + vmov q8, q10 > + veor q12, q6, q0 > + > + vorr q10, q10, q9 > + veor q15, q11, q8 > + vand q14, q11, q12 > + vorr q11, q11, q12 > + veor q12, q12, q9 > + vand q8, q8, q9 > + veor q9, q3, q0 > + vand q15, q15, q12 > + vand q13, q13, q9 > + veor q9, q7, q1 > + veor q12, q5, q6 > + veor q11, q11, q13 > + veor q10, q10, q13 > + vand q13, q9, q12 > + vorr q9, q9, q12 > + veor q11, q11, q15 > + veor q8, q8, q13 > + veor q10, q10, q14 > + veor q9, q9, q15 > + veor q8, q8, q14 > + vand q12, q2, q3 > + veor q9, q9, q14 > + vand q13, q4, q0 > + vand q14, q1, q5 > + vorr q15, q7, q6 > + veor q11, q11, q12 > + veor q9, q9, q14 > + veor q8, q8, q15 > + veor q10, q10, q13 > + > + @ Inv_GF16 0, 1, 2, 3, s0, s1, s2, s3 > + > + @ new smaller inversion > + > + vand q14, q11, q9 > + vmov q12, q8 > + > + veor q13, q10, q14 > + veor q15, q8, q14 > + veor q14, q8, q14 @ q14=q15 > + > + vbsl q13, q9, q8 > + vbsl q15, q11, q10 > + veor q11, q11, q10 > + > + vbsl q12, q13, q14 > + vbsl q8, q14, q13 > + > + vand q14, q12, q15 > + veor q9, q9, q8 > + > + veor q14, q14, q11 > + veor q12, q6, q0 > + veor q8, q5, q3 > + veor q10, q15, q14 > + vand q10, q10, q6 > + veor q6, q6, q5 > + vand q11, q5, q15 > + vand q6, q6, q14 > + veor q5, q11, q10 > + veor q6, q6, q11 > + veor q15, q15, q13 > + veor q14, q14, q9 > + veor q11, q15, q14 > + veor q10, q13, q9 > + vand q11, q11, q12 > + vand q10, q10, q0 > + veor q12, q12, q8 > + veor q0, q0, q3 > + vand q8, q8, q15 > + vand q3, q3, q13 > + vand q12, q12, q14 > + vand q0, q0, q9 > + veor q8, q8, q12 > + veor q0, q0, q3 > + veor q12, q12, q11 > + veor q3, q3, q10 > + veor q6, q6, q12 > + veor q0, q0, q12 > + veor q5, q5, q8 > + veor q3, q3, q8 > + > + veor q12, q7, q4 > + veor q8, q1, q2 > + veor q11, q15, q14 > + veor q10, q13, q9 > + vand q11, q11, q12 > + vand q10, q10, q4 > + veor q12, q12, q8 > + veor q4, q4, q2 > + vand q8, q8, q15 > + vand q2, q2, q13 > + vand q12, q12, q14 > + vand q4, q4, q9 > + veor q8, q8, q12 > + veor q4, q4, q2 > + veor q12, q12, q11 > + veor q2, q2, q10 > + veor q15, q15, q13 > + veor q14, q14, q9 > + veor q10, q15, q14 > + vand q10, q10, q7 > + veor q7, q7, q1 > + vand q11, q1, q15 > + vand q7, q7, q14 > + veor q1, q11, q10 > + veor q7, q7, q11 > + veor q7, q7, q12 > + veor q4, q4, q12 > + veor q1, q1, q8 > + veor q2, q2, q8 > + veor q7, q7, q0 > + veor q1, q1, q6 > + veor q6, q6, q0 > + veor q4, q4, q7 > + veor q0, q0, q1 > + > + veor q1, q1, q5 > + veor q5, q5, q2 > + veor q2, q2, q3 > + veor q3, q3, q5 > + veor q4, q4, q5 > + > + veor q6, q6, q3 > + subs r5,r5,#1 > + bcc .Lenc_done > + vext.8 q8, q0, q0, #12 @ x0 <<< 32 > + vext.8 q9, q1, q1, #12 > + veor q0, q0, q8 @ x0 ^ (x0 <<< 32) > + vext.8 q10, q4, q4, #12 > + veor q1, q1, q9 > + vext.8 q11, q6, q6, #12 > + veor q4, q4, q10 > + vext.8 q12, q3, q3, #12 > + veor q6, q6, q11 > + vext.8 q13, q7, q7, #12 > + veor q3, q3, q12 > + vext.8 q14, q2, q2, #12 > + veor q7, q7, q13 > + vext.8 q15, q5, q5, #12 > + veor q2, q2, q14 > + > + veor q9, q9, q0 > + veor q5, q5, q15 > + vext.8 q0, q0, q0, #8 @ (x0 ^ (x0 <<< 32)) <<< 64) > + veor q10, q10, q1 > + veor q8, q8, q5 > + veor q9, q9, q5 > + vext.8 q1, q1, q1, #8 > + veor q13, q13, q3 > + veor q0, q0, q8 > + veor q14, q14, q7 > + veor q1, q1, q9 > + vext.8 q8, q3, q3, #8 > + veor q12, q12, q6 > + vext.8 q9, q7, q7, #8 > + veor q15, q15, q2 > + vext.8 q3, q6, q6, #8 > + veor q11, q11, q4 > + vext.8 q7, q5, q5, #8 > + veor q12, q12, q5 > + vext.8 q6, q2, q2, #8 > + veor q11, q11, q5 > + vext.8 q2, q4, q4, #8 > + veor q5, q9, q13 > + veor q4, q8, q12 > + veor q3, q3, q11 > + veor q7, q7, q15 > + veor q6, q6, q14 > + @ vmov q4, q8 > + veor q2, q2, q10 > + @ vmov q5, q9 > + vldmia r6, {q12} @ .LSR > + ite eq @ Thumb2 thing, samity check in ARM > + addeq r6,r6,#0x10 > + bne .Lenc_loop > + vldmia r6, {q12} @ .LSRM0 > + b .Lenc_loop > +.align 4 > +.Lenc_done: > + vmov.i8 q8,#0x55 @ compose .LBS0 > + vmov.i8 q9,#0x33 @ compose .LBS1 > + vshr.u64 q10, q2, #1 > + vshr.u64 q11, q3, #1 > + veor q10, q10, q5 > + veor q11, q11, q7 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q5, q5, q10 > + vshl.u64 q10, q10, #1 > + veor q7, q7, q11 > + vshl.u64 q11, q11, #1 > + veor q2, q2, q10 > + veor q3, q3, q11 > + vshr.u64 q10, q4, #1 > + vshr.u64 q11, q0, #1 > + veor q10, q10, q6 > + veor q11, q11, q1 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q6, q6, q10 > + vshl.u64 q10, q10, #1 > + veor q1, q1, q11 > + vshl.u64 q11, q11, #1 > + veor q4, q4, q10 > + veor q0, q0, q11 > + vmov.i8 q8,#0x0f @ compose .LBS2 > + vshr.u64 q10, q7, #2 > + vshr.u64 q11, q3, #2 > + veor q10, q10, q5 > + veor q11, q11, q2 > + vand q10, q10, q9 > + vand q11, q11, q9 > + veor q5, q5, q10 > + vshl.u64 q10, q10, #2 > + veor q2, q2, q11 > + vshl.u64 q11, q11, #2 > + veor q7, q7, q10 > + veor q3, q3, q11 > + vshr.u64 q10, q1, #2 > + vshr.u64 q11, q0, #2 > + veor q10, q10, q6 > + veor q11, q11, q4 > + vand q10, q10, q9 > + vand q11, q11, q9 > + veor q6, q6, q10 > + vshl.u64 q10, q10, #2 > + veor q4, q4, q11 > + vshl.u64 q11, q11, #2 > + veor q1, q1, q10 > + veor q0, q0, q11 > + vshr.u64 q10, q6, #4 > + vshr.u64 q11, q4, #4 > + veor q10, q10, q5 > + veor q11, q11, q2 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q5, q5, q10 > + vshl.u64 q10, q10, #4 > + veor q2, q2, q11 > + vshl.u64 q11, q11, #4 > + veor q6, q6, q10 > + veor q4, q4, q11 > + vshr.u64 q10, q1, #4 > + vshr.u64 q11, q0, #4 > + veor q10, q10, q7 > + veor q11, q11, q3 > + vand q10, q10, q8 > + vand q11, q11, q8 > + veor q7, q7, q10 > + vshl.u64 q10, q10, #4 > + veor q3, q3, q11 > + vshl.u64 q11, q11, #4 > + veor q1, q1, q10 > + veor q0, q0, q11 > + vldmia r4, {q8} @ last round key > + veor q4, q4, q8 > + veor q6, q6, q8 > + veor q3, q3, q8 > + veor q7, q7, q8 > + veor q2, q2, q8 > + veor q5, q5, q8 > + veor q0, q0, q8 > + veor q1, q1, q8 > + bx lr > +.size _bsaes_encrypt8,.-_bsaes_encrypt8 > +.type _bsaes_key_convert,%function > +.align 4 > +_bsaes_key_convert: > + adr r6,_bsaes_key_convert > + vld1.8 {q7}, [r4]! @ load round 0 key > + sub r6,r6,#_bsaes_key_convert-.LM0 > + vld1.8 {q15}, [r4]! @ load round 1 key > + > + vmov.i8 q8, #0x01 @ bit masks > + vmov.i8 q9, #0x02 > + vmov.i8 q10, #0x04 > + vmov.i8 q11, #0x08 > + vmov.i8 q12, #0x10 > + vmov.i8 q13, #0x20 > + vldmia r6, {q14} @ .LM0 > + > +#ifdef __ARMEL__ > + vrev32.8 q7, q7 > + vrev32.8 q15, q15 > +#endif > + sub r5,r5,#1 > + vstmia r12!, {q7} @ save round 0 key > + b .Lkey_loop > + > +.align 4 > +.Lkey_loop: > + vtbl.8 d14,{q15},d28 > + vtbl.8 d15,{q15},d29 > + vmov.i8 q6, #0x40 > + vmov.i8 q15, #0x80 > + > + vtst.8 q0, q7, q8 > + vtst.8 q1, q7, q9 > + vtst.8 q2, q7, q10 > + vtst.8 q3, q7, q11 > + vtst.8 q4, q7, q12 > + vtst.8 q5, q7, q13 > + vtst.8 q6, q7, q6 > + vtst.8 q7, q7, q15 > + vld1.8 {q15}, [r4]! @ load next round key > + vmvn q0, q0 @ "pnot" > + vmvn q1, q1 > + vmvn q5, q5 > + vmvn q6, q6 > +#ifdef __ARMEL__ > + vrev32.8 q15, q15 > +#endif > + subs r5,r5,#1 > + vstmia r12!,{q0-q7} @ write bit-sliced round key > + bne .Lkey_loop > + > + vmov.i8 q7,#0x63 @ compose .L63 > + @ don't save last round key > + bx lr > +.size _bsaes_key_convert,.-_bsaes_key_convert > +.extern AES_cbc_encrypt > +.extern AES_decrypt > + > +.global bsaes_cbc_encrypt > +.type bsaes_cbc_encrypt,%function > +.align 5 > +bsaes_cbc_encrypt: > +#ifndef __KERNEL__ > + cmp r2, #128 > +#ifndef __thumb__ > + blo AES_cbc_encrypt > +#else > + bhs 1f > + b AES_cbc_encrypt > +1: > +#endif > +#endif > + > + @ it is up to the caller to make sure we are called with enc == 0 > + > + mov ip, sp > + stmdb sp!, {r4-r10, lr} > + VFP_ABI_PUSH > + ldr r8, [ip] @ IV is 1st arg on the stack > + mov r2, r2, lsr#4 @ len in 16 byte blocks > + sub sp, #0x10 @ scratch space to carry over the IV > + mov r9, sp @ save sp > + > + ldr r10, [r3, #240] @ get # of rounds > +#ifndef BSAES_ASM_EXTENDED_KEY > + @ allocate the key schedule on the stack > + sub r12, sp, r10, lsl#7 @ 128 bytes per inner round key > + add r12, #96 @ sifze of bit-slices key schedule > + > + @ populate the key schedule > + mov r4, r3 @ pass key > + mov r5, r10 @ pass # of rounds > + mov sp, r12 @ sp is sp > + bl _bsaes_key_convert > + vldmia sp, {q6} > + vstmia r12, {q15} @ save last round key > + veor q7, q7, q6 @ fix up round 0 key > + vstmia sp, {q7} > +#else > + ldr r12, [r3, #244] > + eors r12, #1 > + beq 0f > + > + @ populate the key schedule > + str r12, [r3, #244] > + mov r4, r3 @ pass key > + mov r5, r10 @ pass # of rounds > + add r12, r3, #248 @ pass key schedule > + bl _bsaes_key_convert > + add r4, r3, #248 > + vldmia r4, {q6} > + vstmia r12, {q15} @ save last round key > + veor q7, q7, q6 @ fix up round 0 key > + vstmia r4, {q7} > + > +.align 2 > +0: > +#endif > + > + vld1.8 {q15}, [r8] @ load IV > + b .Lcbc_dec_loop > + > +.align 4 > +.Lcbc_dec_loop: > + subs r2, r2, #0x8 > + bmi .Lcbc_dec_loop_finish > + > + vld1.8 {q0-q1}, [r0]! @ load input > + vld1.8 {q2-q3}, [r0]! > +#ifndef BSAES_ASM_EXTENDED_KEY > + mov r4, sp @ pass the key > +#else > + add r4, r3, #248 > +#endif > + vld1.8 {q4-q5}, [r0]! > + mov r5, r10 > + vld1.8 {q6-q7}, [r0] > + sub r0, r0, #0x60 > + vstmia r9, {q15} @ put aside IV > + > + bl _bsaes_decrypt8 > + > + vldmia r9, {q14} @ reload IV > + vld1.8 {q8-q9}, [r0]! @ reload input > + veor q0, q0, q14 @ ^= IV > + vld1.8 {q10-q11}, [r0]! > + veor q1, q1, q8 > + veor q6, q6, q9 > + vld1.8 {q12-q13}, [r0]! > + veor q4, q4, q10 > + veor q2, q2, q11 > + vld1.8 {q14-q15}, [r0]! > + veor q7, q7, q12 > + vst1.8 {q0-q1}, [r1]! @ write output > + veor q3, q3, q13 > + vst1.8 {q6}, [r1]! > + veor q5, q5, q14 > + vst1.8 {q4}, [r1]! > + vst1.8 {q2}, [r1]! > + vst1.8 {q7}, [r1]! > + vst1.8 {q3}, [r1]! > + vst1.8 {q5}, [r1]! > + > + b .Lcbc_dec_loop > + > +.Lcbc_dec_loop_finish: > + adds r2, r2, #8 > + beq .Lcbc_dec_done > + > + vld1.8 {q0}, [r0]! @ load input > + cmp r2, #2 > + blo .Lcbc_dec_one > + vld1.8 {q1}, [r0]! > +#ifndef BSAES_ASM_EXTENDED_KEY > + mov r4, sp @ pass the key > +#else > + add r4, r3, #248 > +#endif > + mov r5, r10 > + vstmia r9, {q15} @ put aside IV > + beq .Lcbc_dec_two > + vld1.8 {q2}, [r0]! > + cmp r2, #4 > + blo .Lcbc_dec_three > + vld1.8 {q3}, [r0]! > + beq .Lcbc_dec_four > + vld1.8 {q4}, [r0]! > + cmp r2, #6 > + blo .Lcbc_dec_five > + vld1.8 {q5}, [r0]! > + beq .Lcbc_dec_six > + vld1.8 {q6}, [r0]! > + sub r0, r0, #0x70 > + > + bl _bsaes_decrypt8 > + > + vldmia r9, {q14} @ reload IV > + vld1.8 {q8-q9}, [r0]! @ reload input > + veor q0, q0, q14 @ ^= IV > + vld1.8 {q10-q11}, [r0]! > + veor q1, q1, q8 > + veor q6, q6, q9 > + vld1.8 {q12-q13}, [r0]! > + veor q4, q4, q10 > + veor q2, q2, q11 > + vld1.8 {q15}, [r0]! > + veor q7, q7, q12 > + vst1.8 {q0-q1}, [r1]! @ write output > + veor q3, q3, q13 > + vst1.8 {q6}, [r1]! > + vst1.8 {q4}, [r1]! > + vst1.8 {q2}, [r1]! > + vst1.8 {q7}, [r1]! > + vst1.8 {q3}, [r1]! > + b .Lcbc_dec_done > +.align 4 > +.Lcbc_dec_six: > + sub r0, r0, #0x60 > + bl _bsaes_decrypt8 > + vldmia r9,{q14} @ reload IV > + vld1.8 {q8-q9}, [r0]! @ reload input > + veor q0, q0, q14 @ ^= IV > + vld1.8 {q10-q11}, [r0]! > + veor q1, q1, q8 > + veor q6, q6, q9 > + vld1.8 {q12}, [r0]! > + veor q4, q4, q10 > + veor q2, q2, q11 > + vld1.8 {q15}, [r0]! > + veor q7, q7, q12 > + vst1.8 {q0-q1}, [r1]! @ write output > + vst1.8 {q6}, [r1]! > + vst1.8 {q4}, [r1]! > + vst1.8 {q2}, [r1]! > + vst1.8 {q7}, [r1]! > + b .Lcbc_dec_done > +.align 4 > +.Lcbc_dec_five: > + sub r0, r0, #0x50 > + bl _bsaes_decrypt8 > + vldmia r9, {q14} @ reload IV > + vld1.8 {q8-q9}, [r0]! @ reload input > + veor q0, q0, q14 @ ^= IV > + vld1.8 {q10-q11}, [r0]! > + veor q1, q1, q8 > + veor q6, q6, q9 > + vld1.8 {q15}, [r0]! > + veor q4, q4, q10 > + vst1.8 {q0-q1}, [r1]! @ write output > + veor q2, q2, q11 > + vst1.8 {q6}, [r1]! > + vst1.8 {q4}, [r1]! > + vst1.8 {q2}, [r1]! > + b .Lcbc_dec_done > +.align 4 > +.Lcbc_dec_four: > + sub r0, r0, #0x40 > + bl _bsaes_decrypt8 > + vldmia r9, {q14} @ reload IV > + vld1.8 {q8-q9}, [r0]! @ reload input > + veor q0, q0, q14 @ ^= IV > + vld1.8 {q10}, [r0]! > + veor q1, q1, q8 > + veor q6, q6, q9 > + vld1.8 {q15}, [r0]! > + veor q4, q4, q10 > + vst1.8 {q0-q1}, [r1]! @ write output > + vst1.8 {q6}, [r1]! > + vst1.8 {q4}, [r1]! > + b .Lcbc_dec_done > +.align 4 > +.Lcbc_dec_three: > + sub r0, r0, #0x30 > + bl _bsaes_decrypt8 > + vldmia r9, {q14} @ reload IV > + vld1.8 {q8-q9}, [r0]! @ reload input > + veor q0, q0, q14 @ ^= IV > + vld1.8 {q15}, [r0]! > + veor q1, q1, q8 > + veor q6, q6, q9 > + vst1.8 {q0-q1}, [r1]! @ write output > + vst1.8 {q6}, [r1]! > + b .Lcbc_dec_done > +.align 4 > +.Lcbc_dec_two: > + sub r0, r0, #0x20 > + bl _bsaes_decrypt8 > + vldmia r9, {q14} @ reload IV > + vld1.8 {q8}, [r0]! @ reload input > + veor q0, q0, q14 @ ^= IV > + vld1.8 {q15}, [r0]! @ reload input > + veor q1, q1, q8 > + vst1.8 {q0-q1}, [r1]! @ write output > + b .Lcbc_dec_done > +.align 4 > +.Lcbc_dec_one: > + sub r0, r0, #0x10 > + mov r10, r1 @ save original out pointer > + mov r1, r9 @ use the iv scratch space as out buffer > + mov r2, r3 > + vmov q4,q15 @ just in case ensure that IV > + vmov q5,q0 @ and input are preserved > + bl AES_decrypt > + vld1.8 {q0}, [r9,:64] @ load result > + veor q0, q0, q4 @ ^= IV > + vmov q15, q5 @ q5 holds input > + vst1.8 {q0}, [r10] @ write output > + > +.Lcbc_dec_done: > +#ifndef BSAES_ASM_EXTENDED_KEY > + vmov.i32 q0, #0 > + vmov.i32 q1, #0 > +.Lcbc_dec_bzero: @ wipe key schedule [if any] > + vstmia sp!, {q0-q1} > + cmp sp, r9 > + bne .Lcbc_dec_bzero > +#endif > + > + mov sp, r9 > + add sp, #0x10 @ add sp,r9,#0x10 is no good for thumb > + vst1.8 {q15}, [r8] @ return IV > + VFP_ABI_POP > + ldmia sp!, {r4-r10, pc} > +.size bsaes_cbc_encrypt,.-bsaes_cbc_encrypt > +.extern AES_encrypt > +.global bsaes_ctr32_encrypt_blocks > +.type bsaes_ctr32_encrypt_blocks,%function > +.align 5 > +bsaes_ctr32_encrypt_blocks: > + cmp r2, #8 @ use plain AES for > + blo .Lctr_enc_short @ small sizes > + > + mov ip, sp > + stmdb sp!, {r4-r10, lr} > + VFP_ABI_PUSH > + ldr r8, [ip] @ ctr is 1st arg on the stack > + sub sp, sp, #0x10 @ scratch space to carry over the ctr > + mov r9, sp @ save sp > + > + ldr r10, [r3, #240] @ get # of rounds > +#ifndef BSAES_ASM_EXTENDED_KEY > + @ allocate the key schedule on the stack > + sub r12, sp, r10, lsl#7 @ 128 bytes per inner round key > + add r12, #96 @ size of bit-sliced key schedule > + > + @ populate the key schedule > + mov r4, r3 @ pass key > + mov r5, r10 @ pass # of rounds > + mov sp, r12 @ sp is sp > + bl _bsaes_key_convert > + veor q7,q7,q15 @ fix up last round key > + vstmia r12, {q7} @ save last round key > + > + vld1.8 {q0}, [r8] @ load counter > + add r8, r6, #.LREVM0SR-.LM0 @ borrow r8 > + vldmia sp, {q4} @ load round0 key > +#else > + ldr r12, [r3, #244] > + eors r12, #1 > + beq 0f > + > + @ populate the key schedule > + str r12, [r3, #244] > + mov r4, r3 @ pass key > + mov r5, r10 @ pass # of rounds > + add r12, r3, #248 @ pass key schedule > + bl _bsaes_key_convert > + veor q7,q7,q15 @ fix up last round key > + vstmia r12, {q7} @ save last round key > + > +.align 2 > +0: add r12, r3, #248 > + vld1.8 {q0}, [r8] @ load counter > + adrl r8, .LREVM0SR @ borrow r8 > + vldmia r12, {q4} @ load round0 key > + sub sp, #0x10 @ place for adjusted round0 key > +#endif > + > + vmov.i32 q8,#1 @ compose 1<<96 > + veor q9,q9,q9 > + vrev32.8 q0,q0 > + vext.8 q8,q9,q8,#4 > + vrev32.8 q4,q4 > + vadd.u32 q9,q8,q8 @ compose 2<<96 > + vstmia sp, {q4} @ save adjusted round0 key > + b .Lctr_enc_loop > + > +.align 4 > +.Lctr_enc_loop: > + vadd.u32 q10, q8, q9 @ compose 3<<96 > + vadd.u32 q1, q0, q8 @ +1 > + vadd.u32 q2, q0, q9 @ +2 > + vadd.u32 q3, q0, q10 @ +3 > + vadd.u32 q4, q1, q10 > + vadd.u32 q5, q2, q10 > + vadd.u32 q6, q3, q10 > + vadd.u32 q7, q4, q10 > + vadd.u32 q10, q5, q10 @ next counter > + > + @ Borrow prologue from _bsaes_encrypt8 to use the opportunity > + @ to flip byte order in 32-bit counter > + > + vldmia sp, {q9} @ load round0 key > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x10 @ pass next round key > +#else > + add r4, r3, #264 > +#endif > + vldmia r8, {q8} @ .LREVM0SR > + mov r5, r10 @ pass rounds > + vstmia r9, {q10} @ save next counter > + sub r6, r8, #.LREVM0SR-.LSR @ pass constants > + > + bl _bsaes_encrypt8_alt > + > + subs r2, r2, #8 > + blo .Lctr_enc_loop_done > + > + vld1.8 {q8-q9}, [r0]! @ load input > + vld1.8 {q10-q11}, [r0]! > + veor q0, q8 > + veor q1, q9 > + vld1.8 {q12-q13}, [r0]! > + veor q4, q10 > + veor q6, q11 > + vld1.8 {q14-q15}, [r0]! > + veor q3, q12 > + vst1.8 {q0-q1}, [r1]! @ write output > + veor q7, q13 > + veor q2, q14 > + vst1.8 {q4}, [r1]! > + veor q5, q15 > + vst1.8 {q6}, [r1]! > + vmov.i32 q8, #1 @ compose 1<<96 > + vst1.8 {q3}, [r1]! > + veor q9, q9, q9 > + vst1.8 {q7}, [r1]! > + vext.8 q8, q9, q8, #4 > + vst1.8 {q2}, [r1]! > + vadd.u32 q9,q8,q8 @ compose 2<<96 > + vst1.8 {q5}, [r1]! > + vldmia r9, {q0} @ load counter > + > + bne .Lctr_enc_loop > + b .Lctr_enc_done > + > +.align 4 > +.Lctr_enc_loop_done: > + add r2, r2, #8 > + vld1.8 {q8}, [r0]! @ load input > + veor q0, q8 > + vst1.8 {q0}, [r1]! @ write output > + cmp r2, #2 > + blo .Lctr_enc_done > + vld1.8 {q9}, [r0]! > + veor q1, q9 > + vst1.8 {q1}, [r1]! > + beq .Lctr_enc_done > + vld1.8 {q10}, [r0]! > + veor q4, q10 > + vst1.8 {q4}, [r1]! > + cmp r2, #4 > + blo .Lctr_enc_done > + vld1.8 {q11}, [r0]! > + veor q6, q11 > + vst1.8 {q6}, [r1]! > + beq .Lctr_enc_done > + vld1.8 {q12}, [r0]! > + veor q3, q12 > + vst1.8 {q3}, [r1]! > + cmp r2, #6 > + blo .Lctr_enc_done > + vld1.8 {q13}, [r0]! > + veor q7, q13 > + vst1.8 {q7}, [r1]! > + beq .Lctr_enc_done > + vld1.8 {q14}, [r0] > + veor q2, q14 > + vst1.8 {q2}, [r1]! > + > +.Lctr_enc_done: > + vmov.i32 q0, #0 > + vmov.i32 q1, #0 > +#ifndef BSAES_ASM_EXTENDED_KEY > +.Lctr_enc_bzero: @ wipe key schedule [if any] > + vstmia sp!, {q0-q1} > + cmp sp, r9 > + bne .Lctr_enc_bzero > +#else > + vstmia sp, {q0-q1} > +#endif > + > + mov sp, r9 > + add sp, #0x10 @ add sp,r9,#0x10 is no good for thumb > + VFP_ABI_POP > + ldmia sp!, {r4-r10, pc} @ return > + > +.align 4 > +.Lctr_enc_short: > + ldr ip, [sp] @ ctr pointer is passed on stack > + stmdb sp!, {r4-r8, lr} > + > + mov r4, r0 @ copy arguments > + mov r5, r1 > + mov r6, r2 > + mov r7, r3 > + ldr r8, [ip, #12] @ load counter LSW > + vld1.8 {q1}, [ip] @ load whole counter value > +#ifdef __ARMEL__ > + rev r8, r8 > +#endif > + sub sp, sp, #0x10 > + vst1.8 {q1}, [sp,:64] @ copy counter value > + sub sp, sp, #0x10 > + > +.Lctr_enc_short_loop: > + add r0, sp, #0x10 @ input counter value > + mov r1, sp @ output on the stack > + mov r2, r7 @ key > + > + bl AES_encrypt > + > + vld1.8 {q0}, [r4]! @ load input > + vld1.8 {q1}, [sp,:64] @ load encrypted counter > + add r8, r8, #1 > +#ifdef __ARMEL__ > + rev r0, r8 > + str r0, [sp, #0x1c] @ next counter value > +#else > + str r8, [sp, #0x1c] @ next counter value > +#endif > + veor q0,q0,q1 > + vst1.8 {q0}, [r5]! @ store output > + subs r6, r6, #1 > + bne .Lctr_enc_short_loop > + > + vmov.i32 q0, #0 > + vmov.i32 q1, #0 > + vstmia sp!, {q0-q1} > + > + ldmia sp!, {r4-r8, pc} > +.size bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks > +.globl bsaes_xts_encrypt > +.type bsaes_xts_encrypt,%function > +.align 4 > +bsaes_xts_encrypt: > + mov ip, sp > + stmdb sp!, {r4-r10, lr} @ 0x20 > + VFP_ABI_PUSH > + mov r6, sp @ future r3 > + > + mov r7, r0 > + mov r8, r1 > + mov r9, r2 > + mov r10, r3 > + > + sub r0, sp, #0x10 @ 0x10 > + bic r0, #0xf @ align at 16 bytes > + mov sp, r0 > + > +#ifdef XTS_CHAIN_TWEAK > + ldr r0, [ip] @ pointer to input tweak > +#else > + @ generate initial tweak > + ldr r0, [ip, #4] @ iv[] > + mov r1, sp > + ldr r2, [ip, #0] @ key2 > + bl AES_encrypt > + mov r0,sp @ pointer to initial tweak > +#endif > + > + ldr r1, [r10, #240] @ get # of rounds > + mov r3, r6 > +#ifndef BSAES_ASM_EXTENDED_KEY > + @ allocate the key schedule on the stack > + sub r12, sp, r1, lsl#7 @ 128 bytes per inner round key > + @ add r12, #96 @ size of bit-sliced key schedule > + sub r12, #48 @ place for tweak[9] > + > + @ populate the key schedule > + mov r4, r10 @ pass key > + mov r5, r1 @ pass # of rounds > + mov sp, r12 > + add r12, #0x90 @ pass key schedule > + bl _bsaes_key_convert > + veor q7, q7, q15 @ fix up last round key > + vstmia r12, {q7} @ save last round key > +#else > + ldr r12, [r10, #244] > + eors r12, #1 > + beq 0f > + > + str r12, [r10, #244] > + mov r4, r10 @ pass key > + mov r5, r1 @ pass # of rounds > + add r12, r10, #248 @ pass key schedule > + bl _bsaes_key_convert > + veor q7, q7, q15 @ fix up last round key > + vstmia r12, {q7} > + > +.align 2 > +0: sub sp, #0x90 @ place for tweak[9] > +#endif > + > + vld1.8 {q8}, [r0] @ initial tweak > + adr r2, .Lxts_magic > + > + subs r9, #0x80 > + blo .Lxts_enc_short > + b .Lxts_enc_loop > + > +.align 4 > +.Lxts_enc_loop: > + vldmia r2, {q5} @ load XTS magic > + vshr.s64 q6, q8, #63 > + mov r0, sp > + vand q6, q6, q5 > + vadd.u64 q9, q8, q8 > + vst1.64 {q8}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q9, #63 > + veor q9, q9, q6 > + vand q7, q7, q5 > + vadd.u64 q10, q9, q9 > + vst1.64 {q9}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q10, #63 > + veor q10, q10, q7 > + vand q6, q6, q5 > + vld1.8 {q0}, [r7]! > + vadd.u64 q11, q10, q10 > + vst1.64 {q10}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q11, #63 > + veor q11, q11, q6 > + vand q7, q7, q5 > + vld1.8 {q1}, [r7]! > + veor q0, q0, q8 > + vadd.u64 q12, q11, q11 > + vst1.64 {q11}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q12, #63 > + veor q12, q12, q7 > + vand q6, q6, q5 > + vld1.8 {q2}, [r7]! > + veor q1, q1, q9 > + vadd.u64 q13, q12, q12 > + vst1.64 {q12}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q13, #63 > + veor q13, q13, q6 > + vand q7, q7, q5 > + vld1.8 {q3}, [r7]! > + veor q2, q2, q10 > + vadd.u64 q14, q13, q13 > + vst1.64 {q13}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q14, #63 > + veor q14, q14, q7 > + vand q6, q6, q5 > + vld1.8 {q4}, [r7]! > + veor q3, q3, q11 > + vadd.u64 q15, q14, q14 > + vst1.64 {q14}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q15, #63 > + veor q15, q15, q6 > + vand q7, q7, q5 > + vld1.8 {q5}, [r7]! > + veor q4, q4, q12 > + vadd.u64 q8, q15, q15 > + vst1.64 {q15}, [r0,:128]! > + vswp d15,d14 > + veor q8, q8, q7 > + vst1.64 {q8}, [r0,:128] @ next round tweak > + > + vld1.8 {q6-q7}, [r7]! > + veor q5, q5, q13 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q6, q6, q14 > + mov r5, r1 @ pass rounds > + veor q7, q7, q15 > + mov r0, sp > + > + bl _bsaes_encrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + vld1.64 {q12-q13}, [r0,:128]! > + veor q1, q1, q9 > + veor q8, q4, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q6, q11 > + vld1.64 {q14-q15}, [r0,:128]! > + veor q10, q3, q12 > + vst1.8 {q8-q9}, [r8]! > + veor q11, q7, q13 > + veor q12, q2, q14 > + vst1.8 {q10-q11}, [r8]! > + veor q13, q5, q15 > + vst1.8 {q12-q13}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + > + subs r9, #0x80 > + bpl .Lxts_enc_loop > + > +.Lxts_enc_short: > + adds r9, #0x70 > + bmi .Lxts_enc_done > + > + vldmia r2, {q5} @ load XTS magic > + vshr.s64 q7, q8, #63 > + mov r0, sp > + vand q7, q7, q5 > + vadd.u64 q9, q8, q8 > + vst1.64 {q8}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q9, #63 > + veor q9, q9, q7 > + vand q6, q6, q5 > + vadd.u64 q10, q9, q9 > + vst1.64 {q9}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q10, #63 > + veor q10, q10, q6 > + vand q7, q7, q5 > + vld1.8 {q0}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_enc_1 > + vadd.u64 q11, q10, q10 > + vst1.64 {q10}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q11, #63 > + veor q11, q11, q7 > + vand q6, q6, q5 > + vld1.8 {q1}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_enc_2 > + veor q0, q0, q8 > + vadd.u64 q12, q11, q11 > + vst1.64 {q11}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q12, #63 > + veor q12, q12, q6 > + vand q7, q7, q5 > + vld1.8 {q2}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_enc_3 > + veor q1, q1, q9 > + vadd.u64 q13, q12, q12 > + vst1.64 {q12}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q13, #63 > + veor q13, q13, q7 > + vand q6, q6, q5 > + vld1.8 {q3}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_enc_4 > + veor q2, q2, q10 > + vadd.u64 q14, q13, q13 > + vst1.64 {q13}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q14, #63 > + veor q14, q14, q6 > + vand q7, q7, q5 > + vld1.8 {q4}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_enc_5 > + veor q3, q3, q11 > + vadd.u64 q15, q14, q14 > + vst1.64 {q14}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q15, #63 > + veor q15, q15, q7 > + vand q6, q6, q5 > + vld1.8 {q5}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_enc_6 > + veor q4, q4, q12 > + sub r9, #0x10 > + vst1.64 {q15}, [r0,:128] @ next round tweak > + > + vld1.8 {q6}, [r7]! > + veor q5, q5, q13 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q6, q6, q14 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_encrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + vld1.64 {q12-q13}, [r0,:128]! > + veor q1, q1, q9 > + veor q8, q4, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q6, q11 > + vld1.64 {q14}, [r0,:128]! > + veor q10, q3, q12 > + vst1.8 {q8-q9}, [r8]! > + veor q11, q7, q13 > + veor q12, q2, q14 > + vst1.8 {q10-q11}, [r8]! > + vst1.8 {q12}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_enc_done > +.align 4 > +.Lxts_enc_6: > + vst1.64 {q14}, [r0,:128] @ next round tweak > + > + veor q4, q4, q12 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q5, q5, q13 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_encrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + vld1.64 {q12-q13}, [r0,:128]! > + veor q1, q1, q9 > + veor q8, q4, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q6, q11 > + veor q10, q3, q12 > + vst1.8 {q8-q9}, [r8]! > + veor q11, q7, q13 > + vst1.8 {q10-q11}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_enc_done > + > +@ put this in range for both ARM and Thumb mode adr instructions > +.align 5 > +.Lxts_magic: > + .quad 1, 0x87 > + > +.align 5 > +.Lxts_enc_5: > + vst1.64 {q13}, [r0,:128] @ next round tweak > + > + veor q3, q3, q11 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q4, q4, q12 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_encrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + vld1.64 {q12}, [r0,:128]! > + veor q1, q1, q9 > + veor q8, q4, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q6, q11 > + veor q10, q3, q12 > + vst1.8 {q8-q9}, [r8]! > + vst1.8 {q10}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_enc_done > +.align 4 > +.Lxts_enc_4: > + vst1.64 {q12}, [r0,:128] @ next round tweak > + > + veor q2, q2, q10 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q3, q3, q11 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_encrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + veor q1, q1, q9 > + veor q8, q4, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q6, q11 > + vst1.8 {q8-q9}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_enc_done > +.align 4 > +.Lxts_enc_3: > + vst1.64 {q11}, [r0,:128] @ next round tweak > + > + veor q1, q1, q9 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q2, q2, q10 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_encrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10}, [r0,:128]! > + veor q0, q0, q8 > + veor q1, q1, q9 > + veor q8, q4, q10 > + vst1.8 {q0-q1}, [r8]! > + vst1.8 {q8}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_enc_done > +.align 4 > +.Lxts_enc_2: > + vst1.64 {q10}, [r0,:128] @ next round tweak > + > + veor q0, q0, q8 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q1, q1, q9 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_encrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + veor q0, q0, q8 > + veor q1, q1, q9 > + vst1.8 {q0-q1}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_enc_done > +.align 4 > +.Lxts_enc_1: > + mov r0, sp > + veor q0, q8 > + mov r1, sp > + vst1.8 {q0}, [sp,:128] > + mov r2, r10 > + mov r4, r3 @ preserve fp > + > + bl AES_encrypt > + > + vld1.8 {q0}, [sp,:128] > + veor q0, q0, q8 > + vst1.8 {q0}, [r8]! > + mov r3, r4 > + > + vmov q8, q9 @ next round tweak > + > +.Lxts_enc_done: > +#ifndef XTS_CHAIN_TWEAK > + adds r9, #0x10 > + beq .Lxts_enc_ret > + sub r6, r8, #0x10 > + > +.Lxts_enc_steal: > + ldrb r0, [r7], #1 > + ldrb r1, [r8, #-0x10] > + strb r0, [r8, #-0x10] > + strb r1, [r8], #1 > + > + subs r9, #1 > + bhi .Lxts_enc_steal > + > + vld1.8 {q0}, [r6] > + mov r0, sp > + veor q0, q0, q8 > + mov r1, sp > + vst1.8 {q0}, [sp,:128] > + mov r2, r10 > + mov r4, r3 @ preserve fp > + > + bl AES_encrypt > + > + vld1.8 {q0}, [sp,:128] > + veor q0, q0, q8 > + vst1.8 {q0}, [r6] > + mov r3, r4 > +#endif > + > +.Lxts_enc_ret: > + bic r0, r3, #0xf > + vmov.i32 q0, #0 > + vmov.i32 q1, #0 > +#ifdef XTS_CHAIN_TWEAK > + ldr r1, [r3, #0x20+VFP_ABI_FRAME] @ chain tweak > +#endif > +.Lxts_enc_bzero: @ wipe key schedule [if any] > + vstmia sp!, {q0-q1} > + cmp sp, r0 > + bne .Lxts_enc_bzero > + > + mov sp, r3 > +#ifdef XTS_CHAIN_TWEAK > + vst1.8 {q8}, [r1] > +#endif > + VFP_ABI_POP > + ldmia sp!, {r4-r10, pc} @ return > + > +.size bsaes_xts_encrypt,.-bsaes_xts_encrypt > + > +.globl bsaes_xts_decrypt > +.type bsaes_xts_decrypt,%function > +.align 4 > +bsaes_xts_decrypt: > + mov ip, sp > + stmdb sp!, {r4-r10, lr} @ 0x20 > + VFP_ABI_PUSH > + mov r6, sp @ future r3 > + > + mov r7, r0 > + mov r8, r1 > + mov r9, r2 > + mov r10, r3 > + > + sub r0, sp, #0x10 @ 0x10 > + bic r0, #0xf @ align at 16 bytes > + mov sp, r0 > + > +#ifdef XTS_CHAIN_TWEAK > + ldr r0, [ip] @ pointer to input tweak > +#else > + @ generate initial tweak > + ldr r0, [ip, #4] @ iv[] > + mov r1, sp > + ldr r2, [ip, #0] @ key2 > + bl AES_encrypt > + mov r0, sp @ pointer to initial tweak > +#endif > + > + ldr r1, [r10, #240] @ get # of rounds > + mov r3, r6 > +#ifndef BSAES_ASM_EXTENDED_KEY > + @ allocate the key schedule on the stack > + sub r12, sp, r1, lsl#7 @ 128 bytes per inner round key > + @ add r12, #96 @ size of bit-sliced key schedule > + sub r12, #48 @ place for tweak[9] > + > + @ populate the key schedule > + mov r4, r10 @ pass key > + mov r5, r1 @ pass # of rounds > + mov sp, r12 > + add r12, #0x90 @ pass key schedule > + bl _bsaes_key_convert > + add r4, sp, #0x90 > + vldmia r4, {q6} > + vstmia r12, {q15} @ save last round key > + veor q7, q7, q6 @ fix up round 0 key > + vstmia r4, {q7} > +#else > + ldr r12, [r10, #244] > + eors r12, #1 > + beq 0f > + > + str r12, [r10, #244] > + mov r4, r10 @ pass key > + mov r5, r1 @ pass # of rounds > + add r12, r10, #248 @ pass key schedule > + bl _bsaes_key_convert > + add r4, r10, #248 > + vldmia r4, {q6} > + vstmia r12, {q15} @ save last round key > + veor q7, q7, q6 @ fix up round 0 key > + vstmia r4, {q7} > + > +.align 2 > +0: sub sp, #0x90 @ place for tweak[9] > +#endif > + vld1.8 {q8}, [r0] @ initial tweak > + adr r2, .Lxts_magic > + > + tst r9, #0xf @ if not multiple of 16 > + it ne @ Thumb2 thing, sanity check in ARM > + subne r9, #0x10 @ subtract another 16 bytes > + subs r9, #0x80 > + > + blo .Lxts_dec_short > + b .Lxts_dec_loop > + > +.align 4 > +.Lxts_dec_loop: > + vldmia r2, {q5} @ load XTS magic > + vshr.s64 q6, q8, #63 > + mov r0, sp > + vand q6, q6, q5 > + vadd.u64 q9, q8, q8 > + vst1.64 {q8}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q9, #63 > + veor q9, q9, q6 > + vand q7, q7, q5 > + vadd.u64 q10, q9, q9 > + vst1.64 {q9}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q10, #63 > + veor q10, q10, q7 > + vand q6, q6, q5 > + vld1.8 {q0}, [r7]! > + vadd.u64 q11, q10, q10 > + vst1.64 {q10}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q11, #63 > + veor q11, q11, q6 > + vand q7, q7, q5 > + vld1.8 {q1}, [r7]! > + veor q0, q0, q8 > + vadd.u64 q12, q11, q11 > + vst1.64 {q11}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q12, #63 > + veor q12, q12, q7 > + vand q6, q6, q5 > + vld1.8 {q2}, [r7]! > + veor q1, q1, q9 > + vadd.u64 q13, q12, q12 > + vst1.64 {q12}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q13, #63 > + veor q13, q13, q6 > + vand q7, q7, q5 > + vld1.8 {q3}, [r7]! > + veor q2, q2, q10 > + vadd.u64 q14, q13, q13 > + vst1.64 {q13}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q14, #63 > + veor q14, q14, q7 > + vand q6, q6, q5 > + vld1.8 {q4}, [r7]! > + veor q3, q3, q11 > + vadd.u64 q15, q14, q14 > + vst1.64 {q14}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q15, #63 > + veor q15, q15, q6 > + vand q7, q7, q5 > + vld1.8 {q5}, [r7]! > + veor q4, q4, q12 > + vadd.u64 q8, q15, q15 > + vst1.64 {q15}, [r0,:128]! > + vswp d15,d14 > + veor q8, q8, q7 > + vst1.64 {q8}, [r0,:128] @ next round tweak > + > + vld1.8 {q6-q7}, [r7]! > + veor q5, q5, q13 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q6, q6, q14 > + mov r5, r1 @ pass rounds > + veor q7, q7, q15 > + mov r0, sp > + > + bl _bsaes_decrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + vld1.64 {q12-q13}, [r0,:128]! > + veor q1, q1, q9 > + veor q8, q6, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q4, q11 > + vld1.64 {q14-q15}, [r0,:128]! > + veor q10, q2, q12 > + vst1.8 {q8-q9}, [r8]! > + veor q11, q7, q13 > + veor q12, q3, q14 > + vst1.8 {q10-q11}, [r8]! > + veor q13, q5, q15 > + vst1.8 {q12-q13}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + > + subs r9, #0x80 > + bpl .Lxts_dec_loop > + > +.Lxts_dec_short: > + adds r9, #0x70 > + bmi .Lxts_dec_done > + > + vldmia r2, {q5} @ load XTS magic > + vshr.s64 q7, q8, #63 > + mov r0, sp > + vand q7, q7, q5 > + vadd.u64 q9, q8, q8 > + vst1.64 {q8}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q9, #63 > + veor q9, q9, q7 > + vand q6, q6, q5 > + vadd.u64 q10, q9, q9 > + vst1.64 {q9}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q10, #63 > + veor q10, q10, q6 > + vand q7, q7, q5 > + vld1.8 {q0}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_dec_1 > + vadd.u64 q11, q10, q10 > + vst1.64 {q10}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q11, #63 > + veor q11, q11, q7 > + vand q6, q6, q5 > + vld1.8 {q1}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_dec_2 > + veor q0, q0, q8 > + vadd.u64 q12, q11, q11 > + vst1.64 {q11}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q12, #63 > + veor q12, q12, q6 > + vand q7, q7, q5 > + vld1.8 {q2}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_dec_3 > + veor q1, q1, q9 > + vadd.u64 q13, q12, q12 > + vst1.64 {q12}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q13, #63 > + veor q13, q13, q7 > + vand q6, q6, q5 > + vld1.8 {q3}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_dec_4 > + veor q2, q2, q10 > + vadd.u64 q14, q13, q13 > + vst1.64 {q13}, [r0,:128]! > + vswp d13,d12 > + vshr.s64 q7, q14, #63 > + veor q14, q14, q6 > + vand q7, q7, q5 > + vld1.8 {q4}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_dec_5 > + veor q3, q3, q11 > + vadd.u64 q15, q14, q14 > + vst1.64 {q14}, [r0,:128]! > + vswp d15,d14 > + vshr.s64 q6, q15, #63 > + veor q15, q15, q7 > + vand q6, q6, q5 > + vld1.8 {q5}, [r7]! > + subs r9, #0x10 > + bmi .Lxts_dec_6 > + veor q4, q4, q12 > + sub r9, #0x10 > + vst1.64 {q15}, [r0,:128] @ next round tweak > + > + vld1.8 {q6}, [r7]! > + veor q5, q5, q13 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q6, q6, q14 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_decrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + vld1.64 {q12-q13}, [r0,:128]! > + veor q1, q1, q9 > + veor q8, q6, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q4, q11 > + vld1.64 {q14}, [r0,:128]! > + veor q10, q2, q12 > + vst1.8 {q8-q9}, [r8]! > + veor q11, q7, q13 > + veor q12, q3, q14 > + vst1.8 {q10-q11}, [r8]! > + vst1.8 {q12}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_dec_done > +.align 4 > +.Lxts_dec_6: > + vst1.64 {q14}, [r0,:128] @ next round tweak > + > + veor q4, q4, q12 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q5, q5, q13 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_decrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + vld1.64 {q12-q13}, [r0,:128]! > + veor q1, q1, q9 > + veor q8, q6, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q4, q11 > + veor q10, q2, q12 > + vst1.8 {q8-q9}, [r8]! > + veor q11, q7, q13 > + vst1.8 {q10-q11}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_dec_done > +.align 4 > +.Lxts_dec_5: > + vst1.64 {q13}, [r0,:128] @ next round tweak > + > + veor q3, q3, q11 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q4, q4, q12 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_decrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + vld1.64 {q12}, [r0,:128]! > + veor q1, q1, q9 > + veor q8, q6, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q4, q11 > + veor q10, q2, q12 > + vst1.8 {q8-q9}, [r8]! > + vst1.8 {q10}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_dec_done > +.align 4 > +.Lxts_dec_4: > + vst1.64 {q12}, [r0,:128] @ next round tweak > + > + veor q2, q2, q10 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q3, q3, q11 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_decrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10-q11}, [r0,:128]! > + veor q0, q0, q8 > + veor q1, q1, q9 > + veor q8, q6, q10 > + vst1.8 {q0-q1}, [r8]! > + veor q9, q4, q11 > + vst1.8 {q8-q9}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_dec_done > +.align 4 > +.Lxts_dec_3: > + vst1.64 {q11}, [r0,:128] @ next round tweak > + > + veor q1, q1, q9 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q2, q2, q10 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_decrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + vld1.64 {q10}, [r0,:128]! > + veor q0, q0, q8 > + veor q1, q1, q9 > + veor q8, q6, q10 > + vst1.8 {q0-q1}, [r8]! > + vst1.8 {q8}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_dec_done > +.align 4 > +.Lxts_dec_2: > + vst1.64 {q10}, [r0,:128] @ next round tweak > + > + veor q0, q0, q8 > +#ifndef BSAES_ASM_EXTENDED_KEY > + add r4, sp, #0x90 @ pass key schedule > +#else > + add r4, r10, #248 @ pass key schedule > +#endif > + veor q1, q1, q9 > + mov r5, r1 @ pass rounds > + mov r0, sp > + > + bl _bsaes_decrypt8 > + > + vld1.64 {q8-q9}, [r0,:128]! > + veor q0, q0, q8 > + veor q1, q1, q9 > + vst1.8 {q0-q1}, [r8]! > + > + vld1.64 {q8}, [r0,:128] @ next round tweak > + b .Lxts_dec_done > +.align 4 > +.Lxts_dec_1: > + mov r0, sp > + veor q0, q8 > + mov r1, sp > + vst1.8 {q0}, [sp,:128] > + mov r2, r10 > + mov r4, r3 @ preserve fp > + mov r5, r2 @ preserve magic > + > + bl AES_decrypt > + > + vld1.8 {q0}, [sp,:128] > + veor q0, q0, q8 > + vst1.8 {q0}, [r8]! > + mov r3, r4 > + mov r2, r5 > + > + vmov q8, q9 @ next round tweak > + > +.Lxts_dec_done: > +#ifndef XTS_CHAIN_TWEAK > + adds r9, #0x10 > + beq .Lxts_dec_ret > + > + @ calculate one round of extra tweak for the stolen ciphertext > + vldmia r2, {q5} > + vshr.s64 q6, q8, #63 > + vand q6, q6, q5 > + vadd.u64 q9, q8, q8 > + vswp d13,d12 > + veor q9, q9, q6 > + > + @ perform the final decryption with the last tweak value > + vld1.8 {q0}, [r7]! > + mov r0, sp > + veor q0, q0, q9 > + mov r1, sp > + vst1.8 {q0}, [sp,:128] > + mov r2, r10 > + mov r4, r3 @ preserve fp > + > + bl AES_decrypt > + > + vld1.8 {q0}, [sp,:128] > + veor q0, q0, q9 > + vst1.8 {q0}, [r8] > + > + mov r6, r8 > +.Lxts_dec_steal: > + ldrb r1, [r8] > + ldrb r0, [r7], #1 > + strb r1, [r8, #0x10] > + strb r0, [r8], #1 > + > + subs r9, #1 > + bhi .Lxts_dec_steal > + > + vld1.8 {q0}, [r6] > + mov r0, sp > + veor q0, q8 > + mov r1, sp > + vst1.8 {q0}, [sp,:128] > + mov r2, r10 > + > + bl AES_decrypt > + > + vld1.8 {q0}, [sp,:128] > + veor q0, q0, q8 > + vst1.8 {q0}, [r6] > + mov r3, r4 > +#endif > + > +.Lxts_dec_ret: > + bic r0, r3, #0xf > + vmov.i32 q0, #0 > + vmov.i32 q1, #0 > +#ifdef XTS_CHAIN_TWEAK > + ldr r1, [r3, #0x20+VFP_ABI_FRAME] @ chain tweak > +#endif > +.Lxts_dec_bzero: @ wipe key schedule [if any] > + vstmia sp!, {q0-q1} > + cmp sp, r0 > + bne .Lxts_dec_bzero > + > + mov sp, r3 > +#ifdef XTS_CHAIN_TWEAK > + vst1.8 {q8}, [r1] > +#endif > + VFP_ABI_POP > + ldmia sp!, {r4-r10, pc} @ return > + > +.size bsaes_xts_decrypt,.-bsaes_xts_decrypt > +#endif > diff --git a/arch/arm/crypto/aesbs-glue.c b/arch/arm/crypto/aesbs-glue.c > new file mode 100644 > index 0000000..e809443 > --- /dev/null > +++ b/arch/arm/crypto/aesbs-glue.c > @@ -0,0 +1,435 @@ > +/* > + * linux/arch/arm/crypto/aesbs-glue.c - glue code for NEON bit sliced AES > + * > + * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@xxxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > + > +#include <asm/neon.h> > +#include <crypto/aes.h> > +#include <crypto/ablk_helper.h> > +#include <crypto/algapi.h> > +#include <linux/module.h> > + > +#include "aes_glue.h" > + > +#define BIT_SLICED_KEY_MAXSIZE (128 * (AES_MAXNR - 1) + 2 * AES_BLOCK_SIZE) > + > +struct BS_KEY { > + struct AES_KEY rk; > + int converted; > + u8 __aligned(8) bs[BIT_SLICED_KEY_MAXSIZE]; > +} __aligned(8); > + > +asmlinkage void bsaes_enc_key_convert(u8 out[], struct AES_KEY const *in); > +asmlinkage void bsaes_dec_key_convert(u8 out[], struct AES_KEY const *in); > + > +asmlinkage void bsaes_cbc_encrypt(u8 const in[], u8 out[], u32 bytes, > + struct BS_KEY *key, u8 iv[]); > + > +asmlinkage void bsaes_ctr32_encrypt_blocks(u8 const in[], u8 out[], u32 blocks, > + struct BS_KEY *key, u8 const iv[]); > + > +asmlinkage void bsaes_xts_encrypt(u8 const in[], u8 out[], u32 bytes, > + struct BS_KEY *key, u8 tweak[]); > + > +asmlinkage void bsaes_xts_decrypt(u8 const in[], u8 out[], u32 bytes, > + struct BS_KEY *key, u8 tweak[]); > + > +struct aesbs_cbc_ctx { > + struct AES_KEY enc; > + struct BS_KEY dec; > +}; > + > +struct aesbs_ctr_ctx { > + struct BS_KEY enc; > +}; > + > +struct aesbs_xts_ctx { > + struct BS_KEY enc; > + struct BS_KEY dec; > + struct AES_KEY twkey; > +}; > + > +static int aesbs_cbc_set_key(struct crypto_tfm *tfm, const u8 *in_key, > + unsigned int key_len) > +{ > + struct aesbs_cbc_ctx *ctx = crypto_tfm_ctx(tfm); > + int bits = key_len * 8; > + > + if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc)) { > + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; > + return -EINVAL; > + } > + ctx->dec.rk = ctx->enc; > + private_AES_set_decrypt_key(in_key, bits, &ctx->dec.rk); > + ctx->dec.converted = 0; > + return 0; > +} > + > +static int aesbs_ctr_set_key(struct crypto_tfm *tfm, const u8 *in_key, > + unsigned int key_len) > +{ > + struct aesbs_ctr_ctx *ctx = crypto_tfm_ctx(tfm); > + int bits = key_len * 8; > + > + if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) { > + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; > + return -EINVAL; > + } > + ctx->enc.converted = 0; > + return 0; > +} > + > +static int aesbs_xts_set_key(struct crypto_tfm *tfm, const u8 *in_key, > + unsigned int key_len) > +{ > + struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm); > + int bits = key_len * 4; > + > + if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) { > + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; > + return -EINVAL; > + } > + ctx->dec.rk = ctx->enc.rk; > + private_AES_set_decrypt_key(in_key, bits, &ctx->dec.rk); > + private_AES_set_encrypt_key(in_key + key_len / 2, bits, &ctx->twkey); > + ctx->enc.converted = ctx->dec.converted = 0; > + return 0; > +} > + > +static int aesbs_cbc_encrypt(struct blkcipher_desc *desc, > + struct scatterlist *dst, > + struct scatterlist *src, unsigned int nbytes) > +{ > + struct aesbs_cbc_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); > + struct blkcipher_walk walk; > + int err; > + > + blkcipher_walk_init(&walk, dst, src, nbytes); > + err = blkcipher_walk_virt(desc, &walk); > + > + while (walk.nbytes) { > + u32 blocks = walk.nbytes / AES_BLOCK_SIZE; > + u8 *src = walk.src.virt.addr; > + > + if (walk.dst.virt.addr == walk.src.virt.addr) { > + u8 *iv = walk.iv; > + > + do { > + crypto_xor(src, iv, AES_BLOCK_SIZE); > + AES_encrypt(src, src, &ctx->enc); > + iv = src; > + src += AES_BLOCK_SIZE; > + } while (--blocks); > + memcpy(walk.iv, iv, AES_BLOCK_SIZE); > + } else { > + u8 *dst = walk.dst.virt.addr; > + > + do { > + crypto_xor(walk.iv, src, AES_BLOCK_SIZE); > + AES_encrypt(walk.iv, dst, &ctx->enc); > + memcpy(walk.iv, dst, AES_BLOCK_SIZE); > + src += AES_BLOCK_SIZE; > + dst += AES_BLOCK_SIZE; > + } while (--blocks); > + } > + err = blkcipher_walk_done(desc, &walk, 0); > + } > + return err; > +} > + > +static int aesbs_cbc_decrypt(struct blkcipher_desc *desc, > + struct scatterlist *dst, > + struct scatterlist *src, unsigned int nbytes) > +{ > + struct aesbs_cbc_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); > + struct blkcipher_walk walk; > + int err; > + > + blkcipher_walk_init(&walk, dst, src, nbytes); > + err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE); > + > + while ((walk.nbytes / AES_BLOCK_SIZE) >= 8) { > + kernel_neon_begin(); > + bsaes_cbc_encrypt(walk.src.virt.addr, walk.dst.virt.addr, > + walk.nbytes, &ctx->dec, walk.iv); > + kernel_neon_end(); > + err = blkcipher_walk_done(desc, &walk, 0); > + } > + while (walk.nbytes) { > + u32 blocks = walk.nbytes / AES_BLOCK_SIZE; > + u8 *dst = walk.dst.virt.addr; > + u8 *src = walk.src.virt.addr; > + u8 *iv = walk.iv; > + > + do { > + u8 bk[2][AES_BLOCK_SIZE]; > + > + if (walk.dst.virt.addr == walk.src.virt.addr) > + memcpy(bk[blocks & 1], src, AES_BLOCK_SIZE); > + > + AES_decrypt(src, dst, &ctx->dec.rk); > + crypto_xor(dst, iv, AES_BLOCK_SIZE); > + > + if (walk.dst.virt.addr == walk.src.virt.addr) > + iv = bk[blocks & 1]; > + else > + iv = src; > + > + dst += AES_BLOCK_SIZE; > + src += AES_BLOCK_SIZE; > + } while (--blocks); > + err = blkcipher_walk_done(desc, &walk, 0); > + } > + return err; > +} > + > +static void inc_be128_ctr(__be32 ctr[], u32 addend) > +{ > + int i; > + > + for (i = 3; i >= 0; i--, addend = 1) { > + u32 n = be32_to_cpu(ctr[i]) + addend; > + > + ctr[i] = cpu_to_be32(n); > + if (n >= addend) > + break; > + } > +} > + > +static int aesbs_ctr_encrypt(struct blkcipher_desc *desc, > + struct scatterlist *dst, struct scatterlist *src, > + unsigned int nbytes) > +{ > + struct aesbs_ctr_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); > + struct blkcipher_walk walk; > + u32 blocks; > + int err; > + > + blkcipher_walk_init(&walk, dst, src, nbytes); > + err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE); > + > + while ((blocks = walk.nbytes / AES_BLOCK_SIZE)) { > + u32 tail = walk.nbytes % AES_BLOCK_SIZE; > + __be32 *ctr = (__be32 *)walk.iv; > + u32 headroom = UINT_MAX - be32_to_cpu(ctr[3]); > + > + /* avoid 32 bit counter overflow in the NEON code */ > + if (unlikely(headroom < blocks)) { > + blocks = headroom + 1; > + tail = walk.nbytes - blocks * AES_BLOCK_SIZE; > + } > + kernel_neon_begin(); > + bsaes_ctr32_encrypt_blocks(walk.src.virt.addr, > + walk.dst.virt.addr, blocks, > + &ctx->enc, walk.iv); > + kernel_neon_end(); > + inc_be128_ctr(ctr, blocks); > + > + nbytes -= blocks * AES_BLOCK_SIZE; > + if (nbytes && nbytes == tail && nbytes <= AES_BLOCK_SIZE) > + break; > + > + err = blkcipher_walk_done(desc, &walk, tail); > + } > + if (walk.nbytes) { > + u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE; > + u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE; > + u8 ks[AES_BLOCK_SIZE]; > + > + AES_encrypt(walk.iv, ks, &ctx->enc.rk); > + if (tdst != tsrc) > + memcpy(tdst, tsrc, nbytes); > + crypto_xor(tdst, ks, nbytes); > + err = blkcipher_walk_done(desc, &walk, 0); > + } > + return err; > +} > + > +static int aesbs_xts_encrypt(struct blkcipher_desc *desc, > + struct scatterlist *dst, > + struct scatterlist *src, unsigned int nbytes) > +{ > + struct aesbs_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); > + struct blkcipher_walk walk; > + int err; > + > + blkcipher_walk_init(&walk, dst, src, nbytes); > + err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE); > + > + /* generate the initial tweak */ > + AES_encrypt(walk.iv, walk.iv, &ctx->twkey); > + > + while (walk.nbytes) { > + kernel_neon_begin(); > + bsaes_xts_encrypt(walk.src.virt.addr, walk.dst.virt.addr, > + walk.nbytes, &ctx->enc, walk.iv); > + kernel_neon_end(); > + err = blkcipher_walk_done(desc, &walk, 0); > + } > + return err; > +} > + > +static int aesbs_xts_decrypt(struct blkcipher_desc *desc, > + struct scatterlist *dst, > + struct scatterlist *src, unsigned int nbytes) > +{ > + struct aesbs_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); > + struct blkcipher_walk walk; > + int err; > + > + blkcipher_walk_init(&walk, dst, src, nbytes); > + err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE); > + > + /* generate the initial tweak */ > + AES_encrypt(walk.iv, walk.iv, &ctx->twkey); > + > + while (walk.nbytes) { > + kernel_neon_begin(); > + bsaes_xts_decrypt(walk.src.virt.addr, walk.dst.virt.addr, > + walk.nbytes, &ctx->dec, walk.iv); > + kernel_neon_end(); > + err = blkcipher_walk_done(desc, &walk, 0); > + } > + return err; > +} > + > +static struct crypto_alg aesbs_algs[] = { { > + .cra_name = "__cbc-aes-neonbs", > + .cra_driver_name = "__driver-cbc-aes-neonbs", > + .cra_priority = 0, > + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, > + .cra_blocksize = AES_BLOCK_SIZE, > + .cra_ctxsize = sizeof(struct aesbs_cbc_ctx), > + .cra_alignmask = 7, > + .cra_type = &crypto_blkcipher_type, > + .cra_module = THIS_MODULE, > + .cra_blkcipher = { > + .min_keysize = AES_MIN_KEY_SIZE, > + .max_keysize = AES_MAX_KEY_SIZE, > + .ivsize = AES_BLOCK_SIZE, > + .setkey = aesbs_cbc_set_key, > + .encrypt = aesbs_cbc_encrypt, > + .decrypt = aesbs_cbc_decrypt, > + }, > +}, { > + .cra_name = "__ctr-aes-neonbs", > + .cra_driver_name = "__driver-ctr-aes-neonbs", > + .cra_priority = 0, > + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, > + .cra_blocksize = 1, > + .cra_ctxsize = sizeof(struct aesbs_ctr_ctx), > + .cra_alignmask = 7, > + .cra_type = &crypto_blkcipher_type, > + .cra_module = THIS_MODULE, > + .cra_blkcipher = { > + .min_keysize = AES_MIN_KEY_SIZE, > + .max_keysize = AES_MAX_KEY_SIZE, > + .ivsize = AES_BLOCK_SIZE, > + .setkey = aesbs_ctr_set_key, > + .encrypt = aesbs_ctr_encrypt, > + .decrypt = aesbs_ctr_encrypt, > + }, > +}, { > + .cra_name = "__xts-aes-neonbs", > + .cra_driver_name = "__driver-xts-aes-neonbs", > + .cra_priority = 0, > + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, > + .cra_blocksize = AES_BLOCK_SIZE, > + .cra_ctxsize = sizeof(struct aesbs_xts_ctx), > + .cra_alignmask = 7, > + .cra_type = &crypto_blkcipher_type, > + .cra_module = THIS_MODULE, > + .cra_blkcipher = { > + .min_keysize = 2 * AES_MIN_KEY_SIZE, > + .max_keysize = 2 * AES_MAX_KEY_SIZE, > + .ivsize = AES_BLOCK_SIZE, > + .setkey = aesbs_xts_set_key, > + .encrypt = aesbs_xts_encrypt, > + .decrypt = aesbs_xts_decrypt, > + }, > +}, { > + .cra_name = "cbc(aes)", > + .cra_driver_name = "cbc-aes-neonbs", > + .cra_priority = 300, > + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, > + .cra_blocksize = AES_BLOCK_SIZE, > + .cra_ctxsize = sizeof(struct async_helper_ctx), > + .cra_alignmask = 7, > + .cra_type = &crypto_ablkcipher_type, > + .cra_module = THIS_MODULE, > + .cra_init = ablk_init, > + .cra_exit = ablk_exit, > + .cra_ablkcipher = { > + .min_keysize = AES_MIN_KEY_SIZE, > + .max_keysize = AES_MAX_KEY_SIZE, > + .ivsize = AES_BLOCK_SIZE, > + .setkey = ablk_set_key, > + .encrypt = __ablk_encrypt, > + .decrypt = ablk_decrypt, > + } > +}, { > + .cra_name = "ctr(aes)", > + .cra_driver_name = "ctr-aes-neonbs", > + .cra_priority = 300, > + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, > + .cra_blocksize = 1, > + .cra_ctxsize = sizeof(struct async_helper_ctx), > + .cra_alignmask = 7, > + .cra_type = &crypto_ablkcipher_type, > + .cra_module = THIS_MODULE, > + .cra_init = ablk_init, > + .cra_exit = ablk_exit, > + .cra_ablkcipher = { > + .min_keysize = AES_MIN_KEY_SIZE, > + .max_keysize = AES_MAX_KEY_SIZE, > + .ivsize = AES_BLOCK_SIZE, > + .setkey = ablk_set_key, > + .encrypt = ablk_encrypt, > + .decrypt = ablk_decrypt, > + } > +}, { > + .cra_name = "xts(aes)", > + .cra_driver_name = "xts-aes-neonbs", > + .cra_priority = 300, > + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, > + .cra_blocksize = AES_BLOCK_SIZE, > + .cra_ctxsize = sizeof(struct async_helper_ctx), > + .cra_alignmask = 7, > + .cra_type = &crypto_ablkcipher_type, > + .cra_module = THIS_MODULE, > + .cra_init = ablk_init, > + .cra_exit = ablk_exit, > + .cra_ablkcipher = { > + .min_keysize = 2 * AES_MIN_KEY_SIZE, > + .max_keysize = 2 * AES_MAX_KEY_SIZE, > + .ivsize = AES_BLOCK_SIZE, > + .setkey = ablk_set_key, > + .encrypt = ablk_encrypt, > + .decrypt = ablk_decrypt, > + } > +} }; > + > +static int __init aesbs_mod_init(void) > +{ > + if (!cpu_has_neon()) > + return -ENODEV; > + > + return crypto_register_algs(aesbs_algs, ARRAY_SIZE(aesbs_algs)); > +} > + > +static void __exit aesbs_mod_exit(void) > +{ > + crypto_unregister_algs(aesbs_algs, ARRAY_SIZE(aesbs_algs)); > +} > + > +module_init(aesbs_mod_init); > +module_exit(aesbs_mod_exit); > + > +MODULE_DESCRIPTION("Bit sliced AES in CBC/CTR/XTS modes using NEON"); > +MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx>"); > +MODULE_LICENSE("GPL"); > diff --git a/crypto/Kconfig b/crypto/Kconfig > index 8179ae6..4d6e656 100644 > --- a/crypto/Kconfig > +++ b/crypto/Kconfig > @@ -780,6 +780,22 @@ config CRYPTO_AES_ARM > > See <http://csrc.nist.gov/encryption/aes/> for more information. > > +config CRYPTO_AES_ARM_BS > + tristate "Bit sliced AES using NEON instructions" > + depends on ARM && KERNEL_MODE_NEON > + select CRYPTO_ALGAPI > + select CRYPTO_AES_ARM > + select CRYPTO_ABLK_HELPER > + help > + Use a faster and more secure NEON based implementation of AES in CBC, > + CTR and XTS modes > + > + Bit sliced AES gives around 45% speedup on Cortex-A15 for CTR mode > + and for XTS mode encryption, CBC and XTS mode decryption speedup is > + around 25%. (CBC encryption speed is not affected by this driver.) > + This implementation does not rely on any lookup tables so it is > + believed to be invulnerable to cache timing attacks. > + > config CRYPTO_ANUBIS > tristate "Anubis cipher algorithm" > select CRYPTO_ALGAPI > -- > 1.8.1.2 > -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html