2013-10-03 22:00:51

by Ard Biesheuvel

[permalink] [raw]
Subject: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

This is v2 of a series implementing a faster and more secure AES implementation
based on bit slicing using NEON instructions.

Changes since v1:
- implemented a suggestion by Jussi Kivilinna which substantially improves
decryption performance, decryption speedup is now 25% on Cortex-A15 (up from
5 - 10%), encryption speedup is still at 45%;
- fixed a potential issue with tail blocks in CTR mode;
- copied some comments about the origin of this code and the expected power
efficiency from the cover letter to the commit log of patch 3;
- some cosmetic changes.

This code passes the builtin test 'modprobe tcrypt.ko mode=10' in both ARM and
Thumb-2 modes.

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.

Note to reviewers:
Reviewing the file aesbs-core.S may be a bit overwhelming, so if there are any
questions or concerns, please refer the file bsaes-armv7.pl which can be found
at the link below. This is the original Perl script that gets called by
OpenSSL's build system during their build to generate the .S file on the fly.
[In the case of OpenSSL, this is used in some cases to target different
assemblers or ABIs]. This arrangement is not suitable (or required) for the
kernel, so I have taken the generated .S file instead.

http://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=6f6a6130

This series still depends on commit a62b01cd (crypto: create generic version of
ablk_helper) which I omitted this time but which can be found in the cryptodev
tree or in linux-next.

Ard Biesheuvel (3):
ARM: pull in <asm/simd.h> from asm-generic
ARM: move AES typedefs and function prototypes to separate header
ARM: add support for bit sliced AES using NEON instructions

arch/arm/crypto/Makefile | 6 +-
arch/arm/crypto/aes_glue.c | 22 +-
arch/arm/crypto/aes_glue.h | 19 +
arch/arm/crypto/aesbs-core.S | 2544 ++++++++++++++++++++++++++++++++++++++++++
arch/arm/crypto/aesbs-glue.c | 435 ++++++++
arch/arm/include/asm/Kbuild | 1 +
crypto/Kconfig | 16 +
7 files changed, 3025 insertions(+), 18 deletions(-)
create mode 100644 arch/arm/crypto/aes_glue.h
create mode 100644 arch/arm/crypto/aesbs-core.S
create mode 100644 arch/arm/crypto/aesbs-glue.c

--
1.8.1.2


2013-10-03 22:00:53

by Ard Biesheuvel

[permalink] [raw]
Subject: [PATCH v2 2/3] ARM: move AES typedefs and function prototypes to separate header

Put the struct definitions for AES keys and the asm function prototypes in a
separate header and export the asm functions from the module.
This allows other drivers to use them directly.

Signed-off-by: Ard Biesheuvel <[email protected]>
---
arch/arm/crypto/aes_glue.c | 22 ++++++----------------
arch/arm/crypto/aes_glue.h | 19 +++++++++++++++++++
2 files changed, 25 insertions(+), 16 deletions(-)
create mode 100644 arch/arm/crypto/aes_glue.h

diff --git a/arch/arm/crypto/aes_glue.c b/arch/arm/crypto/aes_glue.c
index 59f7877..3003fa1 100644
--- a/arch/arm/crypto/aes_glue.c
+++ b/arch/arm/crypto/aes_glue.c
@@ -6,22 +6,12 @@
#include <linux/crypto.h>
#include <crypto/aes.h>

-#define AES_MAXNR 14
+#include "aes_glue.h"

-typedef struct {
- unsigned int rd_key[4 *(AES_MAXNR + 1)];
- int rounds;
-} AES_KEY;
-
-struct AES_CTX {
- AES_KEY enc_key;
- AES_KEY dec_key;
-};
-
-asmlinkage void AES_encrypt(const u8 *in, u8 *out, AES_KEY *ctx);
-asmlinkage void AES_decrypt(const u8 *in, u8 *out, AES_KEY *ctx);
-asmlinkage int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
-asmlinkage int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
+EXPORT_SYMBOL(AES_encrypt);
+EXPORT_SYMBOL(AES_decrypt);
+EXPORT_SYMBOL(private_AES_set_encrypt_key);
+EXPORT_SYMBOL(private_AES_set_decrypt_key);

