Skip to contentSkip to conversation

crypto: sun8i-ce - Add AES-XTS for the H616

PATCH New Arun Iyengar 1 participant 1 message Nov 10

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 crypto: sun8i-ce - Add AES-XTS for the H616

The H616 crypto engine has a separate RAES unit (algorithm type 0x30) that does AES-ECB, AES-CBC and AES-XTS. Its XTS mode (symmetric mode 0b1001) takes the two keys back to back at the key address, the tweak at the IV address, and an xts_first/xts_last pair of flags that mark the first and the last block of a data unit. The key size field gives the size of one of the two keys: 128 or 256 bits, there is no 192-bit XTS.

Register xts(aes) for the H616: each request is one data unit, so both flags are set and the request IV is the tweak of its first block. XTS returns no IV, so the CBC write-back of the last block is skipped. Ciphertext stealing (lengths that are not a multiple of the block size) and two 192-bit keys go to the fallback, as do the requests that the existing checks already send there.

The engine is much slower at XTS than the CPU's ARMv8 AES instructions:
4 times slower for 64 KiB requests (213 against 861 MB/s), 8 times for 4 KiB and 17 times for 512 bytes. Register it below every CPU implementation of xts(aes) (priority 90), so that the CPU stays the default, for dm-crypt too, and the engine is only used when it is asked for by driver name.

The other variants get CE_ID_NOTSUPP for the new mode, so nothing changes for them.

---
The H616 crypto engine can do AES-XTS in its separate RAES unit. This patch registers xts(aes) for the H616, below the CPU implementations because the engine is slower than the ARMv8 Crypto Extensions; it stays available by driver name (xts-aes-sun8i-ce) for users who want to offload the CPU.

Testing on an Orange Pi Zero2 (H616), v7.3-based kernel with this patch (sun8i-ce is unchanged between v7.3 and cryptodev-2.6):
- the boot-time self-test of xts-aes-sun8i-ce passes, and the testmgr vectors run on the engine (debugfs request counters);
- 21 known-answer vectors (IEEE 1619 and generated, including ciphertext stealing lengths, which go to the fallback) pass, and 3000 random requests (10% with misaligned buffers) give the same result as xts-aes-ce;
- dm-crypt with capi:xts-aes-sun8i-ce-plain64, 512 and 4096-byte
sectors: 48 MiB written and read back with matching sha256, and the raw sectors decrypt with xts-aes-ce; with this priority, xts(aes) and plain aes-xts-plain64 resolve to the CPU's xts-aes-ce;
- the existing ECB/CBC ciphers, hashes and the TRNG still match their software implementations.
Throughput, engine against xts-aes-ce: 20/352 MB/s for 512-byte requests, 98/759 MB/s for 4 KiB, 213/861 MB/s for 64 KiB.

This patch was developed with Claude (Anthropic) as a
coding assistant: it investigated the problem, wrote the code and
the commit messages. I reviewed it, and it was tested on an
Orange Pi Zero2 (H616) as described above.
---
Changes in v2:
- Select CRYPTO_XTS: the xts(aes) transform allocates an xts(aes)
fallback in sun8i_ce_cipher_init(), which fails without it (found by
the Sashiko AI review).
- Link to v1: https://patch.msgid.link/[email protected]

To: Corentin Labbe <[email protected]>
To: Herbert Xu <[email protected]>
To: "David S. Miller" <[email protected]>
To: Chen-Yu Tsai <[email protected]>
To: Jernej Skrabec <[email protected]>
To: Samuel Holland <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]

---
 drivers/crypto/allwinner/Kconfig                   |   1 +
 .../crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c    | 102 +++++++++++++++++----
 drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c  |  44 +++++++--
 drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h       |  21 ++++-
 4 files changed, 142 insertions(+), 26 deletions(-)
drivers/crypto/allwinner/Kconfig +1 -0
index d86ae005fbe2..c07212ea2fba 100644
@@ -39,6 +39,7 @@ config CRYPTO_DEV_SUN8I_CE
 	select CRYPTO_ENGINE
 	select CRYPTO_ECB
 	select CRYPTO_CBC
+	select CRYPTO_XTS
 	select CRYPTO_AES
 	select CRYPTO_DES
 	depends on CRYPTO_DEV_ALLWINNER
drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c +85 -17

172 lines not on this page · raw message

drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c +37 -7

92 lines not on this page · raw message

drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h +19 -2
index 468d99bf5bf6..89689e54e5fd 100644
@@ -46,6 +46,10 @@
 
 #define CE_OP_ECB	0
 #define CE_OP_CBC	(1 << 8)
+#define CE_OP_XTS	(9 << 8)
+
+#define CE_SYM_XTS_FIRST	BIT(12)
+#define CE_SYM_XTS_LAST		BIT(13)
 
 #define CE_ALG_AES		0
 #define CE_ALG_DES		1
@@ -58,6 +62,7 @@
 #define CE_ALG_SHA512           21
 #define CE_ALG_TRNG		48
 #define CE_ALG_TRNG_V2		0x1c
+#define CE_ALG_RAES		0x30
 
 /* Used in ce_variant */
 #define CE_ID_NOTSUPP		0xFF
@@ -77,7 +82,8 @@
 
 #define CE_ID_OP_ECB	0
 #define CE_ID_OP_CBC	1
-#define CE_ID_OP_MAX	2
+#define CE_ID_OP_XTS	2
+#define CE_ID_OP_MAX	3
 
 /* Used in CE registers */
 #define CE_ERR_ALGO_NOTSUP	BIT(0)
@@ -98,6 +104,14 @@
 
 #define MAX_SG 8
 
+/*
+ * Priority of the modes that the CPU's own AES instructions run faster than
+ * the engine: below every CPU implementation of them (arm64 CE 300, NEON 250
+ * and 200, AES library 110, generic templates 100), so the CPU stays the
+ * default and the engine is used when it is asked for by driver name.
+ */
+#define CE_PRIO_BELOW_CPU	90
+
 #define CE_MAX_CLOCKS 4
 #define CE_DMA_TIMEOUT_MS	3000
 
@@ -124,7 +138,8 @@ struct ce_clock {
  *              coresponding CE_ALG_XXX value
  * @alg_hash:	list of supported hashes. for each CE_ID_ this will give the
  *              corresponding CE_ALG_XXX value
- * @op_mode:	list of supported block modes
+ * @op_mode:	list of supported block modes, CE_ID_NOTSUPP if not supported.
+ *		XTS runs on the RAES unit (algorithm CE_ALG_RAES)
  * @cipher_t_dlen_in_bytes:	Does the request size for cipher is in
  *				bytes or words
  * @hash_t_dlen_in_bytes:	Does the request size for hash is in
@@ -352,6 +367,8 @@ struct sun8i_ce_alg_template {
 
 int sun8i_ce_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			unsigned int keylen);
+int sun8i_ce_xts_setkey(struct crypto_skcipher *tfm, const u8 *key,
+			unsigned int keylen);
 int sun8i_ce_des3_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			 unsigned int keylen);
 int sun8i_ce_cipher_init(struct crypto_tfm *tfm);

---
base-commit: 82e91fe19fb838f235f7c8829afc1eb389c93bdf
change-id: 20261110-sun8i-ce-h616-xts-8e52bb3c7b36

Best regards,

Signature · 1 line
Arun Iyengar <[email protected]>