static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
@@ -81,7 +71,7 @@ static struct crypto_alg aes_alg = {
.cipher = {
.cia_min_keysize = AES_MIN_KEY_SIZE,
.cia_max_keysize = AES_MAX_KEY_SIZE,
- .cia_setkey = aes_set_key,
+ .cia_setkey = aes_set_key,
.cia_encrypt = aes_encrypt,
.cia_decrypt = aes_decrypt
}
diff --git a/arch/arm/crypto/aes_glue.h b/arch/arm/crypto/aes_glue.h
new file mode 100644
index 0000000..cca3e51
--- /dev/null
+++ b/arch/arm/crypto/aes_glue.h
@@ -0,0 +1,19 @@
+
+#define AES_MAXNR 14
+
+struct AES_KEY {
+ unsigned int rd_key[4 * (AES_MAXNR + 1)];
+ int rounds;
+};
+
+struct AES_CTX {
+ struct AES_KEY enc_key;
+ struct AES_KEY dec_key;
+};
+
+asmlinkage void AES_encrypt(const u8 *in, u8 *out, struct AES_KEY *ctx);
+asmlinkage void AES_decrypt(const u8 *in, u8 *out, struct AES_KEY *ctx);
+asmlinkage int private_AES_set_decrypt_key(const unsigned char *userKey,
+ const int bits, struct AES_KEY *key);
+asmlinkage int private_AES_set_encrypt_key(const unsigned char *userKey,
+ const int bits, struct AES_KEY *key);
--
1.8.1.2

2013-10-03 22:00:56

by Ard Biesheuvel

[permalink] [raw]
Subject: [PATCH v2 3/3] ARM: add support for bit sliced AES using NEON instructions

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 <[email protected]>
Signed-off-by: Ard Biesheuvel <[email protected]>
---
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 <[email protected]> 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
+@ <[email protected]>. 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)...
+@
+@ <[email protected]>
+
+@ April-August 2013
+@
+@ Add CBC, CTR and XTS subroutines, adapt for kernel use.
+@
+@ <[email protected]>
+
+#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 <[email protected]>"
+.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 <[email protected]>
+ *
+ * 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 <[email protected]>");
+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

2013-10-03 22:00:52

by Ard Biesheuvel

[permalink] [raw]
Subject: [PATCH v2 1/3] ARM: pull in <asm/simd.h> from asm-generic

Signed-off-by: Ard Biesheuvel <[email protected]>
---
arch/arm/include/asm/Kbuild | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index d3db398..6577b8a 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -24,6 +24,7 @@ generic-y += sembuf.h
generic-y += serial.h
generic-y += shmbuf.h
generic-y += siginfo.h
+generic-y += simd.h
generic-y += sizes.h
generic-y += socket.h
generic-y += sockios.h
--
1.8.1.2

2013-10-04 00:39:03

by Nicolas Pitre

[permalink] [raw]
Subject: Re: [PATCH v2 3/3] ARM: add support for bit sliced AES using NEON instructions

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 <[email protected]>
> Signed-off-by: Ard Biesheuvel <[email protected]>

Acked-by: Nicolas Pitre <[email protected]>

> ---
> 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 <[email protected]> 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
> +@ <[email protected]>. 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)...
> +@
> +@ <[email protected]>
> +
> +@ April-August 2013
> +@
> +@ Add CBC, CTR and XTS subroutines, adapt for kernel use.
> +@
> +@ <[email protected]>
> +
> +#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 <[email protected]>"
> +.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 <[email protected]>
> + *
> + * 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 <[email protected]>");
> +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
>

2013-10-04 17:49:54

by Will Deacon

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

Hi Ard,

On Thu, Oct 03, 2013 at 10:59:23PM +0100, Ard Biesheuvel wrote:
> Note to reviewers:
> Reviewing the file aesbs-core.S may be a bit overwhelming, so if there are any
> questions or concerns, please refer the file bsaes-armv7.pl which can be found
> at the link below. This is the original Perl script that gets called by
> OpenSSL's build system during their build to generate the .S file on the fly.
> [In the case of OpenSSL, this is used in some cases to target different
> assemblers or ABIs]. This arrangement is not suitable (or required) for the
> kernel, so I have taken the generated .S file instead.
>
> http://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=6f6a6130
>
> This series still depends on commit a62b01cd (crypto: create generic version of
> ablk_helper) which I omitted this time but which can be found in the cryptodev
> tree or in linux-next.

Why do you consider it unsuitable to ship the perl script with the kernel?
Perl 5 is already documented as a build dependency in Documentation/Changes
and I'd *much* rather the .S file was generated rather than shipped and
hacked. That amount of opaque assembly code for something like crypto feels really
dangerous from both a review and a maintenance perspective.

Will

2013-10-04 18:04:51

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

On 4 October 2013 19:48, Will Deacon <[email protected]> wrote:

> On Thu, Oct 03, 2013 at 10:59:23PM +0100, Ard Biesheuvel wrote:
>> Note to reviewers:
>> Reviewing the file aesbs-core.S may be a bit overwhelming, so if there are any
>> questions or concerns, please refer the file bsaes-armv7.pl which can be found
>> at the link below. This is the original Perl script that gets called by
>> OpenSSL's build system during their build to generate the .S file on the fly.
>> [In the case of OpenSSL, this is used in some cases to target different
>> assemblers or ABIs]. This arrangement is not suitable (or required) for the
>> kernel, so I have taken the generated .S file instead.
>>
>> http://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=6f6a6130
>>
>> This series still depends on commit a62b01cd (crypto: create generic version of
>> ablk_helper) which I omitted this time but which can be found in the cryptodev
>> tree or in linux-next.
>
> Why do you consider it unsuitable to ship the perl script with the kernel?
> Perl 5 is already documented as a build dependency in Documentation/Changes
> and I'd *much* rather the .S file was generated rather than shipped and
> hacked. That amount of opaque assembly code for something like crypto feels really
> dangerous from both a review and a maintenance perspective.
>

First of all, please note that the whole point of working so closely
with the OpenSSL maintainer on this is that the version I am
presenting here is the verbatim output of the Perl script that lives
in the OpenSSL tree. So just shipped, not shipped and hacked.

Personally, I would much prefer merging the .pl file as well, I just
thought (and I did poll some people informally) that this is not
something most people are happy about. If I am wrong about this, than
I am quite happy to respin so the .S is generated on the fly.

--
Ard.

2013-10-04 18:29:30

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

On Fri, Oct 04, 2013 at 08:04:50PM +0200, Ard Biesheuvel wrote:
> First of all, please note that the whole point of working so closely
> with the OpenSSL maintainer on this is that the version I am
> presenting here is the verbatim output of the Perl script that lives
> in the OpenSSL tree. So just shipped, not shipped and hacked.
>
> Personally, I would much prefer merging the .pl file as well, I just
> thought (and I did poll some people informally) that this is not
> something most people are happy about. If I am wrong about this, than
> I am quite happy to respin so the .S is generated on the fly.

While it is desirable to keep the dependencies on external tools to a
minimum, as perl is already on the list of required dependencies, there
is no problem with including a script.

Also, remember that the GPL says:

"The source code for a work means the preferred form of the work for
making modifications to it."

So here's the question: is the assembly code the perferred form to make
modifications? From what you're saying above, the answer to that seems
to be no. Now, I'm not going to throw toys out of the pram and say
that this is a hard requirement, but just take a moment to think about
how we treat vendors who don't do this, instead supplying "non-preferred"
forms of source code, and think about whether there's double standards
here.

Now, while I can imagine that people have an ideological objection to
perl (using comments like "write only code" etc) that's not a good
enough excuse to avoid including the perferred form for future
modification.

Now, we have mechanisms in the kernel build where we can include a
prepared source which can be used to lessen the burden on the toolset
required to build the kernel. So, including both the perl script and
the pre-generated assembly is entirely acceptable. This tends to
nullify the excuse that "we don't want to add additional tool burden
to kbuild" argument.

So, what I'd strongly recommend is that we add both the pre-generated
assembly with a _shipped suffix, the perl script, and include a rule
like this:

quiet_cmd_perl = PERL $@
cmd_perl = perl $< > $@

$(src)/blahblah.S_shipped: $(src)/myperlscript
$(call cmd,perl)

and that should end up running "myperlscript" whenever it has a date
stamp newer than the _shipped file, or if that file is missing.

2013-10-04 18:34:05

by Nicolas Pitre

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

On Fri, 4 Oct 2013, Will Deacon wrote:

> Hi Ard,
>
> On Thu, Oct 03, 2013 at 10:59:23PM +0100, Ard Biesheuvel wrote:
> > Note to reviewers:
> > Reviewing the file aesbs-core.S may be a bit overwhelming, so if there are any
> > questions or concerns, please refer the file bsaes-armv7.pl which can be found
> > at the link below. This is the original Perl script that gets called by
> > OpenSSL's build system during their build to generate the .S file on the fly.
> > [In the case of OpenSSL, this is used in some cases to target different
> > assemblers or ABIs]. This arrangement is not suitable (or required) for the
> > kernel, so I have taken the generated .S file instead.
> >
> > http://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=6f6a6130
> >
> > This series still depends on commit a62b01cd (crypto: create generic version of
> > ablk_helper) which I omitted this time but which can be found in the cryptodev
> > tree or in linux-next.
>
> Why do you consider it unsuitable to ship the perl script with the kernel?
> Perl 5 is already documented as a build dependency in Documentation/Changes

Do you have an example of something that does require perl to build the
kernel on ARM? I was under the impression that people try to avoid it
as much as possible in general.

I'm personally sitting on the fence between effectively adding a new
kernel build dependencies or carrying the output of the perl script.
But if the kernel build does already require perl in practice then this
might tip the balance.


Nicolas

2013-10-04 18:39:32

by Nicolas Pitre

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

On Fri, 4 Oct 2013, Russell King - ARM Linux wrote:

> Also, remember that the GPL says:
>
> "The source code for a work means the preferred form of the work for
> making modifications to it."
>
> So here's the question: is the assembly code the perferred form to make
> modifications? From what you're saying above, the answer to that seems
> to be no. Now, I'm not going to throw toys out of the pram and say
> that this is a hard requirement, but just take a moment to think about
> how we treat vendors who don't do this, instead supplying "non-preferred"
> forms of source code, and think about whether there's double standards
> here.
>
> Now, while I can imagine that people have an ideological objection to
> perl (using comments like "write only code" etc) that's not a good
> enough excuse to avoid including the perferred form for future
> modification.
>
> Now, we have mechanisms in the kernel build where we can include a
> prepared source which can be used to lessen the burden on the toolset
> required to build the kernel. So, including both the perl script and
> the pre-generated assembly is entirely acceptable. This tends to
> nullify the excuse that "we don't want to add additional tool burden
> to kbuild" argument.

Those are very good arguments. And I agree with your recommendation as
well.


Nicolas

2013-10-04 18:41:36

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

On 4 October 2013 20:34, Nicolas Pitre <[email protected]> wrote:
> On Fri, 4 Oct 2013, Will Deacon wrote:
[...]
>>
>> Why do you consider it unsuitable to ship the perl script with the kernel?
>> Perl 5 is already documented as a build dependency in Documentation/Changes
>
> Do you have an example of something that does require perl to build the
> kernel on ARM? I was under the impression that people try to avoid it
> as much as possible in general.
>
> I'm personally sitting on the fence between effectively adding a new
> kernel build dependencies or carrying the output of the perl script.
> But if the kernel build does already require perl in practice then this
> might tip the balance.
>

I like Russell's suggestion the most, in fact. In this case, the build
time requirement for Perl effectively gets suspended until you start
making modifications to the perl script, and the relation between the
.S and the .pl files is made explicit by the make rule.

Should I put the cmd_perl rule in scripts/Makefile.build ? Or can I
just keep it under arch/arm/crypto ?

--
Ard.

2013-10-04 18:45:44

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

On Fri, Oct 04, 2013 at 02:34:01PM -0400, Nicolas Pitre wrote:
> Do you have an example of something that does require perl to build the
> kernel on ARM? I was under the impression that people try to avoid it
> as much as possible in general.
>
> I'm personally sitting on the fence between effectively adding a new
> kernel build dependencies or carrying the output of the perl script.
> But if the kernel build does already require perl in practice then this
> might tip the balance.

That is really not a concern with the modern kbuild. It has supported
having shipped versions of generated files included in the source tree
for years. So, we can have the perl version included (the preferred
form for editing) while avoiding the issue of requiring everyone to
have perl.

In other words, if you want to build a kernel, you don't need perl for
this. If you want to edit the "preferred" form, then you do need perl
so that the "preferred" form can be turned into assembly to update the
shipped version.

2013-10-04 18:47:02

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

On Fri, Oct 04, 2013 at 08:41:35PM +0200, Ard Biesheuvel wrote:
> On 4 October 2013 20:34, Nicolas Pitre <[email protected]> wrote:
> > On Fri, 4 Oct 2013, Will Deacon wrote:
> [...]
> >>
> >> Why do you consider it unsuitable to ship the perl script with the kernel?
> >> Perl 5 is already documented as a build dependency in Documentation/Changes
> >
> > Do you have an example of something that does require perl to build the
> > kernel on ARM? I was under the impression that people try to avoid it
> > as much as possible in general.
> >
> > I'm personally sitting on the fence between effectively adding a new
> > kernel build dependencies or carrying the output of the perl script.
> > But if the kernel build does already require perl in practice then this
> > might tip the balance.
> >
>
> I like Russell's suggestion the most, in fact. In this case, the build
> time requirement for Perl effectively gets suspended until you start
> making modifications to the perl script, and the relation between the
> .S and the .pl files is made explicit by the make rule.
>
> Should I put the cmd_perl rule in scripts/Makefile.build ? Or can I
> just keep it under arch/arm/crypto ?

Just running through the Makefiles, it seems we have a fair amount
of stuff already using perl in various ways. So I wouldn't worry too
much about where it's placed. It's probably something that should
eventually end up in scripts/ at _some_ point.

2013-10-04 18:54:14

by Nicolas Pitre

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

On Fri, 4 Oct 2013, Ard Biesheuvel wrote:

> On 4 October 2013 20:34, Nicolas Pitre <[email protected]> wrote:
> > On Fri, 4 Oct 2013, Will Deacon wrote:
> [...]
> >>
> >> Why do you consider it unsuitable to ship the perl script with the kernel?
> >> Perl 5 is already documented as a build dependency in Documentation/Changes
> >
> > Do you have an example of something that does require perl to build the
> > kernel on ARM? I was under the impression that people try to avoid it
> > as much as possible in general.
> >
> > I'm personally sitting on the fence between effectively adding a new
> > kernel build dependencies or carrying the output of the perl script.
> > But if the kernel build does already require perl in practice then this
> > might tip the balance.
> >
>
> I like Russell's suggestion the most, in fact.

Me too.

> In this case, the build time requirement for Perl effectively gets
> suspended until you start making modifications to the perl script, and
> the relation between the .S and the .pl files is made explicit by the
> make rule.
>
> Should I put the cmd_perl rule in scripts/Makefile.build ? Or can I
> just keep it under arch/arm/crypto ?

To avoid possible gag reactions from the wider community I'd suggest you
keep it local for now. Unless there are already such perl usage
elsewhere in the tree in which case abstracting it to
scripts/Makefile.build first is recommended.


Nicolas

2013-10-04 18:57:30

by Nicolas Pitre

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] ARM: NEON based fast(er) AES in CBC/CTR/XTS modes

On Fri, 4 Oct 2013, Russell King - ARM Linux wrote:

> On Fri, Oct 04, 2013 at 08:41:35PM +0200, Ard Biesheuvel wrote:
> > On 4 October 2013 20:34, Nicolas Pitre <[email protected]> wrote:
> > > On Fri, 4 Oct 2013, Will Deacon wrote:
> > [...]
> > >>
> > >> Why do you consider it unsuitable to ship the perl script with the kernel?
> > >> Perl 5 is already documented as a build dependency in Documentation/Changes
> > >
> > > Do you have an example of something that does require perl to build the
> > > kernel on ARM? I was under the impression that people try to avoid it
> > > as much as possible in general.
> > >
> > > I'm personally sitting on the fence between effectively adding a new
> > > kernel build dependencies or carrying the output of the perl script.
> > > But if the kernel build does already require perl in practice then this
> > > might tip the balance.
> > >
> >
> > I like Russell's suggestion the most, in fact. In this case, the build
> > time requirement for Perl effectively gets suspended until you start
> > making modifications to the perl script, and the relation between the
> > .S and the .pl files is made explicit by the make rule.
> >
> > Should I put the cmd_perl rule in scripts/Makefile.build ? Or can I
> > just keep it under arch/arm/crypto ?
>
> Just running through the Makefiles, it seems we have a fair amount
> of stuff already using perl in various ways. So I wouldn't worry too
> much about where it's placed. It's probably something that should
> eventually end up in scripts/ at _some_ point.

BTW, Russell's opinion has precedence over what I just said.


Nicolas