Skip to contentSkip to conversation

crypto: Adiantum support

PATCH In review Eric Biggers 3 participants 22 messages Nov 17, 2018 – Nov 30, 2018

Subsystems (9)
lore
Share & tools
lore

Eric Biggers

author maintainer
#0 lore raw

v4 cover crypto: Adiantum support

Hello,

We've been working to find a way to bring storage encryption to entry-level Android devices like the inexpensive "Android Go" devices sold in developing countries, and some smartwatches. Unfortunately, often these devices still ship with no encryption, since for cost reasons they have to use older CPUs like ARM Cortex-A7; and these CPUs lack the ARMv8 Cryptography Extensions, making AES-XTS much too slow.

We're trying to change this, since we believe encryption is for everyone, not just those who can afford it. And while it's unknown how long CPUs without AES support will be around, there will likely always be a "low end"; and in any case it's immensely valuable to provide a software-optimized cipher that doesn't depend on hardware support. Lack of hardware support should not be an excuse for no encryption.

But after an extensive search (e.g. see [1]) we were unable to find an existing cipher that simultaneously meets the very strict performance requirements on ARM processors, is secure (including having sufficient security parameters as well as sufficient cryptanalysis of any primitive(s) used), is suitable for practical use in dm-crypt and fscrypt, *and* avoids any particularly controversial primitive.

Therefore, we (well, Paul Crowley did the real work) designed a new encryption mode, Adiantum. In essence, Adiantum makes it secure to use the ChaCha stream cipher for disk encryption. Adiantum is specified by our paper here: https://eprint.iacr.org/2018/720.pdf ("Adiantum:
length-preserving encryption for entry-level processors"). Reference code and test vectors are here: https://github.com/google/adiantum.
Most of the high-level concepts of Adiantum are not new; similar existing modes include XCB, HCTR, and HCH. Adiantum and these modes are true wide-block modes (tweakable super-pseudorandom permutations), so they actually provide a stronger notion of security than XTS.

Adiantum is an improved version of our previous algorithm, HPolyC [2]. Like HPolyC, Adiantum uses XChaCha12, two passes of an ?-almost-?-universal (?A?U) hash function, and one AES-256 encryption of a single 16-byte block. On ARM Cortex-A7, on 4096-byte messages Adiantum is about 4x faster than AES-256-XTS (about 5x for decryption), and about 30% faster than Speck128/256-XTS.

Adiantum is a construction, not a primitive. Its security is reducible to that of XChaCha12 and AES-256, subject to a security bound; the proof is in Section 5 of our paper. Therefore, one need not "trust" Adiantum; they only need trust XChaCha12 and AES-256. Note that of these two primitives, AES-256 currently has the lower security margin.

Adiantum is ~20% faster than HPolyC, with no loss of security; in fact, Adiantum's security bound is slightly better than HPolyC's. It does this by choosing a faster ?A?U hash function: it still uses Poly1305's ?A?U hash function, but now a hash function from the "NH" family of hash functions is used to "compress" the message by 32x first. NH is ?AU (as shown in the UMAC paper[3]) but is over twice as fast as Poly1305. Key agility is reduced, but that's acceptable for disk encryption.

NH is also very simple, and it's easy to implement in SIMD assembly, e.g. in ARM NEON. Now, to get good performance only a SIMD implementation of NH is required, not Poly1305. Therefore, Adiantum can be easier to port to new platforms than HPolyC, despite Adiantum's slightly increased complexity. For now this patchset only includes an ARM32 NEON implementation of NH, but as a proof of concept I've also written SSE2, AVX2, and ARM64 NEON implementations of NH; see
https://github.com/google/adiantum/tree/master/benchmark/src.

This patchset adds Adiantum to Linux's crypto API, focusing on generic and ARM32 implementations. Patches 1-9 add support for XChaCha20 and XChaCha12. Patches 10-13 add NHPoly1305 support, needed for Adiantum hashing. Patch 14 adds Adiantum support as a skcipher template.

This patchset applies to cryptodev. It can also be found in git at branch "adiantum-v4" of:
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git

With this patchset, Adiantum is already usable in dm-crypt via the "capi:" cipher syntax. I'll also be adding Adiantum support to fscrypt via the patch https://patchwork.kernel.org/patch/10669339/, but I dropped it from this series for now since it will be taken through the fscrypt git tree instead. Note that in fscrypt, Adiantum will also fix an information leak in filenames encryption when filenames share a common prefix, and Adiantum's long IV support make it safe to use the same key for many files, improving performance even more.

Again, for more details please read our paper:

Adiantum: length-preserving encryption for entry-level processors
(https://eprint.iacr.org/2018/720.pdf)

References:
[1] https://www.spinics.net/lists/linux-crypto/msg33000.html
[2] https://patchwork.kernel.org/cover/10558059/
[3] https://fastcrypto.org/umac/umac_proc.pdf

Changed since v3:
- Rebase onto cryptodev because of recent ChaCha20 changes.
- Drop fscrypt patch; I'm sending it as a standalone patch.

Changed since v2:
- Simplify the generic NH implementation.
- Add patches to reduce atomic walks and disabling preemption.
- Split Poly1305 changes into two patches.
- Add tcrypt test mode for Adiantum.
- Make NEON 'chacha_permute' a function rather than a macro.
- Use .base.* style when declaring algorithms.
- Replace BUG_ON() in chacha_permute() with WARN_ON_ONCE().
- Set Adiantum instance {min,max}_keysize correctly in all cases.
- Make the Adiantum template take the nhpoly1305 driver name as optional third argument (useful for testing).

Thanks to Ard Biesheuvel for reviewing the patches.

Changed since v1:
- Replace HPolyC with Adiantum (uses a faster hash function).
- Drop ARM accelerated Poly1305.
- Add fscrypt patch.

Eric Biggers (14):
crypto: chacha20-generic - add HChaCha20 library function
crypto: chacha20-generic - don't unnecessarily use atomic walk
crypto: chacha20-generic - add XChaCha20 support
crypto: chacha20-generic - refactor to allow varying number of rounds
crypto: chacha - add XChaCha12 support
crypto: arm/chacha20 - limit the preemption-disabled section
crypto: arm/chacha20 - add XChaCha20 support
crypto: arm/chacha20 - refactor to allow varying number of rounds
crypto: arm/chacha - add XChaCha12 support
crypto: poly1305 - use structures for key and accumulator
crypto: poly1305 - add Poly1305 core API
crypto: nhpoly1305 - add NHPoly1305 support
crypto: arm/nhpoly1305 - add NEON-accelerated NHPoly1305
crypto: adiantum - add Adiantum support

 arch/arm/crypto/Kconfig                       |    7 +-
 arch/arm/crypto/Makefile                      |    6 +-
 ...hacha20-neon-core.S => chacha-neon-core.S} |   98 +-
 arch/arm/crypto/chacha-neon-glue.c            |  201 ++
 arch/arm/crypto/chacha20-neon-glue.c          |  127 -
 arch/arm/crypto/nh-neon-core.S                |  116 +
 arch/arm/crypto/nhpoly1305-neon-glue.c        |   77 +
 arch/arm64/crypto/chacha20-neon-glue.c        |   40 +-
 arch/x86/crypto/chacha20_glue.c               |   48 +-
 arch/x86/crypto/poly1305_glue.c               |   20 +-
 crypto/Kconfig                                |   46 +-
 crypto/Makefile                               |    4 +-
 crypto/adiantum.c                             |  658 ++++
 crypto/chacha20_generic.c                     |  137 -
 crypto/chacha20poly1305.c                     |   10 +-
 crypto/chacha_generic.c                       |  217 ++
 crypto/nhpoly1305.c                           |  254 ++
 crypto/poly1305_generic.c                     |  174 +-
 crypto/tcrypt.c                               |   12 +
 crypto/testmgr.c                              |   30 +
 crypto/testmgr.h                              | 2856 ++++++++++++++++-
 drivers/char/random.c                         |   51 +-
 drivers/crypto/caam/caamalg.c                 |    2 +-
 drivers/crypto/caam/caamalg_qi2.c             |    8 +-
 drivers/crypto/caam/compat.h                  |    2 +-
 include/crypto/chacha.h                       |   54 +
 include/crypto/chacha20.h                     |   28 -
 include/crypto/nhpoly1305.h                   |   74 +
 include/crypto/poly1305.h                     |   28 +-
 lib/Makefile                                  |    2 +-
 lib/{chacha20.c => chacha.c}                  |   59 +-
 31 files changed, 4931 insertions(+), 515 deletions(-)
 rename arch/arm/crypto/{chacha20-neon-core.S => chacha-neon-core.S} (90%)
 create mode 100644 arch/arm/crypto/chacha-neon-glue.c
 delete mode 100644 arch/arm/crypto/chacha20-neon-glue.c
 create mode 100644 arch/arm/crypto/nh-neon-core.S
 create mode 100644 arch/arm/crypto/nhpoly1305-neon-glue.c
 create mode 100644 crypto/adiantum.c
 delete mode 100644 crypto/chacha20_generic.c
 create mode 100644 crypto/chacha_generic.c
 create mode 100644 crypto/nhpoly1305.c
 create mode 100644 include/crypto/chacha.h
 delete mode 100644 include/crypto/chacha20.h
 create mode 100644 include/crypto/nhpoly1305.h
 rename lib/{chacha20.c => chacha.c} (58%)
Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#1 lore raw

PATCH v4 1/14 crypto: chacha20-generic - add HChaCha20 library function

From: Eric Biggers <[email protected]>

Refactor the unkeyed permutation part of chacha20_block() into its own function, then add hchacha20_block() which is the ChaCha equivalent of HSalsa20 and is an intermediate step towards XChaCha20 (see
https://cr.yp.to/snuffle/xsalsa-20081128.pdf). HChaCha20 skips the final addition of the initial state, and outputs only certain words of the state. It should not be used for streaming directly.

---
 include/crypto/chacha20.h |  2 ++
 lib/chacha20.c            | 50 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 46 insertions(+), 6 deletions(-)
include/crypto/chacha20.h +2 -0
index 2d3129442a52..56073814eef0 100644
@@ -20,6 +20,8 @@ struct chacha20_ctx {
 };
 
 void chacha20_block(u32 *state, u8 *stream);
+void hchacha20_block(const u32 *in, u32 *out);
+
 void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv);
 int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			   unsigned int keysize);
lib/chacha20.c +44 -6

72 lines not on this page · raw message

Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#2 lore raw

PATCH v4 2/14 crypto: chacha20-generic - don't unnecessarily use atomic walk

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

chacha20-generic doesn't use SIMD instructions or otherwise disable preemption, so passing atomic=true to skcipher_walk_virt() is unnecessary.

---
 crypto/chacha20_generic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
crypto/chacha20_generic.c +1 -1
index 3ae96587caf9..3529521d72a4 100644
@@ -81,7 +81,7 @@ int crypto_chacha20_crypt(struct skcipher_request *req)
 	u32 state[16];
 	int err;
 
-	err = skcipher_walk_virt(&walk, req, true);
+	err = skcipher_walk_virt(&walk, req, false);
 
 	crypto_chacha20_init(state, ctx, walk.iv);
 
Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#3 lore raw

PATCH v4 3/14 crypto: chacha20-generic - add XChaCha20 support

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

Add support for the XChaCha20 stream cipher. XChaCha20 is the application of the XSalsa20 construction
(https://cr.yp.to/snuffle/xsalsa-20081128.pdf) to ChaCha20 rather than to Salsa20. XChaCha20 extends ChaCha20's nonce length from 64 bits (or 96 bits, depending on convention) to 192 bits, while provably retaining ChaCha20's security. XChaCha20 uses the ChaCha20 permutation to map the key and first 128 nonce bits to a 256-bit subkey. Then, it does the ChaCha20 stream cipher with the subkey and remaining 64 bits of nonce.

We need XChaCha support in order to add support for the Adiantum encryption mode. Note that to meet our performance requirements, we actually plan to primarily use the variant XChaCha12. But we believe it's wise to first add XChaCha20 as a baseline with a higher security margin, in case there are any situations where it can be used. Supporting both variants is straightforward.

Since XChaCha20's subkey differs for each request, XChaCha20 can't be a template that wraps ChaCha20; that would require re-keying the underlying ChaCha20 for every request, which wouldn't be thread-safe. Instead, we make XChaCha20 its own top-level algorithm which calls the ChaCha20 streaming implementation internally.

Similar to the existing ChaCha20 implementation, we define the IV to be the nonce and stream position concatenated together. This allows users to seek to any position in the stream.

I considered splitting the code into separate chacha20-common, chacha20, and xchacha20 modules, so that chacha20 and xchacha20 could be enabled/disabled independently. However, since nearly all the code is shared anyway, I ultimately decided there would have been little benefit to the added complexity of separate modules.

---
 crypto/Kconfig            |  14 +-
 crypto/chacha20_generic.c | 120 +++++---
 crypto/testmgr.c          |   6 +
 crypto/testmgr.h          | 577 ++++++++++++++++++++++++++++++++++++++
 include/crypto/chacha20.h |  14 +-
 5 files changed, 689 insertions(+), 42 deletions(-)
crypto/Kconfig +9 -5
index 62dbd1a99fa3..75ebd1a2746c 100644
@@ -1403,18 +1403,22 @@ config CRYPTO_SALSA20
 	  Bernstein <[email protected]>. See <http://cr.yp.to/snuffle.html>
 
 config CRYPTO_CHACHA20
-	tristate "ChaCha20 cipher algorithm"
+	tristate "ChaCha20 stream cipher algorithms"
 	select CRYPTO_BLKCIPHER
 	help
-	  ChaCha20 cipher algorithm, RFC7539.
+	  The ChaCha20 and XChaCha20 stream cipher algorithms.
 
 	  ChaCha20 is a 256-bit high-speed stream cipher designed by Daniel J.
 	  Bernstein and further specified in RFC7539 for use in IETF protocols.
-	  This is the portable C implementation of ChaCha20.
-
-	  See also:
+	  This is the portable C implementation of ChaCha20.  See also:
 	  <http://cr.yp.to/chacha/chacha-20080128.pdf>
 
+	  XChaCha20 is the application of the XSalsa20 construction to ChaCha20
+	  rather than to Salsa20.  XChaCha20 extends ChaCha20's nonce length
+	  from 64 bits (or 96 bits using the RFC7539 convention) to 192 bits,
+	  while provably retaining ChaCha20's security.  See also:
+	  <https://cr.yp.to/snuffle/xsalsa-20081128.pdf>
+
 config CRYPTO_CHACHA20_X86_64
 	tristate "ChaCha20 cipher algorithm (x86_64/SSSE3/AVX2)"
 	depends on X86 && 64BIT
crypto/chacha20_generic.c +84 -36

157 lines not on this page · raw message

crypto/testmgr.c +6 -0
index 379794a259a7..11f5c8b0f4dc 100644
@@ -3576,6 +3576,12 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.suite = {
 			.hash = __VECS(aes_xcbc128_tv_template)
 		}
+	}, {
+		.alg = "xchacha20",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = __VECS(xchacha20_tv_template)
+		},
 	}, {
 		.alg = "xts(aes)",
 		.test = alg_test_skcipher,
crypto/testmgr.h +577 -0

583 lines not on this page · raw message

include/crypto/chacha20.h +13 -1
index 56073814eef0..c24b4ac03b85 100644
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Common values for the ChaCha20 algorithm
+ * Common values and helper functions for the ChaCha20 and XChaCha20 algorithms.
+ *
+ * XChaCha20 extends ChaCha20's nonce to 192 bits, while provably retaining
+ * ChaCha20's security.  Here they share the same key size, tfm context, and
+ * setkey function; only their IV size and encrypt/decrypt function differ.
  */
 
 #ifndef _CRYPTO_CHACHA20_H
@@ -10,11 +14,16 @@
 #include <linux/types.h>
 #include <linux/crypto.h>
 
+/* 32-bit stream position, then 96-bit nonce (RFC7539 convention) */
 #define CHACHA20_IV_SIZE	16
+
 #define CHACHA20_KEY_SIZE	32
 #define CHACHA20_BLOCK_SIZE	64
 #define CHACHAPOLY_IV_SIZE	12
 
+/* 192-bit nonce, then 64-bit stream position */
+#define XCHACHA20_IV_SIZE	32
+
 struct chacha20_ctx {
 	u32 key[8];
 };
@@ -23,8 +32,11 @@ void chacha20_block(u32 *state, u8 *stream);
 void hchacha20_block(const u32 *in, u32 *out);
 
 void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv);
+
 int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			   unsigned int keysize);
+
 int crypto_chacha20_crypt(struct skcipher_request *req);
+int crypto_xchacha20_crypt(struct skcipher_request *req);
 
 #endif
Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#4 lore raw

PATCH v4 4/14 crypto: chacha20-generic - refactor to allow varying number of rounds

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

In preparation for adding XChaCha12 support, rename/refactor chacha20-generic to support different numbers of rounds. The justification for needing XChaCha12 support is explained in more detail in the patch "crypto: chacha - add XChaCha12 support".

The only difference between ChaCha{8,12,20} are the number of rounds itself; all other parts of the algorithm are the same. Therefore, remove the "20" from all definitions, structures, functions, files, etc. that will be shared by all ChaCha versions.

Also make ->setkey() store the round count in the chacha_ctx (previously chacha20_ctx). The generic code then passes the round count through to chacha_block(). There will be a ->setkey() function for each explicitly allowed round count; the encrypt/decrypt functions will be the same. I decided not to do it the opposite way (same ->setkey() function for all round counts, with different encrypt/decrypt functions) because that would have required more boilerplate code in architecture-specific implementations of ChaCha and XChaCha.

---
 arch/arm/crypto/chacha20-neon-glue.c          |  40 +++----
 arch/arm64/crypto/chacha20-neon-glue.c        |  40 +++----
 arch/x86/crypto/chacha20_glue.c               |  48 ++++----
 crypto/Makefile                               |   2 +-
 crypto/chacha20poly1305.c                     |  10 +-
 .../{chacha20_generic.c => chacha_generic.c}  | 110 ++++++++++--------
 drivers/char/random.c                         |  51 ++++----
 drivers/crypto/caam/caamalg.c                 |   2 +-
 drivers/crypto/caam/caamalg_qi2.c             |   8 +-
 drivers/crypto/caam/compat.h                  |   2 +-
 include/crypto/chacha.h                       |  47 ++++++++
 include/crypto/chacha20.h                     |  42 -------
 lib/Makefile                                  |   2 +-
 lib/{chacha20.c => chacha.c}                  |  43 ++++---
 14 files changed, 232 insertions(+), 215 deletions(-)
 rename crypto/{chacha20_generic.c => chacha_generic.c} (57%)
 create mode 100644 include/crypto/chacha.h
 delete mode 100644 include/crypto/chacha20.h
 rename lib/{chacha20.c => chacha.c} (67%)
arch/arm/crypto/chacha20-neon-glue.c +20 -20
index 59a7be08e80c..7386eb1c1889 100644
@@ -19,7 +19,7 @@
  */
 
 #include <crypto/algapi.h>
-#include <crypto/chacha20.h>
+#include <crypto/chacha.h>
 #include <crypto/internal/skcipher.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -34,20 +34,20 @@ asmlinkage void chacha20_4block_xor_neon(u32 *state, u8 *dst, const u8 *src);
 static void chacha20_doneon(u32 *state, u8 *dst, const u8 *src,
 			    unsigned int bytes)
 {
-	u8 buf[CHACHA20_BLOCK_SIZE];
+	u8 buf[CHACHA_BLOCK_SIZE];
 
-	while (bytes >= CHACHA20_BLOCK_SIZE * 4) {
+	while (bytes >= CHACHA_BLOCK_SIZE * 4) {
 		chacha20_4block_xor_neon(state, dst, src);
-		bytes -= CHACHA20_BLOCK_SIZE * 4;
-		src += CHACHA20_BLOCK_SIZE * 4;
-		dst += CHACHA20_BLOCK_SIZE * 4;
+		bytes -= CHACHA_BLOCK_SIZE * 4;
+		src += CHACHA_BLOCK_SIZE * 4;
+		dst += CHACHA_BLOCK_SIZE * 4;
 		state[12] += 4;
 	}
-	while (bytes >= CHACHA20_BLOCK_SIZE) {
+	while (bytes >= CHACHA_BLOCK_SIZE) {
 		chacha20_block_xor_neon(state, dst, src);
-		bytes -= CHACHA20_BLOCK_SIZE;
-		src += CHACHA20_BLOCK_SIZE;
-		dst += CHACHA20_BLOCK_SIZE;
+		bytes -= CHACHA_BLOCK_SIZE;
+		src += CHACHA_BLOCK_SIZE;
+		dst += CHACHA_BLOCK_SIZE;
 		state[12]++;
 	}
 	if (bytes) {
@@ -60,17 +60,17 @@ static void chacha20_doneon(u32 *state, u8 *dst, const u8 *src,
 static int chacha20_neon(struct skcipher_request *req)
 {
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
-	struct chacha20_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
 	struct skcipher_walk walk;
 	u32 state[16];
 	int err;
 
-	if (req->cryptlen <= CHACHA20_BLOCK_SIZE || !may_use_simd())
-		return crypto_chacha20_crypt(req);
+	if (req->cryptlen <= CHACHA_BLOCK_SIZE || !may_use_simd())
+		return crypto_chacha_crypt(req);
 
 	err = skcipher_walk_virt(&walk, req, true);
 
-	crypto_chacha20_init(state, ctx, walk.iv);
+	crypto_chacha_init(state, ctx, walk.iv);
 
 	kernel_neon_begin();
 	while (walk.nbytes > 0) {
@@ -93,14 +93,14 @@ static struct skcipher_alg alg = {
 	.base.cra_driver_name	= "chacha20-neon",
 	.base.cra_priority	= 300,
 	.base.cra_blocksize	= 1,
-	.base.cra_ctxsize	= sizeof(struct chacha20_ctx),
+	.base.cra_ctxsize	= sizeof(struct chacha_ctx),
 	.base.cra_module	= THIS_MODULE,
 
-	.min_keysize		= CHACHA20_KEY_SIZE,
-	.max_keysize		= CHACHA20_KEY_SIZE,
-	.ivsize			= CHACHA20_IV_SIZE,
-	.chunksize		= CHACHA20_BLOCK_SIZE,
-	.walksize		= 4 * CHACHA20_BLOCK_SIZE,
+	.min_keysize		= CHACHA_KEY_SIZE,
+	.max_keysize		= CHACHA_KEY_SIZE,
+	.ivsize			= CHACHA_IV_SIZE,
+	.chunksize		= CHACHA_BLOCK_SIZE,
+	.walksize		= 4 * CHACHA_BLOCK_SIZE,
 	.setkey			= crypto_chacha20_setkey,
 	.encrypt		= chacha20_neon,
 	.decrypt		= chacha20_neon,
arch/arm64/crypto/chacha20-neon-glue.c +20 -20
index 727579c93ded..96e0cfb8c3f5 100644
@@ -19,7 +19,7 @@
  */
 
 #include <crypto/algapi.h>
-#include <crypto/chacha20.h>
+#include <crypto/chacha.h>
 #include <crypto/internal/skcipher.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -34,15 +34,15 @@ asmlinkage void chacha20_4block_xor_neon(u32 *state, u8 *dst, const u8 *src);
 static void chacha20_doneon(u32 *state, u8 *dst, const u8 *src,
 			    unsigned int bytes)
 {
-	u8 buf[CHACHA20_BLOCK_SIZE];
+	u8 buf[CHACHA_BLOCK_SIZE];
 
-	while (bytes >= CHACHA20_BLOCK_SIZE * 4) {
+	while (bytes >= CHACHA_BLOCK_SIZE * 4) {
 		kernel_neon_begin();
 		chacha20_4block_xor_neon(state, dst, src);
 		kernel_neon_end();
-		bytes -= CHACHA20_BLOCK_SIZE * 4;
-		src += CHACHA20_BLOCK_SIZE * 4;
-		dst += CHACHA20_BLOCK_SIZE * 4;
+		bytes -= CHACHA_BLOCK_SIZE * 4;
+		src += CHACHA_BLOCK_SIZE * 4;
+		dst += CHACHA_BLOCK_SIZE * 4;
 		state[12] += 4;
 	}
 
@@ -50,11 +50,11 @@ static void chacha20_doneon(u32 *state, u8 *dst, const u8 *src,
 		return;
 
 	kernel_neon_begin();
-	while (bytes >= CHACHA20_BLOCK_SIZE) {
+	while (bytes >= CHACHA_BLOCK_SIZE) {
 		chacha20_block_xor_neon(state, dst, src);
-		bytes -= CHACHA20_BLOCK_SIZE;
-		src += CHACHA20_BLOCK_SIZE;
-		dst += CHACHA20_BLOCK_SIZE;
+		bytes -= CHACHA_BLOCK_SIZE;
+		src += CHACHA_BLOCK_SIZE;
+		dst += CHACHA_BLOCK_SIZE;
 		state[12]++;
 	}
 	if (bytes) {
@@ -68,17 +68,17 @@ static void chacha20_doneon(u32 *state, u8 *dst, const u8 *src,
 static int chacha20_neon(struct skcipher_request *req)
 {
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
-	struct chacha20_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
 	struct skcipher_walk walk;
 	u32 state[16];
 	int err;
 
-	if (!may_use_simd() || req->cryptlen <= CHACHA20_BLOCK_SIZE)
-		return crypto_chacha20_crypt(req);
+	if (!may_use_simd() || req->cryptlen <= CHACHA_BLOCK_SIZE)
+		return crypto_chacha_crypt(req);
 
 	err = skcipher_walk_virt(&walk, req, false);
 
-	crypto_chacha20_init(state, ctx, walk.iv);
+	crypto_chacha_init(state, ctx, walk.iv);
 
 	while (walk.nbytes > 0) {
 		unsigned int nbytes = walk.nbytes;
@@ -99,14 +99,14 @@ static struct skcipher_alg alg = {
 	.base.cra_driver_name	= "chacha20-neon",
 	.base.cra_priority	= 300,
 	.base.cra_blocksize	= 1,
-	.base.cra_ctxsize	= sizeof(struct chacha20_ctx),
+	.base.cra_ctxsize	= sizeof(struct chacha_ctx),
 	.base.cra_module	= THIS_MODULE,
 
-	.min_keysize		= CHACHA20_KEY_SIZE,
-	.max_keysize		= CHACHA20_KEY_SIZE,
-	.ivsize			= CHACHA20_IV_SIZE,
-	.chunksize		= CHACHA20_BLOCK_SIZE,
-	.walksize		= 4 * CHACHA20_BLOCK_SIZE,
+	.min_keysize		= CHACHA_KEY_SIZE,
+	.max_keysize		= CHACHA_KEY_SIZE,
+	.ivsize			= CHACHA_IV_SIZE,
+	.chunksize		= CHACHA_BLOCK_SIZE,
+	.walksize		= 4 * CHACHA_BLOCK_SIZE,
 	.setkey			= crypto_chacha20_setkey,
 	.encrypt		= chacha20_neon,
 	.decrypt		= chacha20_neon,
arch/x86/crypto/chacha20_glue.c +24 -24

109 lines not on this page · raw message

crypto/Makefile +1 -1
index abbd86fdbad2..102e8525814f 100644
@@ -117,7 +117,7 @@ obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o
 obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o
 obj-$(CONFIG_CRYPTO_SEED) += seed.o
 obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o
-obj-$(CONFIG_CRYPTO_CHACHA20) += chacha20_generic.o
+obj-$(CONFIG_CRYPTO_CHACHA20) += chacha_generic.o
 obj-$(CONFIG_CRYPTO_POLY1305) += poly1305_generic.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
crypto/chacha20poly1305.c +5 -5
index f9dd5453046a..fef11446ab1b 100644
@@ -13,7 +13,7 @@
 #include <crypto/internal/hash.h>
 #include <crypto/internal/skcipher.h>
 #include <crypto/scatterwalk.h>
-#include <crypto/chacha20.h>
+#include <crypto/chacha.h>
 #include <crypto/poly1305.h>
 #include <linux/err.h>
 #include <linux/init.h>
@@ -49,7 +49,7 @@ struct poly_req {
 };
 
 struct chacha_req {
-	u8 iv[CHACHA20_IV_SIZE];
+	u8 iv[CHACHA_IV_SIZE];
 	struct scatterlist src[1];
 	struct skcipher_request req; /* must be last member */
 };
@@ -89,7 +89,7 @@ static void chacha_iv(u8 *iv, struct aead_request *req, u32 icb)
 	memcpy(iv, &leicb, sizeof(leicb));
 	memcpy(iv + sizeof(leicb), ctx->salt, ctx->saltlen);
 	memcpy(iv + sizeof(leicb) + ctx->saltlen, req->iv,
-	       CHACHA20_IV_SIZE - sizeof(leicb) - ctx->saltlen);
+	       CHACHA_IV_SIZE - sizeof(leicb) - ctx->saltlen);
 }
 
 static int poly_verify_tag(struct aead_request *req)
@@ -492,7 +492,7 @@ static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
 	struct chachapoly_ctx *ctx = crypto_aead_ctx(aead);
 	int err;
 
-	if (keylen != ctx->saltlen + CHACHA20_KEY_SIZE)
+	if (keylen != ctx->saltlen + CHACHA_KEY_SIZE)
 		return -EINVAL;
 
 	keylen -= ctx->saltlen;
@@ -637,7 +637,7 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
 
 	err = -EINVAL;
 	/* Need 16-byte IV size, including Initial Block Counter value */
-	if (crypto_skcipher_alg_ivsize(chacha) != CHACHA20_IV_SIZE)
+	if (crypto_skcipher_alg_ivsize(chacha) != CHACHA_IV_SIZE)
 		goto out_drop_chacha;
 	/* Not a stream cipher? */
 	if (chacha->base.cra_blocksize != 1)
crypto/chacha_generic.c renamed from crypto/chacha20_generic.c +59 -51

217 lines not on this page · raw message

drivers/char/random.c +25 -26

158 lines not on this page · raw message

drivers/crypto/caam/caamalg.c +1 -1
index 523565ce0060..92e593e2069a 100644
@@ -559,7 +559,7 @@ static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
 	unsigned int ivsize = crypto_aead_ivsize(aead);
 	unsigned int saltlen = CHACHAPOLY_IV_SIZE - ivsize;
 
-	if (keylen != CHACHA20_KEY_SIZE + saltlen) {
+	if (keylen != CHACHA_KEY_SIZE + saltlen) {
 		crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
drivers/crypto/caam/caamalg_qi2.c +4 -4
index 2598640aa98b..425d5d974613 100644
@@ -591,7 +591,7 @@ static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
 	unsigned int ivsize = crypto_aead_ivsize(aead);
 	unsigned int saltlen = CHACHAPOLY_IV_SIZE - ivsize;
 
-	if (keylen != CHACHA20_KEY_SIZE + saltlen) {
+	if (keylen != CHACHA_KEY_SIZE + saltlen) {
 		crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
@@ -1577,9 +1577,9 @@ static struct caam_skcipher_alg driver_algs[] = {
 			.setkey = skcipher_setkey,
 			.encrypt = skcipher_encrypt,
 			.decrypt = skcipher_decrypt,
-			.min_keysize = CHACHA20_KEY_SIZE,
-			.max_keysize = CHACHA20_KEY_SIZE,
-			.ivsize = CHACHA20_IV_SIZE,
+			.min_keysize = CHACHA_KEY_SIZE,
+			.max_keysize = CHACHA_KEY_SIZE,
+			.ivsize = CHACHA_IV_SIZE,
 		},
 		.caam.class1_alg_type = OP_ALG_ALGSEL_CHACHA20,
 	},
drivers/crypto/caam/compat.h +1 -1
index 8bde903f9f4a..87d9efe4c7aa 100644
@@ -36,7 +36,7 @@
 #include <crypto/gcm.h>
 #include <crypto/sha.h>
 #include <crypto/md5.h>
-#include <crypto/chacha20.h>
+#include <crypto/chacha.h>
 #include <crypto/poly1305.h>
 #include <crypto/internal/aead.h>
 #include <crypto/authenc.h>
include/crypto/chacha.h new file +47 -0

47 lines not on this page · raw message

include/crypto/chacha20.h deleted +0 -42

42 lines not on this page · raw message

lib/Makefile +1 -1
index db06d1237898..4c2b6fc5cde9 100644
@@ -20,7 +20,7 @@ KCOV_INSTRUMENT_dynamic_debug.o := n
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
 	 rbtree.o radix-tree.o timerqueue.o xarray.o \
 	 idr.o int_sqrt.o extable.o \
-	 sha1.o chacha20.o irq_regs.o argv_split.o \
+	 sha1.o chacha.o irq_regs.o argv_split.o \
 	 flex_proportions.o ratelimit.o show_mem.o \
 	 is_single_threaded.o plist.o decompress.o kobject_uevent.o \
 	 earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
lib/chacha.c renamed from lib/chacha20.c +24 -19

91 lines not on this page · raw message

Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#5 lore raw

PATCH v4 5/14 crypto: chacha - add XChaCha12 support

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

Now that the generic implementation of ChaCha20 has been refactored to allow varying the number of rounds, add support for XChaCha12, which is the XSalsa construction applied to ChaCha12. ChaCha12 is one of the three ciphers specified by the original ChaCha paper
(https://cr.yp.to/chacha/chacha-20080128.pdf: "ChaCha, a variant of Salsa20"), alongside ChaCha8 and ChaCha20. ChaCha12 is faster than ChaCha20 but has a lower, but still large, security margin.

We need XChaCha12 support so that it can be used in the Adiantum encryption mode, which enables disk/file encryption on low-end mobile devices where AES-XTS is too slow as the CPUs lack AES instructions.

We'd prefer XChaCha20 (the more popular variant), but it's too slow on some of our target devices, so at least in some cases we do need the XChaCha12-based version. In more detail, the problem is that Adiantum is still much slower than we're happy with, and encryption still has a quite noticeable effect on the feel of low-end devices. Users and vendors push back hard against encryption that degrades the user experience, which always risks encryption being disabled entirely. So we need to choose the fastest option that gives us a solid margin of security, and here that's XChaCha12. The best known attack on ChaCha breaks only 7 rounds and has 2^235 time complexity, so ChaCha12's security margin is still better than AES-256's. Much has been learned about cryptanalysis of ARX ciphers since Salsa20 was originally designed in 2005, and it now seems we can be comfortable with a smaller number of rounds. The eSTREAM project also suggests the 12-round version of Salsa20 as providing the best balance among the different variants:
combining very good performance with a "comfortable margin of security".

Note that it would be trivial to add vanilla ChaCha12 in addition to XChaCha12. However, it's unneeded for now and therefore is omitted.

As discussed in the patch that introduced XChaCha20 support, I considered splitting the code into separate chacha-common, chacha20, xchacha20, and xchacha12 modules, so that these algorithms could be enabled/disabled independently. However, since nearly all the code is shared anyway, I ultimately decided there would have been little benefit to the added complexity.

---
 crypto/Kconfig          |   8 +-
 crypto/chacha_generic.c |  26 +-
 crypto/testmgr.c        |   6 +
 crypto/testmgr.h        | 578 ++++++++++++++++++++++++++++++++++++++++
 include/crypto/chacha.h |   7 +
 lib/chacha.c            |   6 +-
 6 files changed, 625 insertions(+), 6 deletions(-)
crypto/Kconfig +6 -2
index 75ebd1a2746c..4431c0db56b7 100644
@@ -1403,10 +1403,10 @@ config CRYPTO_SALSA20
 	  Bernstein <[email protected]>. See <http://cr.yp.to/snuffle.html>
 
 config CRYPTO_CHACHA20
-	tristate "ChaCha20 stream cipher algorithms"
+	tristate "ChaCha stream cipher algorithms"
 	select CRYPTO_BLKCIPHER
 	help
-	  The ChaCha20 and XChaCha20 stream cipher algorithms.
+	  The ChaCha20, XChaCha20, and XChaCha12 stream cipher algorithms.
 
 	  ChaCha20 is a 256-bit high-speed stream cipher designed by Daniel J.
 	  Bernstein and further specified in RFC7539 for use in IETF protocols.
@@ -1419,6 +1419,10 @@ config CRYPTO_CHACHA20
 	  while provably retaining ChaCha20's security.  See also:
 	  <https://cr.yp.to/snuffle/xsalsa-20081128.pdf>
 
+	  XChaCha12 is XChaCha20 reduced to 12 rounds, with correspondingly
+	  reduced security margin but increased performance.  It can be needed
+	  in some performance-sensitive scenarios.
+
 config CRYPTO_CHACHA20_X86_64
 	tristate "ChaCha20 cipher algorithm (x86_64/SSSE3/AVX2)"
 	depends on X86 && 64BIT
crypto/chacha_generic.c +25 -1
index 438f15a14054..35b583101f4f 100644
@@ -1,5 +1,5 @@
 /*
- * ChaCha20 (RFC7539) and XChaCha20 stream cipher algorithms
+ * ChaCha and XChaCha stream ciphers, including ChaCha20 (RFC7539)
  *
  * Copyright (C) 2015 Martin Willi
  * Copyright (C) 2018 Google LLC
@@ -106,6 +106,13 @@ int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
 }
 EXPORT_SYMBOL_GPL(crypto_chacha20_setkey);
 
+int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
+			   unsigned int keysize)
+{
+	return chacha_setkey(tfm, key, keysize, 12);
+}
+EXPORT_SYMBOL_GPL(crypto_chacha12_setkey);
+
 int crypto_chacha_crypt(struct skcipher_request *req)
 {
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
@@ -168,6 +175,21 @@ static struct skcipher_alg algs[] = {
 		.setkey			= crypto_chacha20_setkey,
 		.encrypt		= crypto_xchacha_crypt,
 		.decrypt		= crypto_xchacha_crypt,
+	}, {
+		.base.cra_name		= "xchacha12",
+		.base.cra_driver_name	= "xchacha12-generic",
+		.base.cra_priority	= 100,
+		.base.cra_blocksize	= 1,
+		.base.cra_ctxsize	= sizeof(struct chacha_ctx),
+		.base.cra_module	= THIS_MODULE,
+
+		.min_keysize		= CHACHA_KEY_SIZE,
+		.max_keysize		= CHACHA_KEY_SIZE,
+		.ivsize			= XCHACHA_IV_SIZE,
+		.chunksize		= CHACHA_BLOCK_SIZE,
+		.setkey			= crypto_chacha12_setkey,
+		.encrypt		= crypto_xchacha_crypt,
+		.decrypt		= crypto_xchacha_crypt,
 	}
 };
 
@@ -191,3 +213,5 @@ MODULE_ALIAS_CRYPTO("chacha20");
 MODULE_ALIAS_CRYPTO("chacha20-generic");
 MODULE_ALIAS_CRYPTO("xchacha20");
 MODULE_ALIAS_CRYPTO("xchacha20-generic");
+MODULE_ALIAS_CRYPTO("xchacha12");
+MODULE_ALIAS_CRYPTO("xchacha12-generic");
crypto/testmgr.c +6 -0
index 11f5c8b0f4dc..6ff60c3745f1 100644
@@ -3576,6 +3576,12 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.suite = {
 			.hash = __VECS(aes_xcbc128_tv_template)
 		}
+	}, {
+		.alg = "xchacha12",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = __VECS(xchacha12_tv_template)
+		},
 	}, {
 		.alg = "xchacha20",
 		.test = alg_test_skcipher,
crypto/testmgr.h +578 -0

584 lines not on this page · raw message

include/crypto/chacha.h +7 -0
index b722a23e54bb..1fc70a69d550 100644
@@ -5,6 +5,11 @@
  * XChaCha extends ChaCha's nonce to 192 bits, while provably retaining ChaCha's
  * security.  Here they share the same key size, tfm context, and setkey
  * function; only their IV size and encrypt/decrypt function differ.
+ *
+ * The ChaCha paper specifies 20, 12, and 8-round variants.  In general, it is
+ * recommended to use the 20-round variant ChaCha20.  However, the other
+ * variants can be needed in some performance-sensitive scenarios.  The generic
+ * ChaCha code currently allows only the 20 and 12-round variants.
  */
 
 #ifndef _CRYPTO_CHACHA_H
@@ -40,6 +45,8 @@ void crypto_chacha_init(u32 *state, struct chacha_ctx *ctx, u8 *iv);
 
 int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			   unsigned int keysize);
+int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key,
+			   unsigned int keysize);
 
 int crypto_chacha_crypt(struct skcipher_request *req);
 int crypto_xchacha_crypt(struct skcipher_request *req);
lib/chacha.c +3 -3
index 1bdc688c18df..a46d2832dbab 100644
@@ -21,7 +21,7 @@ static void chacha_permute(u32 *x, int nrounds)
 	int i;
 
 	/* whitelist the allowed round counts */
-	WARN_ON_ONCE(nrounds != 20);
+	WARN_ON_ONCE(nrounds != 20 && nrounds != 12);
 
 	for (i = 0; i < nrounds; i += 2) {
 		x[0]  += x[4];    x[12] = rol32(x[12] ^ x[0],  16);
@@ -70,7 +70,7 @@ static void chacha_permute(u32 *x, int nrounds)
  * chacha_block - generate one keystream block and increment block counter
  * @state: input state matrix (16 32-bit words)
  * @stream: output keystream block (64 bytes)
- * @nrounds: number of rounds (currently must be 20)
+ * @nrounds: number of rounds (20 or 12; 20 is recommended)
  *
  * This is the ChaCha core, a function from 64-byte strings to 64-byte strings.
  * The caller has already converted the endianness of the input.  This function
@@ -96,7 +96,7 @@ EXPORT_SYMBOL(chacha_block);
  * hchacha_block - abbreviated ChaCha core, for XChaCha
  * @in: input state matrix (16 32-bit words)
  * @out: output (8 32-bit words)
- * @nrounds: number of rounds (currently must be 20)
+ * @nrounds: number of rounds (20 or 12; 20 is recommended)
  *
  * HChaCha is the ChaCha equivalent of HSalsa and is an intermediate step
  * towards XChaCha (see https://cr.yp.to/snuffle/xsalsa-20081128.pdf).  HChaCha
Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#6 lore raw

PATCH v4 6/14 crypto: arm/chacha20 - limit the preemption-disabled section

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

To improve responsivesess, disable preemption for each step of the walk (which is at most PAGE_SIZE) rather than for the entire encryption/decryption operation.

---
 arch/arm/crypto/chacha20-neon-glue.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
arch/arm/crypto/chacha20-neon-glue.c +3 -3
index 7386eb1c1889..2bc035cb8f23 100644
@@ -68,22 +68,22 @@ static int chacha20_neon(struct skcipher_request *req)
 	if (req->cryptlen <= CHACHA_BLOCK_SIZE || !may_use_simd())
 		return crypto_chacha_crypt(req);
 
-	err = skcipher_walk_virt(&walk, req, true);
+	err = skcipher_walk_virt(&walk, req, false);
 
 	crypto_chacha_init(state, ctx, walk.iv);
 
-	kernel_neon_begin();
 	while (walk.nbytes > 0) {
 		unsigned int nbytes = walk.nbytes;
 
 		if (nbytes < walk.total)
 			nbytes = round_down(nbytes, walk.stride);
 
+		kernel_neon_begin();
 		chacha20_doneon(state, walk.dst.virt.addr, walk.src.virt.addr,
 				nbytes);
+		kernel_neon_end();
 		err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
 	}
-	kernel_neon_end();
 
 	return err;
 }
Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#7 lore raw

PATCH v4 7/14 crypto: arm/chacha20 - add XChaCha20 support

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

Add an XChaCha20 implementation that is hooked up to the ARM NEON implementation of ChaCha20. This is needed for use in the Adiantum encryption mode; see the generic code patch,
"crypto: chacha20-generic - add XChaCha20 support", for more details.

We also update the NEON code to support HChaCha20 on one block, so we can use that in XChaCha20 rather than calling the generic HChaCha20. This required factoring the permutation out into its own macro.

---
 arch/arm/crypto/Kconfig              |   2 +-
 arch/arm/crypto/chacha20-neon-core.S |  70 ++++++++++++------
 arch/arm/crypto/chacha20-neon-glue.c | 103 ++++++++++++++++++++-------
 3 files changed, 126 insertions(+), 49 deletions(-)
arch/arm/crypto/Kconfig +1 -1
index 0473a8f68389..a08759c32cb9 100644
@@ -126,7 +126,7 @@ config CRYPTO_CRC32_ARM_CE
 	select CRYPTO_HASH
 
 config CRYPTO_CHACHA20_NEON
-	tristate "NEON accelerated ChaCha20 symmetric cipher"
+	tristate "NEON accelerated ChaCha20 stream cipher algorithms"
 	depends on KERNEL_MODE_NEON
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_CHACHA20
arch/arm/crypto/chacha20-neon-core.S +48 -22

90 lines not on this page · raw message

arch/arm/crypto/chacha20-neon-glue.c +77 -26

145 lines not on this page · raw message

Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#8 lore raw

PATCH v4 8/14 crypto: arm/chacha20 - refactor to allow varying number of rounds

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

In preparation for adding XChaCha12 support, rename/refactor the NEON implementation of ChaCha20 to support different numbers of rounds.

---
 arch/arm/crypto/Makefile                      |  4 +-
 ...hacha20-neon-core.S => chacha-neon-core.S} | 44 ++++++++-------
 ...hacha20-neon-glue.c => chacha-neon-glue.c} | 56 ++++++++++---------
 3 files changed, 56 insertions(+), 48 deletions(-)
 rename arch/arm/crypto/{chacha20-neon-core.S => chacha-neon-core.S} (94%)
 rename arch/arm/crypto/{chacha20-neon-glue.c => chacha-neon-glue.c} (72%)
arch/arm/crypto/Makefile +2 -2
index bd5bceef0605..005482ff9504 100644
@@ -9,7 +9,7 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
 obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
 obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
 obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o
-obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha20-neon.o
+obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
 
 ce-obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
 ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
@@ -52,7 +52,7 @@ aes-arm-ce-y	:= aes-ce-core.o aes-ce-glue.o
 ghash-arm-ce-y	:= ghash-ce-core.o ghash-ce-glue.o
 crct10dif-arm-ce-y	:= crct10dif-ce-core.o crct10dif-ce-glue.o
 crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o
-chacha20-neon-y := chacha20-neon-core.o chacha20-neon-glue.o
+chacha-neon-y := chacha-neon-core.o chacha-neon-glue.o
 
 ifdef REGENERATE_ARM_CRYPTO
 quiet_cmd_perl = PERL    $@
arch/arm/crypto/chacha-neon-core.S renamed from arch/arm/crypto/chacha20-neon-core.S +24 -20

136 lines not on this page · raw message

arch/arm/crypto/chacha-neon-glue.c renamed from arch/arm/crypto/chacha20-neon-glue.c +30 -26

138 lines not on this page · raw message

Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#9 lore raw

PATCH v4 9/14 crypto: arm/chacha - add XChaCha12 support

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

Now that the 32-bit ARM NEON implementation of ChaCha20 and XChaCha20 has been refactored to support varying the number of rounds, add support for XChaCha12. This is identical to XChaCha20 except for the number of rounds, which is 12 instead of 20.

XChaCha12 is faster than XChaCha20 but has a lower security margin, though still greater than AES-256's since the best known attacks make it through only 7 rounds. See the patch "crypto: chacha - add XChaCha12 support" for more details about why we need XChaCha12 support.

---
 arch/arm/crypto/Kconfig            |  2 +-
 arch/arm/crypto/chacha-neon-glue.c | 21 ++++++++++++++++++++-
 2 files changed, 21 insertions(+), 2 deletions(-)
arch/arm/crypto/Kconfig +1 -1
index a08759c32cb9..59c674cf08ef 100644
@@ -126,7 +126,7 @@ config CRYPTO_CRC32_ARM_CE
 	select CRYPTO_HASH
 
 config CRYPTO_CHACHA20_NEON
-	tristate "NEON accelerated ChaCha20 stream cipher algorithms"
+	tristate "NEON accelerated ChaCha stream cipher algorithms"
 	depends on KERNEL_MODE_NEON
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_CHACHA20
arch/arm/crypto/chacha-neon-glue.c +20 -1
index 385557d38634..9d6fda81986d 100644
@@ -1,5 +1,6 @@
 /*
- * ChaCha20 (RFC7539) and XChaCha20 stream ciphers, NEON accelerated
+ * ARM NEON accelerated ChaCha and XChaCha stream ciphers,
+ * including ChaCha20 (RFC7539)
  *
  * Copyright (C) 2016 Linaro, Ltd. <[email protected]>
  *
@@ -154,6 +155,22 @@ static struct skcipher_alg algs[] = {
 		.setkey			= crypto_chacha20_setkey,
 		.encrypt		= xchacha_neon,
 		.decrypt		= xchacha_neon,
+	}, {
+		.base.cra_name		= "xchacha12",
+		.base.cra_driver_name	= "xchacha12-neon",
+		.base.cra_priority	= 300,
+		.base.cra_blocksize	= 1,
+		.base.cra_ctxsize	= sizeof(struct chacha_ctx),
+		.base.cra_module	= THIS_MODULE,
+
+		.min_keysize		= CHACHA_KEY_SIZE,
+		.max_keysize		= CHACHA_KEY_SIZE,
+		.ivsize			= XCHACHA_IV_SIZE,
+		.chunksize		= CHACHA_BLOCK_SIZE,
+		.walksize		= 4 * CHACHA_BLOCK_SIZE,
+		.setkey			= crypto_chacha12_setkey,
+		.encrypt		= xchacha_neon,
+		.decrypt		= xchacha_neon,
 	}
 };
 
@@ -180,3 +197,5 @@ MODULE_ALIAS_CRYPTO("chacha20");
 MODULE_ALIAS_CRYPTO("chacha20-neon");
 MODULE_ALIAS_CRYPTO("xchacha20");
 MODULE_ALIAS_CRYPTO("xchacha20-neon");
+MODULE_ALIAS_CRYPTO("xchacha12");
+MODULE_ALIAS_CRYPTO("xchacha12-neon");
Signature · 1 line
2.19.1.1215.g8438c0b245-goog
author maintainer
#10 lore raw

PATCH v4 10/14 crypto: poly1305 - use structures for key and accumulator

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

In preparation for exposing a low-level Poly1305 API which implements the ?-almost-?-universal (?A?U) hash function underlying the Poly1305 MAC and supports block-aligned inputs only, create structures poly1305_key and poly1305_state which hold the limbs of the Poly1305 "r" key and accumulator, respectively.

These structures could actually have the same type (e.g. poly1305_val), but different types are preferable, to prevent misuse.

---
 arch/x86/crypto/poly1305_glue.c | 20 +++++++------
 crypto/poly1305_generic.c       | 52 ++++++++++++++++-----------------
 include/crypto/poly1305.h       | 12 ++++++--
 3 files changed, 47 insertions(+), 37 deletions(-)
arch/x86/crypto/poly1305_glue.c +11 -9
index f012b7e28ad1..88cc01506c84 100644
@@ -83,35 +83,37 @@ static unsigned int poly1305_simd_blocks(struct poly1305_desc_ctx *dctx,
 	if (poly1305_use_avx2 && srclen >= POLY1305_BLOCK_SIZE * 4) {
 		if (unlikely(!sctx->wset)) {
 			if (!sctx->uset) {
-				memcpy(sctx->u, dctx->r, sizeof(sctx->u));
-				poly1305_simd_mult(sctx->u, dctx->r);
+				memcpy(sctx->u, dctx->r.r, sizeof(sctx->u));
+				poly1305_simd_mult(sctx->u, dctx->r.r);
 				sctx->uset = true;
 			}
 			memcpy(sctx->u + 5, sctx->u, sizeof(sctx->u));
-			poly1305_simd_mult(sctx->u + 5, dctx->r);
+			poly1305_simd_mult(sctx->u + 5, dctx->r.r);
 			memcpy(sctx->u + 10, sctx->u + 5, sizeof(sctx->u));
-			poly1305_simd_mult(sctx->u + 10, dctx->r);
+			poly1305_simd_mult(sctx->u + 10, dctx->r.r);
 			sctx->wset = true;
 		}
 		blocks = srclen / (POLY1305_BLOCK_SIZE * 4);
-		poly1305_4block_avx2(dctx->h, src, dctx->r, blocks, sctx->u);
+		poly1305_4block_avx2(dctx->h.h, src, dctx->r.r, blocks,
+				     sctx->u);
 		src += POLY1305_BLOCK_SIZE * 4 * blocks;
 		srclen -= POLY1305_BLOCK_SIZE * 4 * blocks;
 	}
 #endif
 	if (likely(srclen >= POLY1305_BLOCK_SIZE * 2)) {
 		if (unlikely(!sctx->uset)) {
-			memcpy(sctx->u, dctx->r, sizeof(sctx->u));
-			poly1305_simd_mult(sctx->u, dctx->r);
+			memcpy(sctx->u, dctx->r.r, sizeof(sctx->u));
+			poly1305_simd_mult(sctx->u, dctx->r.r);
 			sctx->uset = true;
 		}
 		blocks = srclen / (POLY1305_BLOCK_SIZE * 2);
-		poly1305_2block_sse2(dctx->h, src, dctx->r, blocks, sctx->u);
+		poly1305_2block_sse2(dctx->h.h, src, dctx->r.r, blocks,
+				     sctx->u);
 		src += POLY1305_BLOCK_SIZE * 2 * blocks;
 		srclen -= POLY1305_BLOCK_SIZE * 2 * blocks;
 	}
 	if (srclen >= POLY1305_BLOCK_SIZE) {
-		poly1305_block_sse2(dctx->h, src, dctx->r, 1);
+		poly1305_block_sse2(dctx->h.h, src, dctx->r.r, 1);
 		srclen -= POLY1305_BLOCK_SIZE;
 	}
 	return srclen;
crypto/poly1305_generic.c +26 -26

88 lines not on this page · raw message

include/crypto/poly1305.h +10 -2
index f718a19da82f..493244c46664 100644
@@ -13,13 +13,21 @@
 #define POLY1305_KEY_SIZE	32
 #define POLY1305_DIGEST_SIZE	16
 
+struct poly1305_key {
+	u32 r[5];	/* key, base 2^26 */
+};
+
+struct poly1305_state {
+	u32 h[5];	/* accumulator, base 2^26 */
+};
+
 struct poly1305_desc_ctx {
 	/* key */
-	u32 r[5];
+	struct poly1305_key r;
 	/* finalize key */
 	u32 s[4];
 	/* accumulator */
-	u32 h[5];
+	struct poly1305_state h;
 	/* partial buffer */
 	u8 buf[POLY1305_BLOCK_SIZE];
 	/* bytes used in partial buffer */
Signature · 1 line
2.19.1.1215.g8438c0b245-goog
Acked-by on v4 10/14
#11 lore raw

Re: [PATCH v4 10/14] crypto: poly1305 - use structures for key and accumulator

Quoted 9 lines · Eric Biggers

From: Eric Biggers <[email protected]>

In preparation for exposing a low-level Poly1305 API which implements the ?-almost-?-universal (?A?U) hash function underlying the Poly1305 MAC and supports block-aligned inputs only, create structures poly1305_key and poly1305_state which hold the limbs of the Poly1305 "r" key and accumulator, respectively.

Quoted 5 lines

These structures could actually have the same type (e.g. poly1305_val), but different types are preferable, to prevent misuse.

Quoted 185 lines
---
 arch/x86/crypto/poly1305_glue.c | 20 +++++++------
 crypto/poly1305_generic.c       | 52 ++++++++++++++++-----------------
 include/crypto/poly1305.h       | 12 ++++++--
 3 files changed, 47 insertions(+), 37 deletions(-)
arch/x86/crypto/poly1305_glue.c +11 -9
index f012b7e28ad1..88cc01506c84 100644
@@ -83,35 +83,37 @@ static unsigned int poly1305_simd_blocks(struct poly1305_desc_ctx *dctx,
        if (poly1305_use_avx2 && srclen >= POLY1305_BLOCK_SIZE * 4) {
                if (unlikely(!sctx->wset)) {
                        if (!sctx->uset) {
-                               memcpy(sctx->u, dctx->r, sizeof(sctx->u));
-                               poly1305_simd_mult(sctx->u, dctx->r);
+                               memcpy(sctx->u, dctx->r.r, sizeof(sctx->u));
+                               poly1305_simd_mult(sctx->u, dctx->r.r);
                                sctx->uset = true;
                        }
                        memcpy(sctx->u + 5, sctx->u, sizeof(sctx->u));
-                       poly1305_simd_mult(sctx->u + 5, dctx->r);
+                       poly1305_simd_mult(sctx->u + 5, dctx->r.r);
                        memcpy(sctx->u + 10, sctx->u + 5, sizeof(sctx->u));
-                       poly1305_simd_mult(sctx->u + 10, dctx->r);
+                       poly1305_simd_mult(sctx->u + 10, dctx->r.r);
                        sctx->wset = true;
                }
                blocks = srclen / (POLY1305_BLOCK_SIZE * 4);
-               poly1305_4block_avx2(dctx->h, src, dctx->r, blocks, sctx->u);
+               poly1305_4block_avx2(dctx->h.h, src, dctx->r.r, blocks,
+                                    sctx->u);
                src += POLY1305_BLOCK_SIZE * 4 * blocks;
                srclen -= POLY1305_BLOCK_SIZE * 4 * blocks;
        }
 #endif
        if (likely(srclen >= POLY1305_BLOCK_SIZE * 2)) {
                if (unlikely(!sctx->uset)) {
-                       memcpy(sctx->u, dctx->r, sizeof(sctx->u));
-                       poly1305_simd_mult(sctx->u, dctx->r);
+                       memcpy(sctx->u, dctx->r.r, sizeof(sctx->u));
+                       poly1305_simd_mult(sctx->u, dctx->r.r);
                        sctx->uset = true;
                }
                blocks = srclen / (POLY1305_BLOCK_SIZE * 2);
-               poly1305_2block_sse2(dctx->h, src, dctx->r, blocks, sctx->u);
+               poly1305_2block_sse2(dctx->h.h, src, dctx->r.r, blocks,
+                                    sctx->u);
                src += POLY1305_BLOCK_SIZE * 2 * blocks;
                srclen -= POLY1305_BLOCK_SIZE * 2 * blocks;
        }
        if (srclen >= POLY1305_BLOCK_SIZE) {
-               poly1305_block_sse2(dctx->h, src, dctx->r, 1);
+               poly1305_block_sse2(dctx->h.h, src, dctx->r.r, 1);
                srclen -= POLY1305_BLOCK_SIZE;
        }
        return srclen;
crypto/poly1305_generic.c +26 -26
index 47d3a6b83931..a23173f351b7 100644
@@ -38,7 +38,7 @@ int crypto_poly1305_init(struct shash_desc *desc)
 {
        struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
 
-       memset(dctx->h, 0, sizeof(dctx->h));
+       memset(dctx->h.h, 0, sizeof(dctx->h.h));
        dctx->buflen = 0;
        dctx->rset = false;
        dctx->sset = false;
@@ -50,11 +50,11 @@ EXPORT_SYMBOL_GPL(crypto_poly1305_init);
 static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key)
 {
        /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
-       dctx->r[0] = (get_unaligned_le32(key +  0) >> 0) & 0x3ffffff;
-       dctx->r[1] = (get_unaligned_le32(key +  3) >> 2) & 0x3ffff03;
-       dctx->r[2] = (get_unaligned_le32(key +  6) >> 4) & 0x3ffc0ff;
-       dctx->r[3] = (get_unaligned_le32(key +  9) >> 6) & 0x3f03fff;
-       dctx->r[4] = (get_unaligned_le32(key + 12) >> 8) & 0x00fffff;
+       dctx->r.r[0] = (get_unaligned_le32(key +  0) >> 0) & 0x3ffffff;
+       dctx->r.r[1] = (get_unaligned_le32(key +  3) >> 2) & 0x3ffff03;
+       dctx->r.r[2] = (get_unaligned_le32(key +  6) >> 4) & 0x3ffc0ff;
+       dctx->r.r[3] = (get_unaligned_le32(key +  9) >> 6) & 0x3f03fff;
+       dctx->r.r[4] = (get_unaligned_le32(key + 12) >> 8) & 0x00fffff;
 }
 
 static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key)
@@ -107,22 +107,22 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
                srclen = datalen;
        }
 
-       r0 = dctx->r[0];
-       r1 = dctx->r[1];
-       r2 = dctx->r[2];
-       r3 = dctx->r[3];
-       r4 = dctx->r[4];
+       r0 = dctx->r.r[0];
+       r1 = dctx->r.r[1];
+       r2 = dctx->r.r[2];
+       r3 = dctx->r.r[3];
+       r4 = dctx->r.r[4];
 
        s1 = r1 * 5;
        s2 = r2 * 5;
        s3 = r3 * 5;
        s4 = r4 * 5;
 
-       h0 = dctx->h[0];
-       h1 = dctx->h[1];
-       h2 = dctx->h[2];
-       h3 = dctx->h[3];
-       h4 = dctx->h[4];
+       h0 = dctx->h.h[0];
+       h1 = dctx->h.h[1];
+       h2 = dctx->h.h[2];
+       h3 = dctx->h.h[3];
+       h4 = dctx->h.h[4];
 
        while (likely(srclen >= POLY1305_BLOCK_SIZE)) {
 
@@ -157,11 +157,11 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
                srclen -= POLY1305_BLOCK_SIZE;
        }
 
-       dctx->h[0] = h0;
-       dctx->h[1] = h1;
-       dctx->h[2] = h2;
-       dctx->h[3] = h3;
-       dctx->h[4] = h4;
+       dctx->h.h[0] = h0;
+       dctx->h.h[1] = h1;
+       dctx->h.h[2] = h2;
+       dctx->h.h[3] = h3;
+       dctx->h.h[4] = h4;
 
        return srclen;
 }
@@ -220,11 +220,11 @@ int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
        }
 
        /* fully carry h */
-       h0 = dctx->h[0];
-       h1 = dctx->h[1];
-       h2 = dctx->h[2];
-       h3 = dctx->h[3];
-       h4 = dctx->h[4];
+       h0 = dctx->h.h[0];
+       h1 = dctx->h.h[1];
+       h2 = dctx->h.h[2];
+       h3 = dctx->h.h[3];
+       h4 = dctx->h.h[4];
 
        h2 += (h1 >> 26);     h1 = h1 & 0x3ffffff;
        h3 += (h2 >> 26);     h2 = h2 & 0x3ffffff;
include/crypto/poly1305.h +10 -3
index f718a19da82f..493244c46664 100644
@@ -13,13 +13,21 @@
 #define POLY1305_KEY_SIZE      32
 #define POLY1305_DIGEST_SIZE   16
 
+struct poly1305_key {
+       u32 r[5];       /* key, base 2^26 */
+};
+
+struct poly1305_state {
+       u32 h[5];       /* accumulator, base 2^26 */
+};
+
 struct poly1305_desc_ctx {
        /* key */
-       u32 r[5];
+       struct poly1305_key r;
        /* finalize key */
        u32 s[4];
        /* accumulator */
-       u32 h[5];
+       struct poly1305_state h;
        /* partial buffer */
        u8 buf[POLY1305_BLOCK_SIZE];
        /* bytes used in partial buffer */
--

2.19.1.1215.g8438c0b245-goog

author maintainer
#12 lore raw

PATCH v4 11/14 crypto: poly1305 - add Poly1305 core API

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

Expose a low-level Poly1305 API which implements the ?-almost-?-universal (?A?U) hash function underlying the Poly1305 MAC and supports block-aligned inputs only.

This is needed for Adiantum hashing, which builds an ?A?U hash function from NH and a polynomial evaluation in GF(2^{130}-5); this polynomial evaluation is identical to the one the Poly1305 MAC does. However, the crypto_shash Poly1305 API isn't very appropriate for this because its calling convention assumes it is used as a MAC, with a 32-byte "one-time key" provided for every digest.

But by design, in Adiantum hashing the performance of the polynomial evaluation isn't nearly as critical as NH. So it suffices to just have some C helper functions. Thus, this patch adds such functions.

---
 crypto/poly1305_generic.c | 174 ++++++++++++++++++++++----------------
 include/crypto/poly1305.h |  16 ++++
 2 files changed, 115 insertions(+), 75 deletions(-)
crypto/poly1305_generic.c +99 -75
index a23173f351b7..2a06874204e8 100644
@@ -38,7 +38,7 @@ int crypto_poly1305_init(struct shash_desc *desc)
 {
 	struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
 
-	memset(dctx->h.h, 0, sizeof(dctx->h.h));
+	poly1305_core_init(&dctx->h);
 	dctx->buflen = 0;
 	dctx->rset = false;
 	dctx->sset = false;
@@ -47,23 +47,16 @@ int crypto_poly1305_init(struct shash_desc *desc)
 }
 EXPORT_SYMBOL_GPL(crypto_poly1305_init);
 
-static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key)
+void poly1305_core_setkey(struct poly1305_key *key, const u8 *raw_key)
 {
 	/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
-	dctx->r.r[0] = (get_unaligned_le32(key +  0) >> 0) & 0x3ffffff;
-	dctx->r.r[1] = (get_unaligned_le32(key +  3) >> 2) & 0x3ffff03;
-	dctx->r.r[2] = (get_unaligned_le32(key +  6) >> 4) & 0x3ffc0ff;
-	dctx->r.r[3] = (get_unaligned_le32(key +  9) >> 6) & 0x3f03fff;
-	dctx->r.r[4] = (get_unaligned_le32(key + 12) >> 8) & 0x00fffff;
-}
-
-static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key)
-{
-	dctx->s[0] = get_unaligned_le32(key +  0);
-	dctx->s[1] = get_unaligned_le32(key +  4);
-	dctx->s[2] = get_unaligned_le32(key +  8);
-	dctx->s[3] = get_unaligned_le32(key + 12);
+	key->r[0] = (get_unaligned_le32(raw_key +  0) >> 0) & 0x3ffffff;
+	key->r[1] = (get_unaligned_le32(raw_key +  3) >> 2) & 0x3ffff03;
+	key->r[2] = (get_unaligned_le32(raw_key +  6) >> 4) & 0x3ffc0ff;
+	key->r[3] = (get_unaligned_le32(raw_key +  9) >> 6) & 0x3f03fff;
+	key->r[4] = (get_unaligned_le32(raw_key + 12) >> 8) & 0x00fffff;
 }
+EXPORT_SYMBOL_GPL(poly1305_core_setkey);
 
 /*
  * Poly1305 requires a unique key for each tag, which implies that we can't set
@@ -75,13 +68,16 @@ unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
 {
 	if (!dctx->sset) {
 		if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) {
-			poly1305_setrkey(dctx, src);
+			poly1305_core_setkey(&dctx->r, src);
 			src += POLY1305_BLOCK_SIZE;
 			srclen -= POLY1305_BLOCK_SIZE;
 			dctx->rset = true;
 		}
 		if (srclen >= POLY1305_BLOCK_SIZE) {
-			poly1305_setskey(dctx, src);
+			dctx->s[0] = get_unaligned_le32(src +  0);
+			dctx->s[1] = get_unaligned_le32(src +  4);
+			dctx->s[2] = get_unaligned_le32(src +  8);
+			dctx->s[3] = get_unaligned_le32(src + 12);
 			src += POLY1305_BLOCK_SIZE;
 			srclen -= POLY1305_BLOCK_SIZE;
 			dctx->sset = true;
@@ -91,41 +87,37 @@ unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
 }
 EXPORT_SYMBOL_GPL(crypto_poly1305_setdesckey);
 
-static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
-				    const u8 *src, unsigned int srclen,
-				    u32 hibit)
+static void poly1305_blocks_internal(struct poly1305_state *state,
+				     const struct poly1305_key *key,
+				     const void *src, unsigned int nblocks,
+				     u32 hibit)
 {
 	u32 r0, r1, r2, r3, r4;
 	u32 s1, s2, s3, s4;
 	u32 h0, h1, h2, h3, h4;
 	u64 d0, d1, d2, d3, d4;
-	unsigned int datalen;
 
-	if (unlikely(!dctx->sset)) {
-		datalen = crypto_poly1305_setdesckey(dctx, src, srclen);
-		src += srclen - datalen;
-		srclen = datalen;
-	}
+	if (!nblocks)
+		return;
 
-	r0 = dctx->r.r[0];
-	r1 = dctx->r.r[1];
-	r2 = dctx->r.r[2];
-	r3 = dctx->r.r[3];
-	r4 = dctx->r.r[4];
+	r0 = key->r[0];
+	r1 = key->r[1];
+	r2 = key->r[2];
+	r3 = key->r[3];
+	r4 = key->r[4];
 
 	s1 = r1 * 5;
 	s2 = r2 * 5;
 	s3 = r3 * 5;
 	s4 = r4 * 5;
 
-	h0 = dctx->h.h[0];
-	h1 = dctx->h.h[1];
-	h2 = dctx->h.h[2];
-	h3 = dctx->h.h[3];
-	h4 = dctx->h.h[4];
-
-	while (likely(srclen >= POLY1305_BLOCK_SIZE)) {
+	h0 = state->h[0];
+	h1 = state->h[1];
+	h2 = state->h[2];
+	h3 = state->h[3];
+	h4 = state->h[4];
 
+	do {
 		/* h += m[i] */
 		h0 += (get_unaligned_le32(src +  0) >> 0) & 0x3ffffff;
 		h1 += (get_unaligned_le32(src +  3) >> 2) & 0x3ffffff;
@@ -154,16 +146,36 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
 		h1 += h0 >> 26;       h0 = h0 & 0x3ffffff;
 
 		src += POLY1305_BLOCK_SIZE;
-		srclen -= POLY1305_BLOCK_SIZE;
-	}
+	} while (--nblocks);
 
-	dctx->h.h[0] = h0;
-	dctx->h.h[1] = h1;
-	dctx->h.h[2] = h2;
-	dctx->h.h[3] = h3;
-	dctx->h.h[4] = h4;
+	state->h[0] = h0;
+	state->h[1] = h1;
+	state->h[2] = h2;
+	state->h[3] = h3;
+	state->h[4] = h4;
+}
 
-	return srclen;
+void poly1305_core_blocks(struct poly1305_state *state,
+			  const struct poly1305_key *key,
+			  const void *src, unsigned int nblocks)
+{
+	poly1305_blocks_internal(state, key, src, nblocks, 1 << 24);
+}
+EXPORT_SYMBOL_GPL(poly1305_core_blocks);
+
+static void poly1305_blocks(struct poly1305_desc_ctx *dctx,
+			    const u8 *src, unsigned int srclen, u32 hibit)
+{
+	unsigned int datalen;
+
+	if (unlikely(!dctx->sset)) {
+		datalen = crypto_poly1305_setdesckey(dctx, src, srclen);
+		src += srclen - datalen;
+		srclen = datalen;
+	}
+
+	poly1305_blocks_internal(&dctx->h, &dctx->r,
+				 src, srclen / POLY1305_BLOCK_SIZE, hibit);
 }
 
 int crypto_poly1305_update(struct shash_desc *desc,
@@ -187,9 +199,9 @@ int crypto_poly1305_update(struct shash_desc *desc,
 	}
 
 	if (likely(srclen >= POLY1305_BLOCK_SIZE)) {
-		bytes = poly1305_blocks(dctx, src, srclen, 1 << 24);
-		src += srclen - bytes;
-		srclen = bytes;
+		poly1305_blocks(dctx, src, srclen, 1 << 24);
+		src += srclen - (srclen % POLY1305_BLOCK_SIZE);
+		srclen %= POLY1305_BLOCK_SIZE;
 	}
 
 	if (unlikely(srclen)) {
@@ -201,30 +213,18 @@ int crypto_poly1305_update(struct shash_desc *desc,
 }
 EXPORT_SYMBOL_GPL(crypto_poly1305_update);
 
-int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
+void poly1305_core_emit(const struct poly1305_state *state, void *dst)
 {
-	struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
 	u32 h0, h1, h2, h3, h4;
 	u32 g0, g1, g2, g3, g4;
 	u32 mask;
-	u64 f = 0;
-
-	if (unlikely(!dctx->sset))
-		return -ENOKEY;
-
-	if (unlikely(dctx->buflen)) {
-		dctx->buf[dctx->buflen++] = 1;
-		memset(dctx->buf + dctx->buflen, 0,
-		       POLY1305_BLOCK_SIZE - dctx->buflen);
-		poly1305_blocks(dctx, dctx->buf, POLY1305_BLOCK_SIZE, 0);
-	}
 
 	/* fully carry h */
-	h0 = dctx->h.h[0];
-	h1 = dctx->h.h[1];
-	h2 = dctx->h.h[2];
-	h3 = dctx->h.h[3];
-	h4 = dctx->h.h[4];
+	h0 = state->h[0];
+	h1 = state->h[1];
+	h2 = state->h[2];
+	h3 = state->h[3];
+	h4 = state->h[4];
 
 	h2 += (h1 >> 26);     h1 = h1 & 0x3ffffff;
 	h3 += (h2 >> 26);     h2 = h2 & 0x3ffffff;
@@ -254,16 +254,40 @@ int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
 	h4 = (h4 & mask) | g4;
 
 	/* h = h % (2^128) */
-	h0 = (h0 >>  0) | (h1 << 26);
-	h1 = (h1 >>  6) | (h2 << 20);
-	h2 = (h2 >> 12) | (h3 << 14);
-	h3 = (h3 >> 18) | (h4 <<  8);
+	put_unaligned_le32((h0 >>  0) | (h1 << 26), dst +  0);
+	put_unaligned_le32((h1 >>  6) | (h2 << 20), dst +  4);
+	put_unaligned_le32((h2 >> 12) | (h3 << 14), dst +  8);
+	put_unaligned_le32((h3 >> 18) | (h4 <<  8), dst + 12);
+}
+EXPORT_SYMBOL_GPL(poly1305_core_emit);
+
+int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
+{
+	struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
+	__le32 digest[4];
+	u64 f = 0;
+
+	if (unlikely(!dctx->sset))
+		return -ENOKEY;
+
+	if (unlikely(dctx->buflen)) {
+		dctx->buf[dctx->buflen++] = 1;
+		memset(dctx->buf + dctx->buflen, 0,
+		       POLY1305_BLOCK_SIZE - dctx->buflen);
+		poly1305_blocks(dctx, dctx->buf, POLY1305_BLOCK_SIZE, 0);
+	}
+
+	poly1305_core_emit(&dctx->h, digest);
 
 	/* mac = (h + s) % (2^128) */
-	f = (f >> 32) + h0 + dctx->s[0]; put_unaligned_le32(f, dst +  0);
-	f = (f >> 32) + h1 + dctx->s[1]; put_unaligned_le32(f, dst +  4);
-	f = (f >> 32) + h2 + dctx->s[2]; put_unaligned_le32(f, dst +  8);
-	f = (f >> 32) + h3 + dctx->s[3]; put_unaligned_le32(f, dst + 12);
+	f = (f >> 32) + le32_to_cpu(digest[0]) + dctx->s[0];
+	put_unaligned_le32(f, dst + 0);
+	f = (f >> 32) + le32_to_cpu(digest[1]) + dctx->s[1];
+	put_unaligned_le32(f, dst + 4);
+	f = (f >> 32) + le32_to_cpu(digest[2]) + dctx->s[2];
+	put_unaligned_le32(f, dst + 8);
+	f = (f >> 32) + le32_to_cpu(digest[3]) + dctx->s[3];
+	put_unaligned_le32(f, dst + 12);
 
 	return 0;
 }
include/crypto/poly1305.h +16 -0
index 493244c46664..34317ed2071e 100644
@@ -38,6 +38,22 @@ struct poly1305_desc_ctx {
 	bool sset;
 };
 
+/*
+ * Poly1305 core functions.  These implement the ?-almost-?-universal hash
+ * function underlying the Poly1305 MAC, i.e. they don't add an encrypted nonce
+ * ("s key") at the end.  They also only support block-aligned inputs.
+ */
+void poly1305_core_setkey(struct poly1305_key *key, const u8 *raw_key);
+static inline void poly1305_core_init(struct poly1305_state *state)
+{
+	memset(state->h, 0, sizeof(state->h));
+}
+void poly1305_core_blocks(struct poly1305_state *state,
+			  const struct poly1305_key *key,
+			  const void *src, unsigned int nblocks);
+void poly1305_core_emit(const struct poly1305_state *state, void *dst);
+
+/* Crypto API helper functions for the Poly1305 MAC */
 int crypto_poly1305_init(struct shash_desc *desc);
 unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
 					const u8 *src, unsigned int srclen);
Signature · 1 line
2.19.1.1215.g8438c0b245-goog
Acked-by on v4 11/14
#13 lore raw

Re: [PATCH v4 11/14] crypto: poly1305 - add Poly1305 core API

Quoted 14 lines · Eric Biggers

From: Eric Biggers <[email protected]>

Expose a low-level Poly1305 API which implements the ?-almost-?-universal (?A?U) hash function underlying the Poly1305 MAC and supports block-aligned inputs only.

This is needed for Adiantum hashing, which builds an ?A?U hash function from NH and a polynomial evaluation in GF(2^{130}-5); this polynomial evaluation is identical to the one the Poly1305 MAC does. However, the crypto_shash Poly1305 API isn't very appropriate for this because its calling convention assumes it is used as a MAC, with a 32-byte "one-time key" provided for every digest.

Quoted 6 lines

But by design, in Adiantum hashing the performance of the polynomial evaluation isn't nearly as critical as NH. So it suffices to just have some C helper functions. Thus, this patch adds such functions.

Quoted 301 lines
---
 crypto/poly1305_generic.c | 174 ++++++++++++++++++++++----------------
 include/crypto/poly1305.h |  16 ++++
 2 files changed, 115 insertions(+), 75 deletions(-)
crypto/poly1305_generic.c +99 -75
index a23173f351b7..2a06874204e8 100644
@@ -38,7 +38,7 @@ int crypto_poly1305_init(struct shash_desc *desc)
 {
        struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
 
-       memset(dctx->h.h, 0, sizeof(dctx->h.h));
+       poly1305_core_init(&dctx->h);
        dctx->buflen = 0;
        dctx->rset = false;
        dctx->sset = false;
@@ -47,23 +47,16 @@ int crypto_poly1305_init(struct shash_desc *desc)
 }
 EXPORT_SYMBOL_GPL(crypto_poly1305_init);
 
-static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key)
+void poly1305_core_setkey(struct poly1305_key *key, const u8 *raw_key)
 {
        /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
-       dctx->r.r[0] = (get_unaligned_le32(key +  0) >> 0) & 0x3ffffff;
-       dctx->r.r[1] = (get_unaligned_le32(key +  3) >> 2) & 0x3ffff03;
-       dctx->r.r[2] = (get_unaligned_le32(key +  6) >> 4) & 0x3ffc0ff;
-       dctx->r.r[3] = (get_unaligned_le32(key +  9) >> 6) & 0x3f03fff;
-       dctx->r.r[4] = (get_unaligned_le32(key + 12) >> 8) & 0x00fffff;
-}
-
-static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key)
-{
-       dctx->s[0] = get_unaligned_le32(key +  0);
-       dctx->s[1] = get_unaligned_le32(key +  4);
-       dctx->s[2] = get_unaligned_le32(key +  8);
-       dctx->s[3] = get_unaligned_le32(key + 12);
+       key->r[0] = (get_unaligned_le32(raw_key +  0) >> 0) & 0x3ffffff;
+       key->r[1] = (get_unaligned_le32(raw_key +  3) >> 2) & 0x3ffff03;
+       key->r[2] = (get_unaligned_le32(raw_key +  6) >> 4) & 0x3ffc0ff;
+       key->r[3] = (get_unaligned_le32(raw_key +  9) >> 6) & 0x3f03fff;
+       key->r[4] = (get_unaligned_le32(raw_key + 12) >> 8) & 0x00fffff;
 }
+EXPORT_SYMBOL_GPL(poly1305_core_setkey);
 
 /*
  * Poly1305 requires a unique key for each tag, which implies that we can't set
@@ -75,13 +68,16 @@ unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
 {
        if (!dctx->sset) {
                if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) {
-                       poly1305_setrkey(dctx, src);
+                       poly1305_core_setkey(&dctx->r, src);
                        src += POLY1305_BLOCK_SIZE;
                        srclen -= POLY1305_BLOCK_SIZE;
                        dctx->rset = true;
                }
                if (srclen >= POLY1305_BLOCK_SIZE) {
-                       poly1305_setskey(dctx, src);
+                       dctx->s[0] = get_unaligned_le32(src +  0);
+                       dctx->s[1] = get_unaligned_le32(src +  4);
+                       dctx->s[2] = get_unaligned_le32(src +  8);
+                       dctx->s[3] = get_unaligned_le32(src + 12);
                        src += POLY1305_BLOCK_SIZE;
                        srclen -= POLY1305_BLOCK_SIZE;
                        dctx->sset = true;
@@ -91,41 +87,37 @@ unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
 }
 EXPORT_SYMBOL_GPL(crypto_poly1305_setdesckey);
 
-static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
-                                   const u8 *src, unsigned int srclen,
-                                   u32 hibit)
+static void poly1305_blocks_internal(struct poly1305_state *state,
+                                    const struct poly1305_key *key,
+                                    const void *src, unsigned int nblocks,
+                                    u32 hibit)
 {
        u32 r0, r1, r2, r3, r4;
        u32 s1, s2, s3, s4;
        u32 h0, h1, h2, h3, h4;
        u64 d0, d1, d2, d3, d4;
-       unsigned int datalen;
 
-       if (unlikely(!dctx->sset)) {
-               datalen = crypto_poly1305_setdesckey(dctx, src, srclen);
-               src += srclen - datalen;
-               srclen = datalen;
-       }
+       if (!nblocks)
+               return;
 
-       r0 = dctx->r.r[0];
-       r1 = dctx->r.r[1];
-       r2 = dctx->r.r[2];
-       r3 = dctx->r.r[3];
-       r4 = dctx->r.r[4];
+       r0 = key->r[0];
+       r1 = key->r[1];
+       r2 = key->r[2];
+       r3 = key->r[3];
+       r4 = key->r[4];
 
        s1 = r1 * 5;
        s2 = r2 * 5;
        s3 = r3 * 5;
        s4 = r4 * 5;
 
-       h0 = dctx->h.h[0];
-       h1 = dctx->h.h[1];
-       h2 = dctx->h.h[2];
-       h3 = dctx->h.h[3];
-       h4 = dctx->h.h[4];
-
-       while (likely(srclen >= POLY1305_BLOCK_SIZE)) {
+       h0 = state->h[0];
+       h1 = state->h[1];
+       h2 = state->h[2];
+       h3 = state->h[3];
+       h4 = state->h[4];
 
+       do {
                /* h += m[i] */
                h0 += (get_unaligned_le32(src +  0) >> 0) & 0x3ffffff;
                h1 += (get_unaligned_le32(src +  3) >> 2) & 0x3ffffff;
@@ -154,16 +146,36 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
                h1 += h0 >> 26;       h0 = h0 & 0x3ffffff;
 
                src += POLY1305_BLOCK_SIZE;
-               srclen -= POLY1305_BLOCK_SIZE;
-       }
+       } while (--nblocks);
 
-       dctx->h.h[0] = h0;
-       dctx->h.h[1] = h1;
-       dctx->h.h[2] = h2;
-       dctx->h.h[3] = h3;
-       dctx->h.h[4] = h4;
+       state->h[0] = h0;
+       state->h[1] = h1;
+       state->h[2] = h2;
+       state->h[3] = h3;
+       state->h[4] = h4;
+}
 
-       return srclen;
+void poly1305_core_blocks(struct poly1305_state *state,
+                         const struct poly1305_key *key,
+                         const void *src, unsigned int nblocks)
+{
+       poly1305_blocks_internal(state, key, src, nblocks, 1 << 24);
+}
+EXPORT_SYMBOL_GPL(poly1305_core_blocks);
+
+static void poly1305_blocks(struct poly1305_desc_ctx *dctx,
+                           const u8 *src, unsigned int srclen, u32 hibit)
+{
+       unsigned int datalen;
+
+       if (unlikely(!dctx->sset)) {
+               datalen = crypto_poly1305_setdesckey(dctx, src, srclen);
+               src += srclen - datalen;
+               srclen = datalen;
+       }
+
+       poly1305_blocks_internal(&dctx->h, &dctx->r,
+                                src, srclen / POLY1305_BLOCK_SIZE, hibit);
 }
 
 int crypto_poly1305_update(struct shash_desc *desc,
@@ -187,9 +199,9 @@ int crypto_poly1305_update(struct shash_desc *desc,
        }
 
        if (likely(srclen >= POLY1305_BLOCK_SIZE)) {
-               bytes = poly1305_blocks(dctx, src, srclen, 1 << 24);
-               src += srclen - bytes;
-               srclen = bytes;
+               poly1305_blocks(dctx, src, srclen, 1 << 24);
+               src += srclen - (srclen % POLY1305_BLOCK_SIZE);
+               srclen %= POLY1305_BLOCK_SIZE;
        }
 
        if (unlikely(srclen)) {
@@ -201,30 +213,18 @@ int crypto_poly1305_update(struct shash_desc *desc,
 }
 EXPORT_SYMBOL_GPL(crypto_poly1305_update);
 
-int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
+void poly1305_core_emit(const struct poly1305_state *state, void *dst)
 {
-       struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
        u32 h0, h1, h2, h3, h4;
        u32 g0, g1, g2, g3, g4;
        u32 mask;
-       u64 f = 0;
-
-       if (unlikely(!dctx->sset))
-               return -ENOKEY;
-
-       if (unlikely(dctx->buflen)) {
-               dctx->buf[dctx->buflen++] = 1;
-               memset(dctx->buf + dctx->buflen, 0,
-                      POLY1305_BLOCK_SIZE - dctx->buflen);
-               poly1305_blocks(dctx, dctx->buf, POLY1305_BLOCK_SIZE, 0);
-       }
 
        /* fully carry h */
-       h0 = dctx->h.h[0];
-       h1 = dctx->h.h[1];
-       h2 = dctx->h.h[2];
-       h3 = dctx->h.h[3];
-       h4 = dctx->h.h[4];
+       h0 = state->h[0];
+       h1 = state->h[1];
+       h2 = state->h[2];
+       h3 = state->h[3];
+       h4 = state->h[4];
 
        h2 += (h1 >> 26);     h1 = h1 & 0x3ffffff;
        h3 += (h2 >> 26);     h2 = h2 & 0x3ffffff;
@@ -254,16 +254,40 @@ int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
        h4 = (h4 & mask) | g4;
 
        /* h = h % (2^128) */
-       h0 = (h0 >>  0) | (h1 << 26);
-       h1 = (h1 >>  6) | (h2 << 20);
-       h2 = (h2 >> 12) | (h3 << 14);
-       h3 = (h3 >> 18) | (h4 <<  8);
+       put_unaligned_le32((h0 >>  0) | (h1 << 26), dst +  0);
+       put_unaligned_le32((h1 >>  6) | (h2 << 20), dst +  4);
+       put_unaligned_le32((h2 >> 12) | (h3 << 14), dst +  8);
+       put_unaligned_le32((h3 >> 18) | (h4 <<  8), dst + 12);
+}
+EXPORT_SYMBOL_GPL(poly1305_core_emit);
+
+int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
+{
+       struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
+       __le32 digest[4];
+       u64 f = 0;
+
+       if (unlikely(!dctx->sset))
+               return -ENOKEY;
+
+       if (unlikely(dctx->buflen)) {
+               dctx->buf[dctx->buflen++] = 1;
+               memset(dctx->buf + dctx->buflen, 0,
+                      POLY1305_BLOCK_SIZE - dctx->buflen);
+               poly1305_blocks(dctx, dctx->buf, POLY1305_BLOCK_SIZE, 0);
+       }
+
+       poly1305_core_emit(&dctx->h, digest);
 
        /* mac = (h + s) % (2^128) */
-       f = (f >> 32) + h0 + dctx->s[0]; put_unaligned_le32(f, dst +  0);
-       f = (f >> 32) + h1 + dctx->s[1]; put_unaligned_le32(f, dst +  4);
-       f = (f >> 32) + h2 + dctx->s[2]; put_unaligned_le32(f, dst +  8);
-       f = (f >> 32) + h3 + dctx->s[3]; put_unaligned_le32(f, dst + 12);
+       f = (f >> 32) + le32_to_cpu(digest[0]) + dctx->s[0];
+       put_unaligned_le32(f, dst + 0);
+       f = (f >> 32) + le32_to_cpu(digest[1]) + dctx->s[1];
+       put_unaligned_le32(f, dst + 4);
+       f = (f >> 32) + le32_to_cpu(digest[2]) + dctx->s[2];
+       put_unaligned_le32(f, dst + 8);
+       f = (f >> 32) + le32_to_cpu(digest[3]) + dctx->s[3];
+       put_unaligned_le32(f, dst + 12);
 
        return 0;
 }
include/crypto/poly1305.h +16 -1
index 493244c46664..34317ed2071e 100644
@@ -38,6 +38,22 @@ struct poly1305_desc_ctx {
        bool sset;
 };
 
+/*
+ * Poly1305 core functions.  These implement the ?-almost-?-universal hash
+ * function underlying the Poly1305 MAC, i.e. they don't add an encrypted nonce
+ * ("s key") at the end.  They also only support block-aligned inputs.
+ */
+void poly1305_core_setkey(struct poly1305_key *key, const u8 *raw_key);
+static inline void poly1305_core_init(struct poly1305_state *state)
+{
+       memset(state->h, 0, sizeof(state->h));
+}
+void poly1305_core_blocks(struct poly1305_state *state,
+                         const struct poly1305_key *key,
+                         const void *src, unsigned int nblocks);
+void poly1305_core_emit(const struct poly1305_state *state, void *dst);
+
+/* Crypto API helper functions for the Poly1305 MAC */
 int crypto_poly1305_init(struct shash_desc *desc);
 unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
                                        const u8 *src, unsigned int srclen);
--

2.19.1.1215.g8438c0b245-goog

author maintainer
#14 lore raw

PATCH v4 12/14 crypto: nhpoly1305 - add NHPoly1305 support

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

Add a generic implementation of NHPoly1305, an ?-almost-?-universal hash function used in the Adiantum encryption mode.

CONFIG_NHPOLY1305 is not selectable by itself since there won't be any real reason to enable it without also enabling Adiantum support.

---
 crypto/Kconfig              |    5 +
 crypto/Makefile             |    1 +
 crypto/nhpoly1305.c         |  254 +++++++
 crypto/testmgr.c            |    6 +
 crypto/testmgr.h            | 1240 ++++++++++++++++++++++++++++++++++-
 include/crypto/nhpoly1305.h |   74 +++
 6 files changed, 1576 insertions(+), 4 deletions(-)
 create mode 100644 crypto/nhpoly1305.c
 create mode 100644 include/crypto/nhpoly1305.h
crypto/Kconfig +5 -0
index 4431c0db56b7..eaeb8a986b7d 100644
@@ -496,6 +496,11 @@ config CRYPTO_KEYWRAP
 	  Support for key wrapping (NIST SP800-38F / RFC3394) without
 	  padding.
 
+config CRYPTO_NHPOLY1305
+	tristate
+	select CRYPTO_HASH
+	select CRYPTO_POLY1305
+
 comment "Hash modes"
 
 config CRYPTO_CMAC
crypto/Makefile +1 -0
index 102e8525814f..c3310c85f09f 100644
@@ -85,6 +85,7 @@ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_XTS) += xts.o
 obj-$(CONFIG_CRYPTO_CTR) += ctr.o
 obj-$(CONFIG_CRYPTO_KEYWRAP) += keywrap.o
+obj-$(CONFIG_CRYPTO_NHPOLY1305) += nhpoly1305.o
 obj-$(CONFIG_CRYPTO_GCM) += gcm.o
 obj-$(CONFIG_CRYPTO_CCM) += ccm.o
 obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o
crypto/nhpoly1305.c new file +254 -0

254 lines not on this page · raw message

crypto/testmgr.c +6 -0
index 6ff60c3745f1..665911c24786 100644
@@ -3311,6 +3311,12 @@ static const struct alg_test_desc alg_test_descs[] = {
 				.dec = __VECS(morus640_dec_tv_template),
 			}
 		}
+	}, {
+		.alg = "nhpoly1305",
+		.test = alg_test_hash,
+		.suite = {
+			.hash = __VECS(nhpoly1305_tv_template)
+		}
 	}, {
 		.alg = "ofb(aes)",
 		.test = alg_test_skcipher,
crypto/testmgr.h +1236 -4

1,259 lines not on this page · raw message

include/crypto/nhpoly1305.h new file +74 -0

74 lines not on this page · raw message

Signature · 1 line
2.19.1.1215.g8438c0b245-goog
Acked-by on v4 12/14
#15 lore raw

Re: [PATCH v4 12/14] crypto: nhpoly1305 - add NHPoly1305 support

Quoted 10 lines · Eric Biggers

From: Eric Biggers <[email protected]>

Add a generic implementation of NHPoly1305, an ?-almost-?-universal hash function used in the Adiantum encryption mode.

CONFIG_NHPOLY1305 is not selectable by itself since there won't be any real reason to enable it without also enabling Adiantum support.

Quoted 1,665 lines
---
 crypto/Kconfig              |    5 +
 crypto/Makefile             |    1 +
 crypto/nhpoly1305.c         |  254 +++++++
 crypto/testmgr.c            |    6 +
 crypto/testmgr.h            | 1240 ++++++++++++++++++++++++++++++++++-
 include/crypto/nhpoly1305.h |   74 +++
 6 files changed, 1576 insertions(+), 4 deletions(-)
 create mode 100644 crypto/nhpoly1305.c
 create mode 100644 include/crypto/nhpoly1305.h
crypto/Kconfig +5 -0
index 4431c0db56b7..eaeb8a986b7d 100644
@@ -496,6 +496,11 @@ config CRYPTO_KEYWRAP
          Support for key wrapping (NIST SP800-38F / RFC3394) without
          padding.
 
+config CRYPTO_NHPOLY1305
+       tristate
+       select CRYPTO_HASH
+       select CRYPTO_POLY1305
+
 comment "Hash modes"
 
 config CRYPTO_CMAC
crypto/Makefile +1 -0
index 102e8525814f..c3310c85f09f 100644
@@ -85,6 +85,7 @@ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_XTS) += xts.o
 obj-$(CONFIG_CRYPTO_CTR) += ctr.o
 obj-$(CONFIG_CRYPTO_KEYWRAP) += keywrap.o
+obj-$(CONFIG_CRYPTO_NHPOLY1305) += nhpoly1305.o
 obj-$(CONFIG_CRYPTO_GCM) += gcm.o
 obj-$(CONFIG_CRYPTO_CCM) += ccm.o
 obj-$(CONFIG_CRYPTO_CHACHA20POLY1305) += chacha20poly1305.o
crypto/nhpoly1305.c new file +254 -0
new file mode 100644
index 000000000000..c8385853f699
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * NHPoly1305 - ?-almost-?-universal hash function for Adiantum
+ *
+ * Copyright 2018 Google LLC
+ */
+
+/*
+ * "NHPoly1305" is the main component of Adiantum hashing.
+ * Specifically, it is the calculation
+ *
+ *     H_M ? Poly1305_{K_M}(NH_{K_N}(pad_{128}(M)))
+ *
+ * from the procedure in section A.5 of the Adiantum paper [1].  It is an
+ * ?-almost-?-universal (?A?U) hash function for equal-length inputs over
+ * Z/(2^{128}Z), where the "?" operation is addition.  It hashes 1024-byte
+ * chunks of the input with the NH hash function [2], reducing the input length
+ * by 32x.  The resulting NH digests are evaluated as a polynomial in
+ * GF(2^{130}-5), like in the Poly1305 MAC [3].  Note that the polynomial
+ * evaluation by itself would suffice to achieve the ?A?U property; NH is used
+ * for performance since it's over twice as fast as Poly1305.
+ *
+ * This is *not* a cryptographic hash function; do not use it as such!
+ *
+ * [1] Adiantum: length-preserving encryption for entry-level processors
+ *     (https://eprint.iacr.org/2018/720.pdf)
+ * [2] UMAC: Fast and Secure Message Authentication
+ *     (https://fastcrypto.org/umac/umac_proc.pdf)
+ * [3] The Poly1305-AES message-authentication code
+ *     (https://cr.yp.to/mac/poly1305-20050329.pdf)
+ */
+
+#include <asm/unaligned.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/hash.h>
+#include <crypto/nhpoly1305.h>
+#include <linux/crypto.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+static void nh_generic(const u32 *key, const u8 *message, size_t message_len,
+                      __le64 hash[NH_NUM_PASSES])
+{
+       u64 sums[4] = { 0, 0, 0, 0 };
+
+       BUILD_BUG_ON(NH_PAIR_STRIDE != 2);
+       BUILD_BUG_ON(NH_NUM_PASSES != 4);
+
+       while (message_len) {
+               u32 m0 = get_unaligned_le32(message + 0);
+               u32 m1 = get_unaligned_le32(message + 4);
+               u32 m2 = get_unaligned_le32(message + 8);
+               u32 m3 = get_unaligned_le32(message + 12);
+
+               sums[0] += (u64)(u32)(m0 + key[ 0]) * (u32)(m2 + key[ 2]);
+               sums[1] += (u64)(u32)(m0 + key[ 4]) * (u32)(m2 + key[ 6]);
+               sums[2] += (u64)(u32)(m0 + key[ 8]) * (u32)(m2 + key[10]);
+               sums[3] += (u64)(u32)(m0 + key[12]) * (u32)(m2 + key[14]);
+               sums[0] += (u64)(u32)(m1 + key[ 1]) * (u32)(m3 + key[ 3]);
+               sums[1] += (u64)(u32)(m1 + key[ 5]) * (u32)(m3 + key[ 7]);
+               sums[2] += (u64)(u32)(m1 + key[ 9]) * (u32)(m3 + key[11]);
+               sums[3] += (u64)(u32)(m1 + key[13]) * (u32)(m3 + key[15]);
+               key += NH_MESSAGE_UNIT / sizeof(key[0]);
+               message += NH_MESSAGE_UNIT;
+               message_len -= NH_MESSAGE_UNIT;
+       }
+
+       hash[0] = cpu_to_le64(sums[0]);
+       hash[1] = cpu_to_le64(sums[1]);
+       hash[2] = cpu_to_le64(sums[2]);
+       hash[3] = cpu_to_le64(sums[3]);
+}
+
+/* Pass the next NH hash value through Poly1305 */
+static void process_nh_hash_value(struct nhpoly1305_state *state,
+                                 const struct nhpoly1305_key *key)
+{
+       BUILD_BUG_ON(NH_HASH_BYTES % POLY1305_BLOCK_SIZE != 0);
+
+       poly1305_core_blocks(&state->poly_state, &key->poly_key, state->nh_hash,
+                            NH_HASH_BYTES / POLY1305_BLOCK_SIZE);
+}
+
+/*
+ * Feed the next portion of the source data, as a whole number of 16-byte
+ * "NH message units", through NH and Poly1305.  Each NH hash is taken over
+ * 1024 bytes, except possibly the final one which is taken over a multiple of
+ * 16 bytes up to 1024.  Also, in the case where data is passed in misaligned
+ * chunks, we combine partial hashes; the end result is the same either way.
+ */
+static void nhpoly1305_units(struct nhpoly1305_state *state,
+                            const struct nhpoly1305_key *key,
+                            const u8 *src, unsigned int srclen, nh_t nh_fn)
+{
+       do {
+               unsigned int bytes;
+
+               if (state->nh_remaining == 0) {
+                       /* Starting a new NH message */
+                       bytes = min_t(unsigned int, srclen, NH_MESSAGE_BYTES);
+                       nh_fn(key->nh_key, src, bytes, state->nh_hash);
+                       state->nh_remaining = NH_MESSAGE_BYTES - bytes;
+               } else {
+                       /* Continuing a previous NH message */
+                       __le64 tmp_hash[NH_NUM_PASSES];
+                       unsigned int pos;
+                       int i;
+
+                       pos = NH_MESSAGE_BYTES - state->nh_remaining;
+                       bytes = min(srclen, state->nh_remaining);
+                       nh_fn(&key->nh_key[pos / 4], src, bytes, tmp_hash);
+                       for (i = 0; i < NH_NUM_PASSES; i++)
+                               le64_add_cpu(&state->nh_hash[i],
+                                            le64_to_cpu(tmp_hash[i]));
+                       state->nh_remaining -= bytes;
+               }
+               if (state->nh_remaining == 0)
+                       process_nh_hash_value(state, key);
+               src += bytes;
+               srclen -= bytes;
+       } while (srclen);
+}
+
+int crypto_nhpoly1305_setkey(struct crypto_shash *tfm,
+                            const u8 *key, unsigned int keylen)
+{
+       struct nhpoly1305_key *ctx = crypto_shash_ctx(tfm);
+       int i;
+
+       if (keylen != NHPOLY1305_KEY_SIZE)
+               return -EINVAL;
+
+       poly1305_core_setkey(&ctx->poly_key, key);
+       key += POLY1305_BLOCK_SIZE;
+
+       for (i = 0; i < NH_KEY_WORDS; i++)
+               ctx->nh_key[i] = get_unaligned_le32(key + i * sizeof(u32));
+
+       return 0;
+}
+EXPORT_SYMBOL(crypto_nhpoly1305_setkey);
+
+int crypto_nhpoly1305_init(struct shash_desc *desc)
+{
+       struct nhpoly1305_state *state = shash_desc_ctx(desc);
+
+       poly1305_core_init(&state->poly_state);
+       state->buflen = 0;
+       state->nh_remaining = 0;
+       return 0;
+}
+EXPORT_SYMBOL(crypto_nhpoly1305_init);
+
+int crypto_nhpoly1305_update_helper(struct shash_desc *desc,
+                                   const u8 *src, unsigned int srclen,
+                                   nh_t nh_fn)
+{
+       struct nhpoly1305_state *state = shash_desc_ctx(desc);
+       const struct nhpoly1305_key *key = crypto_shash_ctx(desc->tfm);
+       unsigned int bytes;
+
+       if (state->buflen) {
+               bytes = min(srclen, (int)NH_MESSAGE_UNIT - state->buflen);
+               memcpy(&state->buffer[state->buflen], src, bytes);
+               state->buflen += bytes;
+               if (state->buflen < NH_MESSAGE_UNIT)
+                       return 0;
+               nhpoly1305_units(state, key, state->buffer, NH_MESSAGE_UNIT,
+                                nh_fn);
+               state->buflen = 0;
+               src += bytes;
+               srclen -= bytes;
+       }
+
+       if (srclen >= NH_MESSAGE_UNIT) {
+               bytes = round_down(srclen, NH_MESSAGE_UNIT);
+               nhpoly1305_units(state, key, src, bytes, nh_fn);
+               src += bytes;
+               srclen -= bytes;
+       }
+
+       if (srclen) {
+               memcpy(state->buffer, src, srclen);
+               state->buflen = srclen;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(crypto_nhpoly1305_update_helper);
+
+int crypto_nhpoly1305_update(struct shash_desc *desc,
+                            const u8 *src, unsigned int srclen)
+{
+       return crypto_nhpoly1305_update_helper(desc, src, srclen, nh_generic);
+}
+EXPORT_SYMBOL(crypto_nhpoly1305_update);
+
+int crypto_nhpoly1305_final_helper(struct shash_desc *desc, u8 *dst, nh_t nh_fn)
+{
+       struct nhpoly1305_state *state = shash_desc_ctx(desc);
+       const struct nhpoly1305_key *key = crypto_shash_ctx(desc->tfm);
+
+       if (state->buflen) {
+               memset(&state->buffer[state->buflen], 0,
+                      NH_MESSAGE_UNIT - state->buflen);
+               nhpoly1305_units(state, key, state->buffer, NH_MESSAGE_UNIT,
+                                nh_fn);
+       }
+
+       if (state->nh_remaining)
+               process_nh_hash_value(state, key);
+
+       poly1305_core_emit(&state->poly_state, dst);
+       return 0;
+}
+EXPORT_SYMBOL(crypto_nhpoly1305_final_helper);
+
+int crypto_nhpoly1305_final(struct shash_desc *desc, u8 *dst)
+{
+       return crypto_nhpoly1305_final_helper(desc, dst, nh_generic);
+}
+EXPORT_SYMBOL(crypto_nhpoly1305_final);
+
+static struct shash_alg nhpoly1305_alg = {
+       .base.cra_name          = "nhpoly1305",
+       .base.cra_driver_name   = "nhpoly1305-generic",
+       .base.cra_priority      = 100,
+       .base.cra_ctxsize       = sizeof(struct nhpoly1305_key),
+       .base.cra_module        = THIS_MODULE,
+       .digestsize             = POLY1305_DIGEST_SIZE,
+       .init                   = crypto_nhpoly1305_init,
+       .update                 = crypto_nhpoly1305_update,
+       .final                  = crypto_nhpoly1305_final,
+       .setkey                 = crypto_nhpoly1305_setkey,
+       .descsize               = sizeof(struct nhpoly1305_state),
+};
+
+static int __init nhpoly1305_mod_init(void)
+{
+       return crypto_register_shash(&nhpoly1305_alg);
+}
+
+static void __exit nhpoly1305_mod_exit(void)
+{
+       crypto_unregister_shash(&nhpoly1305_alg);
+}
+
+module_init(nhpoly1305_mod_init);
+module_exit(nhpoly1305_mod_exit);
+
+MODULE_DESCRIPTION("NHPoly1305 ?-almost-?-universal hash function");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Eric Biggers <[email protected]>");
+MODULE_ALIAS_CRYPTO("nhpoly1305");
+MODULE_ALIAS_CRYPTO("nhpoly1305-generic");
crypto/testmgr.c +6 -0
index 6ff60c3745f1..665911c24786 100644
@@ -3311,6 +3311,12 @@ static const struct alg_test_desc alg_test_descs[] = {
                                .dec = __VECS(morus640_dec_tv_template),
                        }
                }
+       }, {
+               .alg = "nhpoly1305",
+               .test = alg_test_hash,
+               .suite = {
+                       .hash = __VECS(nhpoly1305_tv_template)
+               }
        }, {
                .alg = "ofb(aes)",
                .test = alg_test_skcipher,
crypto/testmgr.h +1236 -4
index a23dca2b11d0..50ea1f2705c7 100644
@@ -27,7 +27,7 @@
 #define MAX_DIGEST_SIZE                64
 #define MAX_TAP                        8
 
-#define MAX_KEYLEN             160
+#define MAX_KEYLEN             1088
 #define MAX_IVLEN              32
 
 struct hash_testvec {
@@ -35,10 +35,10 @@ struct hash_testvec {
        const char *key;
        const char *plaintext;
        const char *digest;
-       unsigned char tap[MAX_TAP];
+       unsigned short tap[MAX_TAP];
+       unsigned short np;
        unsigned short psize;
-       unsigned char np;
-       unsigned char ksize;
+       unsigned short ksize;
 };
 
 /*
@@ -5709,6 +5709,1238 @@ static const struct hash_testvec poly1305_tv_template[] = {
        },
 };
 
+/* NHPoly1305 test vectors from https://github.com/google/adiantum */
+static const struct hash_testvec nhpoly1305_tv_template[] = {
+       {
+               .key    = "\xd2\x5d\x4c\xdd\x8d\x2b\x7f\x7a"
+                         "\xd9\xbe\x71\xec\xd1\x83\x52\xe3"
+                         "\xe1\xad\xd7\x5c\x0a\x75\x9d\xec"
+                         "\x1d\x13\x7e\x5d\x71\x07\xc9\xe4"
+                         "\x57\x2d\x44\x68\xcf\xd8\xd6\xc5"
+                         "\x39\x69\x7d\x32\x75\x51\x4f\x7e"
+                         "\xb2\x4c\xc6\x90\x51\x6e\xd9\xd6"
+                         "\xa5\x8b\x2d\xf1\x94\xf9\xf7\x5e"
+                         "\x2c\x84\x7b\x41\x0f\x88\x50\x89"
+                         "\x30\xd9\xa1\x38\x46\x6c\xc0\x4f"
+                         "\xe8\xdf\xdc\x66\xab\x24\x43\x41"
+                         "\x91\x55\x29\x65\x86\x28\x5e\x45"
+                         "\xd5\x2d\xb7\x80\x08\x9a\xc3\xd4"
+                         "\x9a\x77\x0a\xd4\xef\x3e\xe6\x3f"
+                         "\x6f\x2f\x9b\x3a\x7d\x12\x1e\x80"
+                         "\x6c\x44\xa2\x25\xe1\xf6\x60\xe9"
+                         "\x0d\xaf\xc5\x3c\xa5\x79\xae\x64"
+                         "\xbc\xa0\x39\xa3\x4d\x10\xe5\x4d"
+                         "\xd5\xe7\x89\x7a\x13\xee\x06\x78"
+                         "\xdc\xa4\xdc\x14\x27\xe6\x49\x38"
+                         "\xd0\xe0\x45\x25\x36\xc5\xf4\x79"
+                         "\x2e\x9a\x98\x04\xe4\x2b\x46\x52"
+                         "\x7c\x33\xca\xe2\x56\x51\x50\xe2"
+                         "\xa5\x9a\xae\x18\x6a\x13\xf8\xd2"
+                         "\x21\x31\x66\x02\xe2\xda\x8d\x7e"
+                         "\x41\x19\xb2\x61\xee\x48\x8f\xf1"
+                         "\x65\x24\x2e\x1e\x68\xce\x05\xd9"
+                         "\x2a\xcf\xa5\x3a\x57\xdd\x35\x91"
+                         "\x93\x01\xca\x95\xfc\x2b\x36\x04"
+                         "\xe6\x96\x97\x28\xf6\x31\xfe\xa3"
+                         "\x9d\xf6\x6a\x1e\x80\x8d\xdc\xec"
+                         "\xaf\x66\x11\x13\x02\x88\xd5\x27"
+                         "\x33\xb4\x1a\xcd\xa3\xf6\xde\x31"
+                         "\x8e\xc0\x0e\x6c\xd8\x5a\x97\x5e"
+                         "\xdd\xfd\x60\x69\x38\x46\x3f\x90"
+                         "\x5e\x97\xd3\x32\x76\xc7\x82\x49"
+                         "\xfe\xba\x06\x5f\x2f\xa2\xfd\xff"
+                         "\x80\x05\x40\xe4\x33\x03\xfb\x10"
+                         "\xc0\xde\x65\x8c\xc9\x8d\x3a\x9d"
+                         "\xb5\x7b\x36\x4b\xb5\x0c\xcf\x00"
+                         "\x9c\x87\xe4\x49\xad\x90\xda\x4a"
+                         "\xdd\xbd\xff\xe2\x32\x57\xd6\x78"
+                         "\x36\x39\x6c\xd3\x5b\x9b\x88\x59"
+                         "\x2d\xf0\x46\xe4\x13\x0e\x2b\x35"
+                         "\x0d\x0f\x73\x8a\x4f\x26\x84\x75"
+                         "\x88\x3c\xc5\x58\x66\x18\x1a\xb4"
+                         "\x64\x51\x34\x27\x1b\xa4\x11\xc9"
+                         "\x6d\x91\x8a\xfa\x32\x60\x9d\xd7"
+                         "\x87\xe5\xaa\x43\x72\xf8\xda\xd1"
+                         "\x48\x44\x13\x61\xdc\x8c\x76\x17"
+                         "\x0c\x85\x4e\xf3\xdd\xa2\x42\xd2"
+                         "\x74\xc1\x30\x1b\xeb\x35\x31\x29"
+                         "\x5b\xd7\x4c\x94\x46\x35\xa1\x23"
+                         "\x50\xf2\xa2\x8e\x7e\x4f\x23\x4f"
+                         "\x51\xff\xe2\xc9\xa3\x7d\x56\x8b"
+                         "\x41\xf2\xd0\xc5\x57\x7e\x59\xac"
+                         "\xbb\x65\xf3\xfe\xf7\x17\xef\x63"
+                         "\x7c\x6f\x23\xdd\x22\x8e\xed\x84"
+                         "\x0e\x3b\x09\xb3\xf3\xf4\x8f\xcd"
+                         "\x37\xa8\xe1\xa7\x30\xdb\xb1\xa2"
+                         "\x9c\xa2\xdf\x34\x17\x3e\x68\x44"
+                         "\xd0\xde\x03\x50\xd1\x48\x6b\x20"
+                         "\xe2\x63\x45\xa5\xea\x87\xc2\x42"
+                         "\x95\x03\x49\x05\xed\xe0\x90\x29"
+                         "\x1a\xb8\xcf\x9b\x43\xcf\x29\x7a"
+                         "\x63\x17\x41\x9f\xe0\xc9\x10\xfd"
+                         "\x2c\x56\x8c\x08\x55\xb4\xa9\x27"
+                         "\x0f\x23\xb1\x05\x6a\x12\x46\xc7"
+                         "\xe1\xfe\x28\x93\x93\xd7\x2f\xdc"
+                         "\x98\x30\xdb\x75\x8a\xbe\x97\x7a"
+                         "\x02\xfb\x8c\xba\xbe\x25\x09\xbe"
+                         "\xce\xcb\xa2\xef\x79\x4d\x0e\x9d"
+                         "\x1b\x9d\xb6\x39\x34\x38\xfa\x07"
+                         "\xec\xe8\xfc\x32\x85\x1d\xf7\x85"
+                         "\x63\xc3\x3c\xc0\x02\x75\xd7\x3f"
+                         "\xb2\x68\x60\x66\x65\x81\xc6\xb1"
+                         "\x42\x65\x4b\x4b\x28\xd7\xc7\xaa"
+                         "\x9b\xd2\xdc\x1b\x01\xe0\x26\x39"
+                         "\x01\xc1\x52\x14\xd1\x3f\xb7\xe6"
+                         "\x61\x41\xc7\x93\xd2\xa2\x67\xc6"
+                         "\xf7\x11\xb5\xf5\xea\xdd\x19\xfb"
+                         "\x4d\x21\x12\xd6\x7d\xf1\x10\xb0"
+                         "\x89\x07\xc7\x5a\x52\x73\x70\x2f"
+                         "\x32\xef\x65\x2b\x12\xb2\xf0\xf5"
+                         "\x20\xe0\x90\x59\x7e\x64\xf1\x4c"
+                         "\x41\xb3\xa5\x91\x08\xe6\x5e\x5f"
+                         "\x05\x56\x76\xb4\xb0\xcd\x70\x53"
+                         "\x10\x48\x9c\xff\xc2\x69\x55\x24"
+                         "\x87\xef\x84\xea\xfb\xa7\xbf\xa0"
+                         "\x91\x04\xad\x4f\x8b\x57\x54\x4b"
+                         "\xb6\xe9\xd1\xac\x37\x2f\x1d\x2e"
+                         "\xab\xa5\xa4\xe8\xff\xfb\xd9\x39"
+                         "\x2f\xb7\xac\xd1\xfe\x0b\x9a\x80"
+                         "\x0f\xb6\xf4\x36\x39\x90\x51\xe3"
+                         "\x0a\x2f\xb6\x45\x76\x89\xcd\x61"
+                         "\xfe\x48\x5f\x75\x1d\x13\x00\x62"
+                         "\x80\x24\x47\xe7\xbc\x37\xd7\xe3"
+                         "\x15\xe8\x68\x22\xaf\x80\x6f\x4b"
+                         "\xa8\x9f\x01\x10\x48\x14\xc3\x02"
+                         "\x52\xd2\xc7\x75\x9b\x52\x6d\x30"
+                         "\xac\x13\x85\xc8\xf7\xa3\x58\x4b"
+                         "\x49\xf7\x1c\x45\x55\x8c\x39\x9a"
+                         "\x99\x6d\x97\x27\x27\xe6\xab\xdd"
+                         "\x2c\x42\x1b\x35\xdd\x9d\x73\xbb"
+                         "\x6c\xf3\x64\xf1\xfb\xb9\xf7\xe6"
+                         "\x4a\x3c\xc0\x92\xc0\x2e\xb7\x1a"
+                         "\xbe\xab\xb3\x5a\xe5\xea\xb1\x48"
+                         "\x58\x13\x53\x90\xfd\xc3\x8e\x54"
+                         "\xf9\x18\x16\x73\xe8\xcb\x6d\x39"
+                         "\x0e\xd7\xe0\xfe\xb6\x9f\x43\x97"
+                         "\xe8\xd0\x85\x56\x83\x3e\x98\x68"
+                         "\x7f\xbd\x95\xa8\x9a\x61\x21\x8f"
+                         "\x06\x98\x34\xa6\xc8\xd6\x1d\xf3"
+                         "\x3d\x43\xa4\x9a\x8c\xe5\xd3\x5a"
+                         "\x32\xa2\x04\x22\xa4\x19\x1a\x46"
+                         "\x42\x7e\x4d\xe5\xe0\xe6\x0e\xca"
+                         "\xd5\x58\x9d\x2c\xaf\xda\x33\x5c"
+                         "\xb0\x79\x9e\xc9\xfc\xca\xf0\x2f"
+                         "\xa8\xb2\x77\xeb\x7a\xa2\xdd\x37"
+                         "\x35\x83\x07\xd6\x02\x1a\xb6\x6c"
+                         "\x24\xe2\x59\x08\x0e\xfd\x3e\x46"
+                         "\xec\x40\x93\xf4\x00\x26\x4f\x2a"
+                         "\xff\x47\x2f\xeb\x02\x92\x26\x5b"
+                         "\x53\x17\xc2\x8d\x2a\xc7\xa3\x1b"
+                         "\xcd\xbc\xa7\xe8\xd1\x76\xe3\x80"
+                         "\x21\xca\x5d\x3b\xe4\x9c\x8f\xa9"
+                         "\x5b\x7f\x29\x7f\x7c\xd8\xed\x6d"
+                         "\x8c\xb2\x86\x85\xe7\x77\xf2\x85"
+                         "\xab\x38\xa9\x9d\xc1\x4e\xc5\x64"
+                         "\x33\x73\x8b\x59\x03\xad\x05\xdf"
+                         "\x25\x98\x31\xde\xef\x13\xf1\x9b"
+                         "\x3c\x91\x9d\x7b\xb1\xfa\xe6\xbf"
+                         "\x5b\xed\xa5\x55\xe6\xea\x6c\x74"
+                         "\xf4\xb9\xe4\x45\x64\x72\x81\xc2"
+                         "\x4c\x28\xd4\xcd\xac\xe2\xde\xf9"
+                         "\xeb\x5c\xeb\x61\x60\x5a\xe5\x28",
+               .ksize  = 1088,
+               .plaintext      = "",
+               .psize  = 0,
+               .digest = "\x00\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00",
+       }, {
+               .key    = "\x29\x21\x43\xcb\xcb\x13\x07\xde"
+                         "\xbf\x48\xdf\x8a\x7f\xa2\x84\xde"
+                         "\x72\x23\x9d\xf5\xf0\x07\xf2\x4c"
+                         "\x20\x3a\x93\xb9\xcd\x5d\xfe\xcb"
+                         "\x99\x2c\x2b\x58\xc6\x50\x5f\x94"
+                         "\x56\xc3\x7c\x0d\x02\x3f\xb8\x5e"
+                         "\x7b\xc0\x6c\x51\x34\x76\xc0\x0e"
+                         "\xc6\x22\xc8\x9e\x92\xa0\x21\xc9"
+                         "\x85\x5c\x7c\xf8\xe2\x64\x47\xc9"
+                         "\xe4\xa2\x57\x93\xf8\xa2\x69\xcd"
+                         "\x62\x98\x99\xf4\xd7\x7b\x14\xb1"
+                         "\xd8\x05\xff\x04\x15\xc9\xe1\x6e"
+                         "\x9b\xe6\x50\x6b\x0b\x3f\x22\x1f"
+                         "\x08\xde\x0c\x5b\x08\x7e\xc6\x2f"
+                         "\x6c\xed\xd6\xb2\x15\xa4\xb3\xf9"
+                         "\xa7\x46\x38\x2a\xea\x69\xa5\xde"
+                         "\x02\xc3\x96\x89\x4d\x55\x3b\xed"
+                         "\x3d\x3a\x85\x77\xbf\x97\x45\x5c"
+                         "\x9e\x02\x69\xe2\x1b\x68\xbe\x96"
+                         "\xfb\x64\x6f\x0f\xf6\x06\x40\x67"
+                         "\xfa\x04\xe3\x55\xfa\xbe\xa4\x60"
+                         "\xef\x21\x66\x97\xe6\x9d\x5c\x1f"
+                         "\x62\x37\xaa\x31\xde\xe4\x9c\x28"
+                         "\x95\xe0\x22\x86\xf4\x4d\xf3\x07"
+                         "\xfd\x5f\x3a\x54\x2c\x51\x80\x71"
+                         "\xba\x78\x69\x5b\x65\xab\x1f\x81"
+                         "\xed\x3b\xff\x34\xa3\xfb\xbc\x73"
+                         "\x66\x7d\x13\x7f\xdf\x6e\xe2\xe2"
+                         "\xeb\x4f\x6c\xda\x7d\x33\x57\xd0"
+                         "\xd3\x7c\x95\x4f\x33\x58\x21\xc7"
+                         "\xc0\xe5\x6f\x42\x26\xc6\x1f\x5e"
+                         "\x85\x1b\x98\x9a\xa2\x1e\x55\x77"
+                         "\x23\xdf\x81\x5e\x79\x55\x05\xfc"
+                         "\xfb\xda\xee\xba\x5a\xba\xf7\x77"
+                         "\x7f\x0e\xd3\xe1\x37\xfe\x8d\x2b"
+                         "\xd5\x3f\xfb\xd0\xc0\x3c\x0b\x3f"
+                         "\xcf\x3c\x14\xcf\xfb\x46\x72\x4c"
+                         "\x1f\x39\xe2\xda\x03\x71\x6d\x23"
+                         "\xef\x93\xcd\x39\xd9\x37\x80\x4d"
+                         "\x65\x61\xd1\x2c\x03\xa9\x47\x72"
+                         "\x4d\x1e\x0e\x16\x33\x0f\x21\x17"
+                         "\xec\x92\xea\x6f\x37\x22\xa4\xd8"
+                         "\x03\x33\x9e\xd8\x03\x69\x9a\xe8"
+                         "\xb2\x57\xaf\x78\x99\x05\x12\xab"
+                         "\x48\x90\x80\xf0\x12\x9b\x20\x64"
+                         "\x7a\x1d\x47\x5f\xba\x3c\xf9\xc3"
+                         "\x0a\x0d\x8d\xa1\xf9\x1b\x82\x13"
+                         "\x3e\x0d\xec\x0a\x83\xc0\x65\xe1"
+                         "\xe9\x95\xff\x97\xd6\xf2\xe4\xd5"
+                         "\x86\xc0\x1f\x29\x27\x63\xd7\xde"
+                         "\xb7\x0a\x07\x99\x04\x2d\xa3\x89"
+                         "\xa2\x43\xcf\xf3\xe1\x43\xac\x4a"
+                         "\x06\x97\xd0\x05\x4f\x87\xfa\xf9"
+                         "\x9b\xbf\x52\x70\xbd\xbc\x6c\xf3"
+                         "\x03\x13\x60\x41\x28\x09\xec\xcc"
+                         "\xb1\x1a\xec\xd6\xfb\x6f\x2a\x89"
+                         "\x5d\x0b\x53\x9c\x59\xc1\x84\x21"
+                         "\x33\x51\x47\x19\x31\x9c\xd4\x0a"
+                         "\x4d\x04\xec\x50\x90\x61\xbd\xbc"
+                         "\x7e\xc8\xd9\x6c\x98\x1d\x45\x41"
+                         "\x17\x5e\x97\x1c\xc5\xa8\xe8\xea"
+                         "\x46\x58\x53\xf7\x17\xd5\xad\x11"
+                         "\xc8\x54\xf5\x7a\x33\x90\xf5\x19"
+                         "\xba\x36\xb4\xfc\x52\xa5\x72\x3d"
+                         "\x14\xbb\x55\xa7\xe9\xe3\x12\xf7"
+                         "\x1c\x30\xa2\x82\x03\xbf\x53\x91"
+                         "\x2e\x60\x41\x9f\x5b\x69\x39\xf6"
+                         "\x4d\xc8\xf8\x46\x7a\x7f\xa4\x98"
+                         "\x36\xff\x06\xcb\xca\xe7\x33\xf2"
+                         "\xc0\x4a\xf4\x3c\x14\x44\x5f\x6b"
+                         "\x75\xef\x02\x36\x75\x08\x14\xfd"
+                         "\x10\x8e\xa5\x58\xd0\x30\x46\x49"
+                         "\xaf\x3a\xf8\x40\x3d\x35\xdb\x84"
+                         "\x11\x2e\x97\x6a\xb7\x87\x7f\xad"
+                         "\xf1\xfa\xa5\x63\x60\xd8\x5e\xbf"
+                         "\x41\x78\x49\xcf\x77\xbb\x56\xbb"
+                         "\x7d\x01\x67\x05\x22\xc8\x8f\x41"
+                         "\xba\x81\xd2\xca\x2c\x38\xac\x76"
+                         "\x06\xc1\x1a\xc2\xce\xac\x90\x67"
+                         "\x57\x3e\x20\x12\x5b\xd9\x97\x58"
+                         "\x65\x05\xb7\x04\x61\x7e\xd8\x3a"
+                         "\xbf\x55\x3b\x13\xe9\x34\x5a\x37"
+                         "\x36\xcb\x94\x45\xc5\x32\xb3\xa0"
+                         "\x0c\x3e\x49\xc5\xd3\xed\xa7\xf0"
+                         "\x1c\x69\xcc\xea\xcc\x83\xc9\x16"
+                         "\x95\x72\x4b\xf4\x89\xd5\xb9\x10"
+                         "\xf6\x2d\x60\x15\xea\x3c\x06\x66"
+                         "\x9f\x82\xad\x17\xce\xd2\xa4\x48"
+                         "\x7c\x65\xd9\xf8\x02\x4d\x9b\x4c"
+                         "\x89\x06\x3a\x34\x85\x48\x89\x86"
+                         "\xf9\x24\xa9\x54\x72\xdb\x44\x95"
+                         "\xc7\x44\x1c\x19\x11\x4c\x04\xdc"
+                         "\x13\xb9\x67\xc8\xc3\x3a\x6a\x50"
+                         "\xfa\xd1\xfb\xe1\x88\xb6\xf1\xa3"
+                         "\xc5\x3b\xdc\x38\x45\x16\x26\x02"
+                         "\x3b\xb8\x8f\x8b\x58\x7d\x23\x04"
+                         "\x50\x6b\x81\x9f\xae\x66\xac\x6f"
+                         "\xcf\x2a\x9d\xf1\xfd\x1d\x57\x07"
+                         "\xbe\x58\xeb\x77\x0c\xe3\xc2\x19"
+                         "\x14\x74\x1b\x51\x1c\x4f\x41\xf3"
+                         "\x32\x89\xb3\xe7\xde\x62\xf6\x5f"
+                         "\xc7\x6a\x4a\x2a\x5b\x0f\x5f\x87"
+                         "\x9c\x08\xb9\x02\x88\xc8\x29\xb7"
+                         "\x94\x52\xfa\x52\xfe\xaa\x50\x10"
+                         "\xba\x48\x75\x5e\x11\x1b\xe6\x39"
+                         "\xd7\x82\x2c\x87\xf1\x1e\xa4\x38"
+                         "\x72\x3e\x51\xe7\xd8\x3e\x5b\x7b"
+                         "\x31\x16\x89\xba\xd6\xad\x18\x5e"
+                         "\xba\xf8\x12\xb3\xf4\x6c\x47\x30"
+                         "\xc0\x38\x58\xb3\x10\x8d\x58\x5d"
+                         "\xb4\xfb\x19\x7e\x41\xc3\x66\xb8"
+                         "\xd6\x72\x84\xe1\x1a\xc2\x71\x4c"
+                         "\x0d\x4a\x21\x7a\xab\xa2\xc0\x36"
+                         "\x15\xc5\xe9\x46\xd7\x29\x17\x76"
+                         "\x5e\x47\x36\x7f\x72\x05\xa7\xcc"
+                         "\x36\x63\xf9\x47\x7d\xe6\x07\x3c"
+                         "\x8b\x79\x1d\x96\x61\x8d\x90\x65"
+                         "\x7c\xf5\xeb\x4e\x6e\x09\x59\x6d"
+                         "\x62\x50\x1b\x0f\xe0\xdc\x78\xf2"
+                         "\x5b\x83\x1a\xa1\x11\x75\xfd\x18"
+                         "\xd7\xe2\x8d\x65\x14\x21\xce\xbe"
+                         "\xb5\x87\xe3\x0a\xda\x24\x0a\x64"
+                         "\xa9\x9f\x03\x8d\x46\x5d\x24\x1a"
+                         "\x8a\x0c\x42\x01\xca\xb1\x5f\x7c"
+                         "\xa5\xac\x32\x4a\xb8\x07\x91\x18"
+                         "\x6f\xb0\x71\x3c\xc9\xb1\xa8\xf8"
+                         "\x5f\x69\xa5\xa1\xca\x9e\x7a\xaa"
+                         "\xac\xe9\xc7\x47\x41\x75\x25\xc3"
+                         "\x73\xe2\x0b\xdd\x6d\x52\x71\xbe"
+                         "\xc5\xdc\xb4\xe7\x01\x26\x53\x77"
+                         "\x86\x90\x85\x68\x6b\x7b\x03\x53"
+                         "\xda\x52\x52\x51\x68\xc8\xf3\xec"
+                         "\x6c\xd5\x03\x7a\xa3\x0e\xb4\x02"
+                         "\x5f\x1a\xab\xee\xca\x67\x29\x7b"
+                         "\xbd\x96\x59\xb3\x8b\x32\x7a\x92"
+                         "\x9f\xd8\x25\x2b\xdf\xc0\x4c\xda",
+               .ksize  = 1088,
+               .plaintext      = "\xbc\xda\x81\xa8\x78\x79\x1c\xbf"
+                         "\x77\x53\xba\x4c\x30\x5b\xb8\x33",
+               .psize  = 16,
+               .digest = "\x04\xbf\x7f\x6a\xce\x72\xea\x6a"
+                         "\x79\xdb\xb0\xc9\x60\xf6\x12\xcc",
+               .np     = 6,
+               .tap    = { 4, 4, 1, 1, 1, 5 },
+       }, {
+               .key    = "\x65\x4d\xe3\xf8\xd2\x4c\xac\x28"
+                         "\x68\xf5\xb3\x81\x71\x4b\xa1\xfa"
+                         "\x04\x0e\xd3\x81\x36\xbe\x0c\x81"
+                         "\x5e\xaf\xbc\x3a\xa4\xc0\x8e\x8b"
+                         "\x55\x63\xd3\x52\x97\x88\xd6\x19"
+                         "\xbc\x96\xdf\x49\xff\x04\x63\xf5"
+                         "\x0c\x11\x13\xaa\x9e\x1f\x5a\xf7"
+                         "\xdd\xbd\x37\x80\xc3\xd0\xbe\xa7"
+                         "\x05\xc8\x3c\x98\x1e\x05\x3c\x84"
+                         "\x39\x61\xc4\xed\xed\x71\x1b\xc4"
+                         "\x74\x45\x2c\xa1\x56\x70\x97\xfd"
+                         "\x44\x18\x07\x7d\xca\x60\x1f\x73"
+                         "\x3b\x6d\x21\xcb\x61\x87\x70\x25"
+                         "\x46\x21\xf1\x1f\x21\x91\x31\x2d"
+                         "\x5d\xcc\xb7\xd1\x84\x3e\x3d\xdb"
+                         "\x03\x53\x2a\x82\xa6\x9a\x95\xbc"
+                         "\x1a\x1e\x0a\x5e\x07\x43\xab\x43"
+                         "\xaf\x92\x82\x06\x91\x04\x09\xf4"
+                         "\x17\x0a\x9a\x2c\x54\xdb\xb8\xf4"
+                         "\xd0\xf0\x10\x66\x24\x8d\xcd\xda"
+                         "\xfe\x0e\x45\x9d\x6f\xc4\x4e\xf4"
+                         "\x96\xaf\x13\xdc\xa9\xd4\x8c\xc4"
+                         "\xc8\x57\x39\x3c\xc2\xd3\x0a\x76"
+                         "\x4a\x1f\x75\x83\x44\xc7\xd1\x39"
+                         "\xd8\xb5\x41\xba\x73\x87\xfa\x96"
+                         "\xc7\x18\x53\xfb\x9b\xda\xa0\x97"
+                         "\x1d\xee\x60\x85\x9e\x14\xc3\xce"
+                         "\xc4\x05\x29\x3b\x95\x30\xa3\xd1"
+                         "\x9f\x82\x6a\x04\xf5\xa7\x75\x57"
+                         "\x82\x04\xfe\x71\x51\x71\xb1\x49"
+                         "\x50\xf8\xe0\x96\xf1\xfa\xa8\x88"
+                         "\x3f\xa0\x86\x20\xd4\x60\x79\x59"
+                         "\x17\x2d\xd1\x09\xf4\xec\x05\x57"
+                         "\xcf\x62\x7e\x0e\x7e\x60\x78\xe6"
+                         "\x08\x60\x29\xd8\xd5\x08\x1a\x24"
+                         "\xc4\x6c\x24\xe7\x92\x08\x3d\x8a"
+                         "\x98\x7a\xcf\x99\x0a\x65\x0e\xdc"
+                         "\x8c\x8a\xbe\x92\x82\x91\xcc\x62"
+                         "\x30\xb6\xf4\x3f\xc6\x8a\x7f\x12"
+                         "\x4a\x8a\x49\xfa\x3f\x5c\xd4\x5a"
+                         "\xa6\x82\xa3\xe6\xaa\x34\x76\xb2"
+                         "\xab\x0a\x30\xef\x6c\x77\x58\x3f"
+                         "\x05\x6b\xcc\x5c\xae\xdc\xd7\xb9"
+                         "\x51\x7e\x8d\x32\x5b\x24\x25\xbe"
+                         "\x2b\x24\x01\xcf\x80\xda\x16\xd8"
+                         "\x90\x72\x2c\xad\x34\x8d\x0c\x74"
+                         "\x02\xcb\xfd\xcf\x6e\xef\x97\xb5"
+                         "\x4c\xf2\x68\xca\xde\x43\x9e\x8a"
+                         "\xc5\x5f\x31\x7f\x14\x71\x38\xec"
+                         "\xbd\x98\xe5\x71\xc4\xb5\xdb\xef"
+                         "\x59\xd2\xca\xc0\xc1\x86\x75\x01"
+                         "\xd4\x15\x0d\x6f\xa4\xf7\x7b\x37"
+                         "\x47\xda\x18\x93\x63\xda\xbe\x9e"
+                         "\x07\xfb\xb2\x83\xd5\xc4\x34\x55"
+                         "\xee\x73\xa1\x42\x96\xf9\x66\x41"
+                         "\xa4\xcc\xd2\x93\x6e\xe1\x0a\xbb"
+                         "\xd2\xdd\x18\x23\xe6\x6b\x98\x0b"
+                         "\x8a\x83\x59\x2c\xc3\xa6\x59\x5b"
+                         "\x01\x22\x59\xf7\xdc\xb0\x87\x7e"
+                         "\xdb\x7d\xf4\x71\x41\xab\xbd\xee"
+                         "\x79\xbe\x3c\x01\x76\x0b\x2d\x0a"
+                         "\x42\xc9\x77\x8c\xbb\x54\x95\x60"
+                         "\x43\x2e\xe0\x17\x52\xbd\x90\xc9"
+                         "\xc2\x2c\xdd\x90\x24\x22\x76\x40"
+                         "\x5c\xb9\x41\xc9\xa1\xd5\xbd\xe3"
+                         "\x44\xe0\xa4\xab\xcc\xb8\xe2\x32"
+                         "\x02\x15\x04\x1f\x8c\xec\x5d\x14"
+                         "\xac\x18\xaa\xef\x6e\x33\x19\x6e"
+                         "\xde\xfe\x19\xdb\xeb\x61\xca\x18"
+                         "\xad\xd8\x3d\xbf\x09\x11\xc7\xa5"
+                         "\x86\x0b\x0f\xe5\x3e\xde\xe8\xd9"
+                         "\x0a\x69\x9e\x4c\x20\xff\xf9\xc5"
+                         "\xfa\xf8\xf3\x7f\xa5\x01\x4b\x5e"
+                         "\x0f\xf0\x3b\x68\xf0\x46\x8c\x2a"
+                         "\x7a\xc1\x8f\xa0\xfe\x6a\x5b\x44"
+                         "\x70\x5c\xcc\x92\x2c\x6f\x0f\xbd"
+                         "\x25\x3e\xb7\x8e\x73\x58\xda\xc9"
+                         "\xa5\xaa\x9e\xf3\x9b\xfd\x37\x3e"
+                         "\xe2\x88\xa4\x7b\xc8\x5c\xa8\x93"
+                         "\x0e\xe7\x9a\x9c\x2e\x95\x18\x9f"
+                         "\xc8\x45\x0c\x88\x9e\x53\x4f\x3a"
+                         "\x76\xc1\x35\xfa\x17\xd8\xac\xa0"
+                         "\x0c\x2d\x47\x2e\x4f\x69\x9b\xf7"
+                         "\xd0\xb6\x96\x0c\x19\xb3\x08\x01"
+                         "\x65\x7a\x1f\xc7\x31\x86\xdb\xc8"
+                         "\xc1\x99\x8f\xf8\x08\x4a\x9d\x23"
+                         "\x22\xa8\xcf\x27\x01\x01\x88\x93"
+                         "\x9c\x86\x45\xbd\xe0\x51\xca\x52"
+                         "\x84\xba\xfe\x03\xf7\xda\xc5\xce"
+                         "\x3e\x77\x75\x86\xaf\x84\xc8\x05"
+                         "\x44\x01\x0f\x02\xf3\x58\xb0\x06"
+                         "\x5a\xd7\x12\x30\x8d\xdf\x1f\x1f"
+                         "\x0a\xe6\xd2\xea\xf6\x3a\x7a\x99"
+                         "\x63\xe8\xd2\xc1\x4a\x45\x8b\x40"
+                         "\x4d\x0a\xa9\x76\x92\xb3\xda\x87"
+                         "\x36\x33\xf0\x78\xc3\x2f\x5f\x02"
+                         "\x1a\x6a\x2c\x32\xcd\x76\xbf\xbd"
+                         "\x5a\x26\x20\x28\x8c\x8c\xbc\x52"
+                         "\x3d\x0a\xc9\xcb\xab\xa4\x21\xb0"
+                         "\x54\x40\x81\x44\xc7\xd6\x1c\x11"
+                         "\x44\xc6\x02\x92\x14\x5a\xbf\x1a"
+                         "\x09\x8a\x18\xad\xcd\x64\x3d\x53"
+                         "\x4a\xb6\xa5\x1b\x57\x0e\xef\xe0"
+                         "\x8c\x44\x5f\x7d\xbd\x6c\xfd\x60"
+                         "\xae\x02\x24\xb6\x99\xdd\x8c\xaf"
+                         "\x59\x39\x75\x3c\xd1\x54\x7b\x86"
+                         "\xcc\x99\xd9\x28\x0c\xb0\x94\x62"
+                         "\xf9\x51\xd1\x19\x96\x2d\x66\xf5"
+                         "\x55\xcf\x9e\x59\xe2\x6b\x2c\x08"
+                         "\xc0\x54\x48\x24\x45\xc3\x8c\x73"
+                         "\xea\x27\x6e\x66\x7d\x1d\x0e\x6e"
+                         "\x13\xe8\x56\x65\x3a\xb0\x81\x5c"
+                         "\xf0\xe8\xd8\x00\x6b\xcd\x8f\xad"
+                         "\xdd\x53\xf3\xa4\x6c\x43\xd6\x31"
+                         "\xaf\xd2\x76\x1e\x91\x12\xdb\x3c"
+                         "\x8c\xc2\x81\xf0\x49\xdb\xe2\x6b"
+                         "\x76\x62\x0a\x04\xe4\xaa\x8a\x7c"
+                         "\x08\x0b\x5d\xd0\xee\x1d\xfb\xc4"
+                         "\x02\x75\x42\xd6\xba\xa7\x22\xa8"
+                         "\x47\x29\xb7\x85\x6d\x93\x3a\xdb"
+                         "\x00\x53\x0b\xa2\xeb\xf8\xfe\x01"
+                         "\x6f\x8a\x31\xd6\x17\x05\x6f\x67"
+                         "\x88\x95\x32\xfe\x4f\xa6\x4b\xf8"
+                         "\x03\xe4\xcd\x9a\x18\xe8\x4e\x2d"
+                         "\xf7\x97\x9a\x0c\x7d\x9f\x7e\x44"
+                         "\x69\x51\xe0\x32\x6b\x62\x86\x8f"
+                         "\xa6\x8e\x0b\x21\x96\xe5\xaf\x77"
+                         "\xc0\x83\xdf\xa5\x0e\xd0\xa1\x04"
+                         "\xaf\xc1\x10\xcb\x5a\x40\xe4\xe3"
+                         "\x38\x7e\x07\xe8\x4d\xfa\xed\xc5"
+                         "\xf0\x37\xdf\xbb\x8a\xcf\x3d\xdc"
+                         "\x61\xd2\xc6\x2b\xff\x07\xc9\x2f"
+                         "\x0c\x2d\x5c\x07\xa8\x35\x6a\xfc"
+                         "\xae\x09\x03\x45\x74\x51\x4d\xc4"
+                         "\xb8\x23\x87\x4a\x99\x27\x20\x87"
+                         "\x62\x44\x0a\x4a\xce\x78\x47\x22",
+               .ksize  = 1088,
+               .plaintext      = "\x8e\xb0\x4c\xde\x9c\x4a\x04\x5a"
+                         "\xf6\xa9\x7f\x45\x25\xa5\x7b\x3a"
+                         "\xbc\x4d\x73\x39\x81\xb5\xbd\x3d"
+                         "\x21\x6f\xd7\x37\x50\x3c\x7b\x28"
+                         "\xd1\x03\x3a\x17\xed\x7b\x7c\x2a"
+                         "\x16\xbc\xdf\x19\x89\x52\x71\x31"
+                         "\xb6\xc0\xfd\xb5\xd3\xba\x96\x99"
+                         "\xb6\x34\x0b\xd0\x99\x93\xfc\x1a"
+                         "\x01\x3c\x85\xc6\x9b\x78\x5c\x8b"
+                         "\xfe\xae\xd2\xbf\xb2\x6f\xf9\xed"
+                         "\xc8\x25\x17\xfe\x10\x3b\x7d\xda"
+                         "\xf4\x8d\x35\x4b\x7c\x7b\x82\xe7"
+                         "\xc2\xb3\xee\x60\x4a\x03\x86\xc9"
+                         "\x4e\xb5\xc4\xbe\xd2\xbd\x66\xf1"
+                         "\x13\xf1\x09\xab\x5d\xca\x63\x1f"
+                         "\xfc\xfb\x57\x2a\xfc\xca\x66\xd8"
+                         "\x77\x84\x38\x23\x1d\xac\xd3\xb3"
+                         "\x7a\xad\x4c\x70\xfa\x9c\xc9\x61"
+                         "\xa6\x1b\xba\x33\x4b\x4e\x33\xec"
+                         "\xa0\xa1\x64\x39\x40\x05\x1c\xc2"
+                         "\x3f\x49\x9d\xae\xf2\xc5\xf2\xc5"
+                         "\xfe\xe8\xf4\xc2\xf9\x96\x2d\x28"
+                         "\x92\x30\x44\xbc\xd2\x7f\xe1\x6e"
+                         "\x62\x02\x8f\x3d\x1c\x80\xda\x0e"
+                         "\x6a\x90\x7e\x75\xff\xec\x3e\xc4"
+                         "\xcd\x16\x34\x3b\x05\x6d\x4d\x20"
+                         "\x1c\x7b\xf5\x57\x4f\xfa\x3d\xac"
+                         "\xd0\x13\x55\xe8\xb3\xe1\x1b\x78"
+                         "\x30\xe6\x9f\x84\xd4\x69\xd1\x08"
+                         "\x12\x77\xa7\x4a\xbd\xc0\xf2\xd2"
+                         "\x78\xdd\xa3\x81\x12\xcb\x6c\x14"
+                         "\x90\x61\xe2\x84\xc6\x2b\x16\xcc"
+                         "\x40\x99\x50\x88\x01\x09\x64\x4f"
+                         "\x0a\x80\xbe\x61\xae\x46\xc9\x0a"
+                         "\x5d\xe0\xfb\x72\x7a\x1a\xdd\x61"
+                         "\x63\x20\x05\xa0\x4a\xf0\x60\x69"
+                         "\x7f\x92\xbc\xbf\x4e\x39\x4d\xdd"
+                         "\x74\xd1\xb7\xc0\x5a\x34\xb7\xae"
+                         "\x76\x65\x2e\xbc\x36\xb9\x04\x95"
+                         "\x42\xe9\x6f\xca\x78\xb3\x72\x07"
+                         "\xa3\xba\x02\x94\x67\x4c\xb1\xd7"
+                         "\xe9\x30\x0d\xf0\x3b\xb8\x10\x6d"
+                         "\xea\x2b\x21\xbf\x74\x59\x82\x97"
+                         "\x85\xaa\xf1\xd7\x54\x39\xeb\x05"
+                         "\xbd\xf3\x40\xa0\x97\xe6\x74\xfe"
+                         "\xb4\x82\x5b\xb1\x36\xcb\xe8\x0d"
+                         "\xce\x14\xd9\xdf\xf1\x94\x22\xcd"
+                         "\xd6\x00\xba\x04\x4c\x05\x0c\xc0"
+                         "\xd1\x5a\xeb\x52\xd5\xa8\x8e\xc8"
+                         "\x97\xa1\xaa\xc1\xea\xc1\xbe\x7c"
+                         "\x36\xb3\x36\xa0\xc6\x76\x66\xc5"
+                         "\xe2\xaf\xd6\x5c\xe2\xdb\x2c\xb3"
+                         "\x6c\xb9\x99\x7f\xff\x9f\x03\x24"
+                         "\xe1\x51\x44\x66\xd8\x0c\x5d\x7f"
+                         "\x5c\x85\x22\x2a\xcf\x6d\x79\x28"
+                         "\xab\x98\x01\x72\xfe\x80\x87\x5f"
+                         "\x46\xba\xef\x81\x24\xee\xbf\xb0"
+                         "\x24\x74\xa3\x65\x97\x12\xc4\xaf"
+                         "\x8b\xa0\x39\xda\x8a\x7e\x74\x6e"
+                         "\x1b\x42\xb4\x44\x37\xfc\x59\xfd"
+                         "\x86\xed\xfb\x8c\x66\x33\xda\x63"
+                         "\x75\xeb\xe1\xa4\x85\x4f\x50\x8f"
+                         "\x83\x66\x0d\xd3\x37\xfa\xe6\x9c"
+                         "\x4f\x30\x87\x35\x18\xe3\x0b\xb7"
+                         "\x6e\x64\x54\xcd\x70\xb3\xde\x54"
+                         "\xb7\x1d\xe6\x4c\x4d\x55\x12\x12"
+                         "\xaf\x5f\x7f\x5e\xee\x9d\xe8\x8e"
+                         "\x32\x9d\x4e\x75\xeb\xc6\xdd\xaa"
+                         "\x48\x82\xa4\x3f\x3c\xd7\xd3\xa8"
+                         "\x63\x9e\x64\xfe\xe3\x97\x00\x62"
+                         "\xe5\x40\x5d\xc3\xad\x72\xe1\x28"
+                         "\x18\x50\xb7\x75\xef\xcd\x23\xbf"
+                         "\x3f\xc0\x51\x36\xf8\x41\xc3\x08"
+                         "\xcb\xf1\x8d\x38\x34\xbd\x48\x45"
+                         "\x75\xed\xbc\x65\x7b\xb5\x0c\x9b"
+                         "\xd7\x67\x7d\x27\xb4\xc4\x80\xd7"
+                         "\xa9\xb9\xc7\x4a\x97\xaa\xda\xc8"
+                         "\x3c\x74\xcf\x36\x8f\xe4\x41\xe3"
+                         "\xd4\xd3\x26\xa7\xf3\x23\x9d\x8f"
+                         "\x6c\x20\x05\x32\x3e\xe0\xc3\xc8"
+                         "\x56\x3f\xa7\x09\xb7\xfb\xc7\xf7"
+                         "\xbe\x2a\xdd\x0f\x06\x7b\x0d\xdd"
+                         "\xb0\xb4\x86\x17\xfd\xb9\x04\xe5"
+                         "\xc0\x64\x5d\xad\x2a\x36\x38\xdb"
+                         "\x24\xaf\x5b\xff\xca\xf9\x41\xe8"
+                         "\xf9\x2f\x1e\x5e\xf9\xf5\xd5\xf2"
+                         "\xb2\x88\xca\xc9\xa1\x31\xe2\xe8"
+                         "\x10\x95\x65\xbf\xf1\x11\x61\x7a"
+                         "\x30\x1a\x54\x90\xea\xd2\x30\xf6"
+                         "\xa5\xad\x60\xf9\x4d\x84\x21\x1b"
+                         "\xe4\x42\x22\xc8\x12\x4b\xb0\x58"
+                         "\x3e\x9c\x2d\x32\x95\x0a\x8e\xb0"
+                         "\x0a\x7e\x77\x2f\xe8\x97\x31\x6a"
+                         "\xf5\x59\xb4\x26\xe6\x37\x12\xc9"
+                         "\xcb\xa0\x58\x33\x6f\xd5\x55\x55"
+                         "\x3c\xa1\x33\xb1\x0b\x7e\x2e\xb4"
+                         "\x43\x2a\x84\x39\xf0\x9c\xf4\x69"
+                         "\x4f\x1e\x79\xa6\x15\x1b\x87\xbb"
+                         "\xdb\x9b\xe0\xf1\x0b\xba\xe3\x6e"
+                         "\xcc\x2f\x49\x19\x22\x29\xfc\x71"
+                         "\xbb\x77\x38\x18\x61\xaf\x85\x76"
+                         "\xeb\xd1\x09\xcc\x86\x04\x20\x9a"
+                         "\x66\x53\x2f\x44\x8b\xc6\xa3\xd2"
+                         "\x5f\xc7\x79\x82\x66\xa8\x6e\x75"
+                         "\x7d\x94\xd1\x86\x75\x0f\xa5\x4f"
+                         "\x3c\x7a\x33\xce\xd1\x6e\x9d\x7b"
+                         "\x1f\x91\x37\xb8\x37\x80\xfb\xe0"
+                         "\x52\x26\xd0\x9a\xd4\x48\x02\x41"
+                         "\x05\xe3\x5a\x94\xf1\x65\x61\x19"
+                         "\xb8\x88\x4e\x2b\xea\xba\x8b\x58"
+                         "\x8b\x42\x01\x00\xa8\xfe\x00\x5c"
+                         "\xfe\x1c\xee\x31\x15\x69\xfa\xb3"
+                         "\x9b\x5f\x22\x8e\x0d\x2c\xe3\xa5"
+                         "\x21\xb9\x99\x8a\x8e\x94\x5a\xef"
+                         "\x13\x3e\x99\x96\x79\x6e\xd5\x42"
+                         "\x36\x03\xa9\xe2\xca\x65\x4e\x8a"
+                         "\x8a\x30\xd2\x7d\x74\xe7\xf0\xaa"
+                         "\x23\x26\xdd\xcb\x82\x39\xfc\x9d"
+                         "\x51\x76\x21\x80\xa2\xbe\x93\x03"
+                         "\x47\xb0\xc1\xb6\xdc\x63\xfd\x9f"
+                         "\xca\x9d\xa5\xca\x27\x85\xe2\xd8"
+                         "\x15\x5b\x7e\x14\x7a\xc4\x89\xcc"
+                         "\x74\x14\x4b\x46\xd2\xce\xac\x39"
+                         "\x6b\x6a\x5a\xa4\x0e\xe3\x7b\x15"
+                         "\x94\x4b\x0f\x74\xcb\x0c\x7f\xa9"
+                         "\xbe\x09\x39\xa3\xdd\x56\x5c\xc7"
+                         "\x99\x56\x65\x39\xf4\x0b\x7d\x87"
+                         "\xec\xaa\xe3\x4d\x22\x65\x39\x4e",
+               .psize  = 1024,
+               .digest = "\x64\x3a\xbc\xc3\x3f\x74\x40\x51"
+                         "\x6e\x56\x01\x1a\x51\xec\x36\xde",
+               .np     = 8,
+               .tap    = { 64, 203, 267, 28, 263, 62, 54, 83 },
+       }, {
+               .key    = "\x1b\x82\x2e\x1b\x17\x23\xb9\x6d"
+                         "\xdc\x9c\xda\x99\x07\xe3\x5f\xd8"
+                         "\xd2\xf8\x43\x80\x8d\x86\x7d\x80"
+                         "\x1a\xd0\xcc\x13\xb9\x11\x05\x3f"
+                         "\x7e\xcf\x7e\x80\x0e\xd8\x25\x48"
+                         "\x8b\xaa\x63\x83\x92\xd0\x72\xf5"
+                         "\x4f\x67\x7e\x50\x18\x25\xa4\xd1"
+                         "\xe0\x7e\x1e\xba\xd8\xa7\x6e\xdb"
+                         "\x1a\xcc\x0d\xfe\x9f\x6d\x22\x35"
+                         "\xe1\xe6\xe0\xa8\x7b\x9c\xb1\x66"
+                         "\xa3\xf8\xff\x4d\x90\x84\x28\xbc"
+                         "\xdc\x19\xc7\x91\x49\xfc\xf6\x33"
+                         "\xc9\x6e\x65\x7f\x28\x6f\x68\x2e"
+                         "\xdf\x1a\x75\xe9\xc2\x0c\x96\xb9"
+                         "\x31\x22\xc4\x07\xc6\x0a\x2f\xfd"
+                         "\x36\x06\x5f\x5c\xc5\xb1\x3a\xf4"
+                         "\x5e\x48\xa4\x45\x2b\x88\xa7\xee"
+                         "\xa9\x8b\x52\xcc\x99\xd9\x2f\xb8"
+                         "\xa4\x58\x0a\x13\xeb\x71\x5a\xfa"
+                         "\xe5\x5e\xbe\xf2\x64\xad\x75\xbc"
+                         "\x0b\x5b\x34\x13\x3b\x23\x13\x9a"
+                         "\x69\x30\x1e\x9a\xb8\x03\xb8\x8b"
+                         "\x3e\x46\x18\x6d\x38\xd9\xb3\xd8"
+                         "\xbf\xf1\xd0\x28\xe6\x51\x57\x80"
+                         "\x5e\x99\xfb\xd0\xce\x1e\x83\xf7"
+                         "\xe9\x07\x5a\x63\xa9\xef\xce\xa5"
+                         "\xfb\x3f\x37\x17\xfc\x0b\x37\x0e"
+                         "\xbb\x4b\x21\x62\xb7\x83\x0e\xa9"
+                         "\x9e\xb0\xc4\xad\x47\xbe\x35\xe7"
+                         "\x51\xb2\xf2\xac\x2b\x65\x7b\x48"
+                         "\xe3\x3f\x5f\xb6\x09\x04\x0c\x58"
+                         "\xce\x99\xa9\x15\x2f\x4e\xc1\xf2"
+                         "\x24\x48\xc0\xd8\x6c\xd3\x76\x17"
+                         "\x83\x5d\xe6\xe3\xfd\x01\x8e\xf7"
+                         "\x42\xa5\x04\x29\x30\xdf\xf9\x00"
+                         "\x4a\xdc\x71\x22\x1a\x33\x15\xb6"
+                         "\xd7\x72\xfb\x9a\xb8\xeb\x2b\x38"
+                         "\xea\xa8\x61\xa8\x90\x11\x9d\x73"
+                         "\x2e\x6c\xce\x81\x54\x5a\x9f\xcd"
+                         "\xcf\xd5\xbd\x26\x5d\x66\xdb\xfb"
+                         "\xdc\x1e\x7c\x10\xfe\x58\x82\x10"
+                         "\x16\x24\x01\xce\x67\x55\x51\xd1"
+                         "\xdd\x6b\x44\xa3\x20\x8e\xa9\xa6"
+                         "\x06\xa8\x29\x77\x6e\x00\x38\x5b"
+                         "\xde\x4d\x58\xd8\x1f\x34\xdf\xf9"
+                         "\x2c\xac\x3e\xad\xfb\x92\x0d\x72"
+                         "\x39\xa4\xac\x44\x10\xc0\x43\xc4"
+                         "\xa4\x77\x3b\xfc\xc4\x0d\x37\xd3"
+                         "\x05\x84\xda\x53\x71\xf8\x80\xd3"
+                         "\x34\x44\xdb\x09\xb4\x2b\x8e\xe3"
+                         "\x00\x75\x50\x9e\x43\x22\x00\x0b"
+                         "\x7c\x70\xab\xd4\x41\xf1\x93\xcd"
+                         "\x25\x2d\x84\x74\xb5\xf2\x92\xcd"
+                         "\x0a\x28\xea\x9a\x49\x02\x96\xcb"
+                         "\x85\x9e\x2f\x33\x03\x86\x1d\xdc"
+                         "\x1d\x31\xd5\xfc\x9d\xaa\xc5\xe9"
+                         "\x9a\xc4\x57\xf5\x35\xed\xf4\x4b"
+                         "\x3d\x34\xc2\x29\x13\x86\x36\x42"
+                         "\x5d\xbf\x90\x86\x13\x77\xe5\xc3"
+                         "\x62\xb4\xfe\x0b\x70\x39\x35\x65"
+                         "\x02\xea\xf6\xce\x57\x0c\xbb\x74"
+                         "\x29\xe3\xfd\x60\x90\xfd\x10\x38"
+                         "\xd5\x4e\x86\xbd\x37\x70\xf0\x97"
+                         "\xa6\xab\x3b\x83\x64\x52\xca\x66"
+                         "\x2f\xf9\xa4\xca\x3a\x55\x6b\xb0"
+                         "\xe8\x3a\x34\xdb\x9e\x48\x50\x2f"
+                         "\x3b\xef\xfd\x08\x2d\x5f\xc1\x37"
+                         "\x5d\xbe\x73\xe4\xd8\xe9\xac\xca"
+                         "\x8a\xaa\x48\x7c\x5c\xf4\xa6\x96"
+                         "\x5f\xfa\x70\xa6\xb7\x8b\x50\xcb"
+                         "\xa6\xf5\xa9\xbd\x7b\x75\x4c\x22"
+                         "\x0b\x19\x40\x2e\xc9\x39\x39\x32"
+                         "\x83\x03\xa8\xa4\x98\xe6\x8e\x16"
+                         "\xb9\xde\x08\xc5\xfc\xbf\xad\x39"
+                         "\xa8\xc7\x93\x6c\x6f\x23\xaf\xc1"
+                         "\xab\xe1\xdf\xbb\x39\xae\x93\x29"
+                         "\x0e\x7d\x80\x8d\x3e\x65\xf3\xfd"
+                         "\x96\x06\x65\x90\xa1\x28\x64\x4b"
+                         "\x69\xf9\xa8\x84\x27\x50\xfc\x87"
+                         "\xf7\xbf\x55\x8e\x56\x13\x58\x7b"
+                         "\x85\xb4\x6a\x72\x0f\x40\xf1\x4f"
+                         "\x83\x81\x1f\x76\xde\x15\x64\x7a"
+                         "\x7a\x80\xe4\xc7\x5e\x63\x01\x91"
+                         "\xd7\x6b\xea\x0b\x9b\xa2\x99\x3b"
+                         "\x6c\x88\xd8\xfd\x59\x3c\x8d\x22"
+                         "\x86\x56\xbe\xab\xa1\x37\x08\x01"
+                         "\x50\x85\x69\x29\xee\x9f\xdf\x21"
+                         "\x3e\x20\x20\xf5\xb0\xbb\x6b\xd0"
+                         "\x9c\x41\x38\xec\x54\x6f\x2d\xbd"
+                         "\x0f\xe1\xbd\xf1\x2b\x6e\x60\x56"
+                         "\x29\xe5\x7a\x70\x1c\xe2\xfc\x97"
+                         "\x82\x68\x67\xd9\x3d\x1f\xfb\xd8"
+                         "\x07\x9f\xbf\x96\x74\xba\x6a\x0e"
+                         "\x10\x48\x20\xd8\x13\x1e\xb5\x44"
+                         "\xf2\xcc\xb1\x8b\xfb\xbb\xec\xd7"
+                         "\x37\x70\x1f\x7c\x55\xd2\x4b\xb9"
+                         "\xfd\x70\x5e\xa3\x91\x73\x63\x52"
+                         "\x13\x47\x5a\x06\xfb\x01\x67\xa5"
+                         "\xc0\xd0\x49\x19\x56\x66\x9a\x77"
+                         "\x64\xaf\x8c\x25\x91\x52\x87\x0e"
+                         "\x18\xf3\x5f\x97\xfd\x71\x13\xf8"
+                         "\x05\xa5\x39\xcc\x65\xd3\xcc\x63"
+                         "\x5b\xdb\x5f\x7e\x5f\x6e\xad\xc4"
+                         "\xf4\xa0\xc5\xc2\x2b\x4d\x97\x38"
+                         "\x4f\xbc\xfa\x33\x17\xb4\x47\xb9"
+                         "\x43\x24\x15\x8d\xd2\xed\x80\x68"
+                         "\x84\xdb\x04\x80\xca\x5e\x6a\x35"
+                         "\x2c\x2c\xe7\xc5\x03\x5f\x54\xb0"
+                         "\x5e\x4f\x1d\x40\x54\x3d\x78\x9a"
+                         "\xac\xda\x80\x27\x4d\x15\x4c\x1a"
+                         "\x6e\x80\xc9\xc4\x3b\x84\x0e\xd9"
+                         "\x2e\x93\x01\x8c\xc3\xc8\x91\x4b"
+                         "\xb3\xaa\x07\x04\x68\x5b\x93\xa5"
+                         "\xe7\xc4\x9d\xe7\x07\xee\xf5\x3b"
+                         "\x40\x89\xcc\x60\x34\x9d\xb4\x06"
+                         "\x1b\xef\x92\xe6\xc1\x2a\x7d\x0f"
+                         "\x81\xaa\x56\xe3\xd7\xed\xa7\xd4"
+                         "\xa7\x3a\x49\xc4\xad\x81\x5c\x83"
+                         "\x55\x8e\x91\x54\xb7\x7d\x65\xa5"
+                         "\x06\x16\xd5\x9a\x16\xc1\xb0\xa2"
+                         "\x06\xd8\x98\x47\x73\x7e\x73\xa0"
+                         "\xb8\x23\xb1\x52\xbf\x68\x74\x5d"
+                         "\x0b\xcb\xfa\x8c\x46\xe3\x24\xe6"
+                         "\xab\xd4\x69\x8d\x8c\xf2\x8a\x59"
+                         "\xbe\x48\x46\x50\x8c\x9a\xe8\xe3"
+                         "\x31\x55\x0a\x06\xed\x4f\xf8\xb7"
+                         "\x4f\xe3\x85\x17\x30\xbd\xd5\x20"
+                         "\xe7\x5b\xb2\x32\xcf\x6b\x16\x44"
+                         "\xd2\xf5\x7e\xd7\xd1\x2f\xee\x64"
+                         "\x3e\x9d\x10\xef\x27\x35\x43\x64"
+                         "\x67\xfb\x7a\x7b\xe0\x62\x31\x9a"
+                         "\x4d\xdf\xa5\xab\xc0\x20\xbb\x01"
+                         "\xe9\x7b\x54\xf1\xde\xb2\x79\x50"
+                         "\x6c\x4b\x91\xdb\x7f\xbb\x50\xc1"
+                         "\x55\x44\x38\x9a\xe0\x9f\xe8\x29"
+                         "\x6f\x15\xf8\x4e\xa6\xec\xa0\x60",
+               .ksize  = 1088,
+               .plaintext      = "\x15\x68\x9e\x2f\xad\x15\x52\xdf"
+                         "\xf0\x42\x62\x24\x2a\x2d\xea\xbf"
+                         "\xc7\xf3\xb4\x1a\xf5\xed\xb2\x08"
+                         "\x15\x60\x1c\x00\x77\xbf\x0b\x0e"
+                         "\xb7\x2c\xcf\x32\x3a\xc7\x01\x77"
+                         "\xef\xa6\x75\xd0\x29\xc7\x68\x20"
+                         "\xb2\x92\x25\xbf\x12\x34\xe9\xa4"
+                         "\xfd\x32\x7b\x3f\x7c\xbd\xa5\x02"
+                         "\x38\x41\xde\xc9\xc1\x09\xd9\xfc"
+                         "\x6e\x78\x22\x83\x18\xf7\x50\x8d"
+                         "\x8f\x9c\x2d\x02\xa5\x30\xac\xff"
+                         "\xea\x63\x2e\x80\x37\x83\xb0\x58"
+                         "\xda\x2f\xef\x21\x55\xba\x7b\xb1"
+                         "\xb6\xed\xf5\xd2\x4d\xaa\x8c\xa9"
+                         "\xdd\xdb\x0f\xb4\xce\xc1\x9a\xb1"
+                         "\xc1\xdc\xbd\xab\x86\xc2\xdf\x0b"
+                         "\xe1\x2c\xf9\xbe\xf6\xd8\xda\x62"
+                         "\x72\xdd\x98\x09\x52\xc0\xc4\xb6"
+                         "\x7b\x17\x5c\xf5\xd8\x4b\x88\xd6"
+                         "\x6b\xbf\x84\x4a\x3f\xf5\x4d\xd2"
+                         "\x94\xe2\x9c\xff\xc7\x3c\xd9\xc8"
+                         "\x37\x38\xbc\x8c\xf3\xe7\xb7\xd0"
+                         "\x1d\x78\xc4\x39\x07\xc8\x5e\x79"
+                         "\xb6\x5a\x90\x5b\x6e\x97\xc9\xd4"
+                         "\x82\x9c\xf3\x83\x7a\xe7\x97\xfc"
+                         "\x1d\xbb\xef\xdb\xce\xe0\x82\xad"
+                         "\xca\x07\x6c\x54\x62\x6f\x81\xe6"
+                         "\x7a\x5a\x96\x6e\x80\x3a\xa2\x37"
+                         "\x6f\xc6\xa4\x29\xc3\x9e\x19\x94"
+                         "\x9f\xb0\x3e\x38\xfb\x3c\x2b\x7d"
+                         "\xaa\xb8\x74\xda\x54\x23\x51\x12"
+                         "\x4b\x96\x36\x8f\x91\x4f\x19\x37"
+                         "\x83\xc9\xdd\xc7\x1a\x32\x2d\xab"
+                         "\xc7\x89\xe2\x07\x47\x6c\xe8\xa6"
+                         "\x70\x6b\x8e\x0c\xda\x5c\x6a\x59"
+                         "\x27\x33\x0e\xe1\xe1\x20\xe8\xc8"
+                         "\xae\xdc\xd0\xe3\x6d\xa8\xa6\x06"
+                         "\x41\xb4\xd4\xd4\xcf\x91\x3e\x06"
+                         "\xb0\x9a\xf7\xf1\xaa\xa6\x23\x92"
+                         "\x10\x86\xf0\x94\xd1\x7c\x2e\x07"
+                         "\x30\xfb\xc5\xd8\xf3\x12\xa9\xe8"
+                         "\x22\x1c\x97\x1a\xad\x96\xb0\xa1"
+                         "\x72\x6a\x6b\xb4\xfd\xf7\xe8\xfa"
+                         "\xe2\x74\xd8\x65\x8d\x35\x17\x4b"
+                         "\x00\x23\x5c\x8c\x70\xad\x71\xa2"
+                         "\xca\xc5\x6c\x59\xbf\xb4\xc0\x6d"
+                         "\x86\x98\x3e\x19\x5a\x90\x92\xb1"
+                         "\x66\x57\x6a\x91\x68\x7c\xbc\xf3"
+                         "\xf1\xdb\x94\xf8\x48\xf1\x36\xd8"
+                         "\x78\xac\x1c\xa9\xcc\xd6\x27\xba"
+                         "\x91\x54\x22\xf5\xe6\x05\x3f\xcc"
+                         "\xc2\x8f\x2c\x3b\x2b\xc3\x2b\x2b"
+                         "\x3b\xb8\xb6\x29\xb7\x2f\x94\xb6"
+                         "\x7b\xfc\x94\x3e\xd0\x7a\x41\x59"
+                         "\x7b\x1f\x9a\x09\xa6\xed\x4a\x82"
+                         "\x9d\x34\x1c\xbd\x4e\x1c\x3a\x66"
+                         "\x80\x74\x0e\x9a\x4f\x55\x54\x47"
+                         "\x16\xba\x2a\x0a\x03\x35\x99\xa3"
+                         "\x5c\x63\x8d\xa2\x72\x8b\x17\x15"
+                         "\x68\x39\x73\xeb\xec\xf2\xe8\xf5"
+                         "\x95\x32\x27\xd6\xc4\xfe\xb0\x51"
+                         "\xd5\x0c\x50\xc5\xcd\x6d\x16\xb3"
+                         "\xa3\x1e\x95\x69\xad\x78\x95\x06"
+                         "\xb9\x46\xf2\x6d\x24\x5a\x99\x76"
+                         "\x73\x6a\x91\xa6\xac\x12\xe1\x28"
+                         "\x79\xbc\x08\x4e\x97\x00\x98\x63"
+                         "\x07\x1c\x4e\xd1\x68\xf3\xb3\x81"
+                         "\xa8\xa6\x5f\xf1\x01\xc9\xc1\xaf"
+                         "\x3a\x96\xf9\x9d\xb5\x5a\x5f\x8f"
+                         "\x7e\xc1\x7e\x77\x0a\x40\xc8\x8e"
+                         "\xfc\x0e\xed\xe1\x0d\xb0\xe5\x5e"
+                         "\x5e\x6f\xf5\x7f\xab\x33\x7d\xcd"
+                         "\xf0\x09\x4b\xb2\x11\x37\xdc\x65"
+                         "\x97\x32\x62\x71\x3a\x29\x54\xb9"
+                         "\xc7\xa4\xbf\x75\x0f\xf9\x40\xa9"
+                         "\x8d\xd7\x8b\xa7\xe0\x9a\xbe\x15"
+                         "\xc6\xda\xd8\x00\x14\x69\x1a\xaf"
+                         "\x5f\x79\xc3\xf5\xbb\x6c\x2a\x9d"
+                         "\xdd\x3c\x5f\x97\x21\xe1\x3a\x03"
+                         "\x84\x6a\xe9\x76\x11\x1f\xd3\xd5"
+                         "\xf0\x54\x20\x4d\xc2\x91\xc3\xa4"
+                         "\x36\x25\xbe\x1b\x2a\x06\xb7\xf3"
+                         "\xd1\xd0\x55\x29\x81\x4c\x83\xa3"
+                         "\xa6\x84\x1e\x5c\xd1\xd0\x6c\x90"
+                         "\xa4\x11\xf0\xd7\x63\x6a\x48\x05"
+                         "\xbc\x48\x18\x53\xcd\xb0\x8d\xdb"
+                         "\xdc\xfe\x55\x11\x5c\x51\xb3\xab"
+                         "\xab\x63\x3e\x31\x5a\x8b\x93\x63"
+                         "\x34\xa9\xba\x2b\x69\x1a\xc0\xe3"
+                         "\xcb\x41\xbc\xd7\xf5\x7f\x82\x3e"
+                         "\x01\xa3\x3c\x72\xf4\xfe\xdf\xbe"
+                         "\xb1\x67\x17\x2b\x37\x60\x0d\xca"
+                         "\x6f\xc3\x94\x2c\xd2\x92\x6d\x9d"
+                         "\x75\x18\x77\xaa\x29\x38\x96\xed"
+                         "\x0e\x20\x70\x92\xd5\xd0\xb4\x00"
+                         "\xc0\x31\xf2\xc9\x43\x0e\x75\x1d"
+                         "\x4b\x64\xf2\x1f\xf2\x29\x6c\x7b"
+                         "\x7f\xec\x59\x7d\x8c\x0d\xd4\xd3"
+                         "\xac\x53\x4c\xa3\xde\x42\x92\x95"
+                         "\x6d\xa3\x4f\xd0\xe6\x3d\xe7\xec"
+                         "\x7a\x4d\x68\xf1\xfe\x67\x66\x09"
+                         "\x83\x22\xb1\x98\x43\x8c\xab\xb8"
+                         "\x45\xe6\x6d\xdf\x5e\x50\x71\xce"
+                         "\xf5\x4e\x40\x93\x2b\xfa\x86\x0e"
+                         "\xe8\x30\xbd\x82\xcc\x1c\x9c\x5f"
+                         "\xad\xfd\x08\x31\xbe\x52\xe7\xe6"
+                         "\xf2\x06\x01\x62\x25\x15\x99\x74"
+                         "\x33\x51\x52\x57\x3f\x57\x87\x61"
+                         "\xb9\x7f\x29\x3d\xcd\x92\x5e\xa6"
+                         "\x5c\x3b\xf1\xed\x5f\xeb\x82\xed"
+                         "\x56\x7b\x61\xe7\xfd\x02\x47\x0e"
+                         "\x2a\x15\xa4\xce\x43\x86\x9b\xe1"
+                         "\x2b\x4c\x2a\xd9\x42\x97\xf7\x9a"
+                         "\xe5\x47\x46\x48\xd3\x55\x6f\x4d"
+                         "\xd9\xeb\x4b\xdd\x7b\x21\x2f\xb3"
+                         "\xa8\x36\x28\xdf\xca\xf1\xf6\xd9"
+                         "\x10\xf6\x1c\xfd\x2e\x0c\x27\xe0"
+                         "\x01\xb3\xff\x6d\x47\x08\x4d\xd4"
+                         "\x00\x25\xee\x55\x4a\xe9\xe8\x5b"
+                         "\xd8\xf7\x56\x12\xd4\x50\xb2\xe5"
+                         "\x51\x6f\x34\x63\x69\xd2\x4e\x96"
+                         "\x4e\xbc\x79\xbf\x18\xae\xc6\x13"
+                         "\x80\x92\x77\xb0\xb4\x0f\x29\x94"
+                         "\x6f\x4c\xbb\x53\x11\x36\xc3\x9f"
+                         "\x42\x8e\x96\x8a\x91\xc8\xe9\xfc"
+                         "\xfe\xbf\x7c\x2d\x6f\xf9\xb8\x44"
+                         "\x89\x1b\x09\x53\x0a\x2a\x92\xc3"
+                         "\x54\x7a\x3a\xf9\xe2\xe4\x75\x87"
+                         "\xa0\x5e\x4b\x03\x7a\x0d\x8a\xf4"
+                         "\x55\x59\x94\x2b\x63\x96\x0e\xf5",
+               .psize  = 1040,
+               .digest = "\xb5\xb9\x08\xb3\x24\x3e\x03\xf0"
+                         "\xd6\x0b\x57\xbc\x0a\x6d\x89\x59",
+       }, {
+               .key    = "\xf6\x34\x42\x71\x35\x52\x8b\x58"
+                         "\x02\x3a\x8e\x4a\x8d\x41\x13\xe9"
+                         "\x7f\xba\xb9\x55\x9d\x73\x4d\xf8"
+                         "\x3f\x5d\x73\x15\xff\xd3\x9e\x7f"
+                         "\x20\x2a\x6a\xa8\xd1\xf0\x8f\x12"
+                         "\x6b\x02\xd8\x6c\xde\xba\x80\x22"
+                         "\x19\x37\xc8\xd0\x4e\x89\x17\x7c"
+                         "\x7c\xdd\x88\xfd\x41\xc0\x04\xb7"
+                         "\x1d\xac\x19\xe3\x20\xc7\x16\xcf"
+                         "\x58\xee\x1d\x7a\x61\x69\xa9\x12"
+                         "\x4b\xef\x4f\xb6\x38\xdd\x78\xf8"
+                         "\x28\xee\x70\x08\xc7\x7c\xcc\xc8"
+                         "\x1e\x41\xf5\x80\x86\x70\xd0\xf0"
+                         "\xa3\x87\x6b\x0a\x00\xd2\x41\x28"
+                         "\x74\x26\xf1\x24\xf3\xd0\x28\x77"
+                         "\xd7\xcd\xf6\x2d\x61\xf4\xa2\x13"
+                         "\x77\xb4\x6f\xa0\xf4\xfb\xd6\xb5"
+                         "\x38\x9d\x5a\x0c\x51\xaf\xad\x63"
+                         "\x27\x67\x8c\x01\xea\x42\x1a\x66"
+                         "\xda\x16\x7c\x3c\x30\x0c\x66\x53"
+                         "\x1c\x88\xa4\x5c\xb2\xe3\x78\x0a"
+                         "\x13\x05\x6d\xe2\xaf\xb3\xe4\x75"
+                         "\x00\x99\x58\xee\x76\x09\x64\xaa"
+                         "\xbb\x2e\xb1\x81\xec\xd8\x0e\xd3"
+                         "\x0c\x33\x5d\xb7\x98\xef\x36\xb6"
+                         "\xd2\x65\x69\x41\x70\x12\xdc\x25"
+                         "\x41\x03\x99\x81\x41\x19\x62\x13"
+                         "\xd1\x0a\x29\xc5\x8c\xe0\x4c\xf3"
+                         "\xd6\xef\x4c\xf4\x1d\x83\x2e\x6d"
+                         "\x8e\x14\x87\xed\x80\xe0\xaa\xd3"
+                         "\x08\x04\x73\x1a\x84\x40\xf5\x64"
+                         "\xbd\x61\x32\x65\x40\x42\xfb\xb0"
+                         "\x40\xf6\x40\x8d\xc7\x7f\x14\xd0"
+                         "\x83\x99\xaa\x36\x7e\x60\xc6\xbf"
+                         "\x13\x8a\xf9\x21\xe4\x7e\x68\x87"
+                         "\xf3\x33\x86\xb4\xe0\x23\x7e\x0a"
+                         "\x21\xb1\xf5\xad\x67\x3c\x9c\x9d"
+                         "\x09\xab\xaf\x5f\xba\xe0\xd0\x82"
+                         "\x48\x22\x70\xb5\x6d\x53\xd6\x0e"
+                         "\xde\x64\x92\x41\xb0\xd3\xfb\xda"
+                         "\x21\xfe\xab\xea\x20\xc4\x03\x58"
+                         "\x18\x2e\x7d\x2f\x03\xa9\x47\x66"
+                         "\xdf\x7b\xa4\x6b\x34\x6b\x55\x9c"
+                         "\x4f\xd7\x9c\x47\xfb\xa9\x42\xec"
+                         "\x5a\x12\xfd\xfe\x76\xa0\x92\x9d"
+                         "\xfe\x1e\x16\xdd\x24\x2a\xe4\x27"
+                         "\xd5\xa9\xf2\x05\x4f\x83\xa2\xaf"
+                         "\xfe\xee\x83\x7a\xad\xde\xdf\x9a"
+                         "\x80\xd5\x81\x14\x93\x16\x7e\x46"
+                         "\x47\xc2\x14\xef\x49\x6e\xb9\xdb"
+                         "\x40\xe8\x06\x6f\x9c\x2a\xfd\x62"
+                         "\x06\x46\xfd\x15\x1d\x36\x61\x6f"
+                         "\x77\x77\x5e\x64\xce\x78\x1b\x85"
+                         "\xbf\x50\x9a\xfd\x67\xa6\x1a\x65"
+                         "\xad\x5b\x33\x30\xf1\x71\xaa\xd9"
+                         "\x23\x0d\x92\x24\x5f\xae\x57\xb0"
+                         "\x24\x37\x0a\x94\x12\xfb\xb5\xb1"
+                         "\xd3\xb8\x1d\x12\x29\xb0\x80\x24"
+                         "\x2d\x47\x9f\x96\x1f\x95\xf1\xb1"
+                         "\xda\x35\xf6\x29\xe0\xe1\x23\x96"
+                         "\xc7\xe8\x22\x9b\x7c\xac\xf9\x41"
+                         "\x39\x01\xe5\x73\x15\x5e\x99\xec"
+                         "\xb4\xc1\xf4\xe7\xa7\x97\x6a\xd5"
+                         "\x90\x9a\xa0\x1d\xf3\x5a\x8b\x5f"
+                         "\xdf\x01\x52\xa4\x93\x31\x97\xb0"
+                         "\x93\x24\xb5\xbc\xb2\x14\x24\x98"
+                         "\x4a\x8f\x19\x85\xc3\x2d\x0f\x74"
+                         "\x9d\x16\x13\x80\x5e\x59\x62\x62"
+                         "\x25\xe0\xd1\x2f\x64\xef\xba\xac"
+                         "\xcd\x09\x07\x15\x8a\xcf\x73\xb5"
+                         "\x8b\xc9\xd8\x24\xb0\x53\xd5\x6f"
+                         "\xe1\x2b\x77\xb1\xc5\xe4\xa7\x0e"
+                         "\x18\x45\xab\x36\x03\x59\xa8\xbd"
+                         "\x43\xf0\xd8\x2c\x1a\x69\x96\xbb"
+                         "\x13\xdf\x6c\x33\x77\xdf\x25\x34"
+                         "\x5b\xa5\x5b\x8c\xf9\x51\x05\xd4"
+                         "\x8b\x8b\x44\x87\x49\xfc\xa0\x8f"
+                         "\x45\x15\x5b\x40\x42\xc4\x09\x92"
+                         "\x98\x0c\x4d\xf4\x26\x37\x1b\x13"
+                         "\x76\x01\x93\x8d\x4f\xe6\xed\x18"
+                         "\xd0\x79\x7b\x3f\x44\x50\xcb\xee"
+                         "\xf7\x4a\xc9\x9e\xe0\x96\x74\xa7"
+                         "\xe6\x93\xb2\x53\xca\x55\xa8\xdc"
+                         "\x1e\x68\x07\x87\xb7\x2e\xc1\x08"
+                         "\xb2\xa4\x5b\xaf\xc6\xdb\x5c\x66"
+                         "\x41\x1c\x51\xd9\xb0\x07\x00\x0d"
+                         "\xf0\x4c\xdc\x93\xde\xa9\x1e\x8e"
+                         "\xd3\x22\x62\xd8\x8b\x88\x2c\xea"
+                         "\x5e\xf1\x6e\x14\x40\xc7\xbe\xaa"
+                         "\x42\x28\xd0\x26\x30\x78\x01\x9b"
+                         "\x83\x07\xbc\x94\xc7\x57\xa2\x9f"
+                         "\x03\x07\xff\x16\xff\x3c\x6e\x48"
+                         "\x0a\xd0\xdd\x4c\xf6\x64\x9a\xf1"
+                         "\xcd\x30\x12\x82\x2c\x38\xd3\x26"
+                         "\x83\xdb\xab\x3e\xc6\xf8\xe6\xfa"
+                         "\x77\x0a\x78\x82\x75\xf8\x63\x51"
+                         "\x59\xd0\x8d\x24\x9f\x25\xe6\xa3"
+                         "\x4c\xbc\x34\xfc\xe3\x10\xc7\x62"
+                         "\xd4\x23\xc8\x3d\xa7\xc6\xa6\x0a"
+                         "\x4f\x7e\x29\x9d\x6d\xbe\xb5\xf1"
+                         "\xdf\xa4\x53\xfa\xc0\x23\x0f\x37"
+                         "\x84\x68\xd0\xb5\xc8\xc6\xae\xf8"
+                         "\xb7\x8d\xb3\x16\xfe\x8f\x87\xad"
+                         "\xd0\xc1\x08\xee\x12\x1c\x9b\x1d"
+                         "\x90\xf8\xd1\x63\xa4\x92\x3c\xf0"
+                         "\xc7\x34\xd8\xf1\x14\xed\xa3\xbc"
+                         "\x17\x7e\xd4\x62\x42\x54\x57\x2c"
+                         "\x3e\x7a\x35\x35\x17\x0f\x0b\x7f"
+                         "\x81\xa1\x3f\xd0\xcd\xc8\x3b\x96"
+                         "\xe9\xe0\x4a\x04\xe1\xb6\x3c\xa1"
+                         "\xd6\xca\xc4\xbd\xb6\xb5\x95\x34"
+                         "\x12\x9d\xc5\x96\xf2\xdf\xba\x54"
+                         "\x76\xd1\xb2\x6b\x3b\x39\xe0\xb9"
+                         "\x18\x62\xfb\xf7\xfc\x12\xf1\x5f"
+                         "\x7e\xc7\xe3\x59\x4c\xa6\xc2\x3d"
+                         "\x40\x15\xf9\xa3\x95\x64\x4c\x74"
+                         "\x8b\x73\x77\x33\x07\xa7\x04\x1d"
+                         "\x33\x5a\x7e\x8f\xbd\x86\x01\x4f"
+                         "\x3e\xb9\x27\x6f\xe2\x41\xf7\x09"
+                         "\x67\xfd\x29\x28\xc5\xe4\xf6\x18"
+                         "\x4c\x1b\x49\xb2\x9c\x5b\xf6\x81"
+                         "\x4f\xbb\x5c\xcc\x0b\xdf\x84\x23"
+                         "\x58\xd6\x28\x34\x93\x3a\x25\x97"
+                         "\xdf\xb2\xc3\x9e\x97\x38\x0b\x7d"
+                         "\x10\xb3\x54\x35\x23\x8c\x64\xee"
+                         "\xf0\xd8\x66\xff\x8b\x22\xd2\x5b"
+                         "\x05\x16\x3c\x89\xf7\xb1\x75\xaf"
+                         "\xc0\xae\x6a\x4f\x3f\xaf\x9a\xf4"
+                         "\xf4\x9a\x24\xd9\x80\x82\xc0\x12"
+                         "\xde\x96\xd1\xbe\x15\x0b\x8d\x6a"
+                         "\xd7\x12\xe4\x85\x9f\x83\xc9\xc3"
+                         "\xff\x0b\xb5\xaf\x3b\xd8\x6d\x67"
+                         "\x81\x45\xe6\xac\xec\xc1\x7b\x16"
+                         "\x18\x0a\xce\x4b\xc0\x2e\x76\xbc"
+                         "\x1b\xfa\xb4\x34\xb8\xfc\x3e\xc8"
+                         "\x5d\x90\x71\x6d\x7a\x79\xef\x06",
+               .ksize  = 1088,
+               .plaintext      = "\xaa\x5d\x54\xcb\xea\x1e\x46\x0f"
+                         "\x45\x87\x70\x51\x8a\x66\x7a\x33"
+                         "\xb4\x18\xff\xa9\x82\xf9\x45\x4b"
+                         "\x93\xae\x2e\x7f\xab\x98\xfe\xbf"
+                         "\x01\xee\xe5\xa0\x37\x8f\x57\xa6"
+                         "\xb0\x76\x0d\xa4\xd6\x28\x2b\x5d"
+                         "\xe1\x03\xd6\x1c\x6f\x34\x0d\xe7"
+                         "\x61\x2d\x2e\xe5\xae\x5d\x47\xc7"
+                         "\x80\x4b\x18\x8f\xa8\x99\xbc\x28"
+                         "\xed\x1d\x9d\x86\x7d\xd7\x41\xd1"
+                         "\xe0\x2b\xe1\x8c\x93\x2a\xa7\x80"
+                         "\xe1\x07\xa0\xa9\x9f\x8c\x8d\x1a"
+                         "\x55\xfc\x6b\x24\x7a\xbd\x3e\x51"
+                         "\x68\x4b\x26\x59\xc8\xa7\x16\xd9"
+                         "\xb9\x61\x13\xde\x8b\x63\x1c\xf6"
+                         "\x60\x01\xfb\x08\xb3\x5b\x0a\xbf"
+                         "\x34\x73\xda\x87\x87\x3d\x6f\x97"
+                         "\x4a\x0c\xa3\x58\x20\xa2\xc0\x81"
+                         "\x5b\x8c\xef\xa9\xc2\x01\x1e\x64"
+                         "\x83\x8c\xbc\x03\xb6\xd0\x29\x9f"
+                         "\x54\xe2\xce\x8b\xc2\x07\x85\x78"
+                         "\x25\x38\x96\x4c\xb4\xbe\x17\x4a"
+                         "\x65\xa6\xfa\x52\x9d\x66\x9d\x65"
+                         "\x4a\xd1\x01\x01\xf0\xcb\x13\xcc"
+                         "\xa5\x82\xf3\xf2\x66\xcd\x3f\x9d"
+                         "\xd1\xaa\xe4\x67\xea\xf2\xad\x88"
+                         "\x56\x76\xa7\x9b\x59\x3c\xb1\x5d"
+                         "\x78\xfd\x69\x79\x74\x78\x43\x26"
+                         "\x7b\xde\x3f\xf1\xf5\x4e\x14\xd9"
+                         "\x15\xf5\x75\xb5\x2e\x19\xf3\x0c"
+                         "\x48\x72\xd6\x71\x6d\x03\x6e\xaa"
+                         "\xa7\x08\xf9\xaa\x70\xa3\x0f\x4d"
+                         "\x12\x8a\xdd\xe3\x39\x73\x7e\xa7"
+                         "\xea\x1f\x6d\x06\x26\x2a\xf2\xc5"
+                         "\x52\xb4\xbf\xfd\x52\x0c\x06\x60"
+                         "\x90\xd1\xb2\x7b\x56\xae\xac\x58"
+                         "\x5a\x6b\x50\x2a\xf5\xe0\x30\x3c"
+                         "\x2a\x98\x0f\x1b\x5b\x0a\x84\x6c"
+                         "\x31\xae\x92\xe2\xd4\xbb\x7f\x59"
+                         "\x26\x10\xb9\x89\x37\x68\x26\xbf"
+                         "\x41\xc8\x49\xc4\x70\x35\x7d\xff"
+                         "\x2d\x7f\xf6\x8a\x93\x68\x8c\x78"
+                         "\x0d\x53\xce\x7d\xff\x7d\xfb\xae"
+                         "\x13\x1b\x75\xc4\x78\xd7\x71\xd8"
+                         "\xea\xd3\xf4\x9d\x95\x64\x8e\xb4"
+                         "\xde\xb8\xe4\xa6\x68\xc8\xae\x73"
+                         "\x58\xaf\xa8\xb0\x5a\x20\xde\x87"
+                         "\x43\xb9\x0f\xe3\xad\x41\x4b\xd5"
+                         "\xb7\xad\x16\x00\xa6\xff\xf6\x74"
+                         "\xbf\x8c\x9f\xb3\x58\x1b\xb6\x55"
+                         "\xa9\x90\x56\x28\xf0\xb5\x13\x4e"
+                         "\x9e\xf7\x25\x86\xe0\x07\x7b\x98"
+                         "\xd8\x60\x5d\x38\x95\x3c\xe4\x22"
+                         "\x16\x2f\xb2\xa2\xaf\xe8\x90\x17"
+                         "\xec\x11\x83\x1a\xf4\xa9\x26\xda"
+                         "\x39\x72\xf5\x94\x61\x05\x51\xec"
+                         "\xa8\x30\x8b\x2c\x13\xd0\x72\xac"
+                         "\xb9\xd2\xa0\x4c\x4b\x78\xe8\x6e"
+                         "\x04\x85\xe9\x04\x49\x82\x91\xff"
+                         "\x89\xe5\xab\x4c\xaa\x37\x03\x12"
+                         "\xca\x8b\x74\x10\xfd\x9e\xd9\x7b"
+                         "\xcb\xdb\x82\x6e\xce\x2e\x33\x39"
+                         "\xce\xd2\x84\x6e\x34\x71\x51\x6e"
+                         "\x0d\xd6\x01\x87\xc7\xfa\x0a\xd3"
+                         "\xad\x36\xf3\x4c\x9f\x96\x5e\x62"
+                         "\x62\x54\xc3\x03\x78\xd6\xab\xdd"
+                         "\x89\x73\x55\x25\x30\xf8\xa7\xe6"
+                         "\x4f\x11\x0c\x7c\x0a\xa1\x2b\x7b"
+                         "\x3d\x0d\xde\x81\xd4\x9d\x0b\xae"
+                         "\xdf\x00\xf9\x4c\xb6\x90\x8e\x16"
+                         "\xcb\x11\xc8\xd1\x2e\x73\x13\x75"
+                         "\x75\x3e\xaa\xf5\xee\x02\xb3\x18"
+                         "\xa6\x2d\xf5\x3b\x51\xd1\x1f\x47"
+                         "\x6b\x2c\xdb\xc4\x10\xe0\xc8\xba"
+                         "\x9d\xac\xb1\x9d\x75\xd5\x41\x0e"
+                         "\x7e\xbe\x18\x5b\xa4\x1f\xf8\x22"
+                         "\x4c\xc1\x68\xda\x6d\x51\x34\x6c"
+                         "\x19\x59\xec\xb5\xb1\xec\xa7\x03"
+                         "\xca\x54\x99\x63\x05\x6c\xb1\xac"
+                         "\x9c\x31\xd6\xdb\xba\x7b\x14\x12"
+                         "\x7a\xc3\x2f\xbf\x8d\xdc\x37\x46"
+                         "\xdb\xd2\xbc\xd4\x2f\xab\x30\xd5"
+                         "\xed\x34\x99\x8e\x83\x3e\xbe\x4c"
+                         "\x86\x79\x58\xe0\x33\x8d\x9a\xb8"
+                         "\xa9\xa6\x90\x46\xa2\x02\xb8\xdd"
+                         "\xf5\xf9\x1a\x5c\x8c\x01\xaa\x6e"
+                         "\xb4\x22\x12\xf5\x0c\x1b\x9b\x7a"
+                         "\xc3\x80\xf3\x06\x00\x5f\x30\xd5"
+                         "\x06\xdb\x7d\x82\xc2\xd4\x0b\x4c"
+                         "\x5f\xe9\xc5\xf5\xdf\x97\x12\xbf"
+                         "\x56\xaf\x9b\x69\xcd\xee\x30\xb4"
+                         "\xa8\x71\xff\x3e\x7d\x73\x7a\xb4"
+                         "\x0d\xa5\x46\x7a\xf3\xf4\x15\x87"
+                         "\x5d\x93\x2b\x8c\x37\x64\xb5\xdd"
+                         "\x48\xd1\xe5\x8c\xae\xd4\xf1\x76"
+                         "\xda\xf4\xba\x9e\x25\x0e\xad\xa3"
+                         "\x0d\x08\x7c\xa8\x82\x16\x8d\x90"
+                         "\x56\x40\x16\x84\xe7\x22\x53\x3a"
+                         "\x58\xbc\xb9\x8f\x33\xc8\xc2\x84"
+                         "\x22\xe6\x0d\xe7\xb3\xdc\x5d\xdf"
+                         "\xd7\x2a\x36\xe4\x16\x06\x07\xd2"
+                         "\x97\x60\xb2\xf5\x5e\x14\xc9\xfd"
+                         "\x8b\x05\xd1\xce\xee\x9a\x65\x99"
+                         "\xb7\xae\x19\xb7\xc8\xbc\xd5\xa2"
+                         "\x7b\x95\xe1\xcc\xba\x0d\xdc\x8a"
+                         "\x1d\x59\x52\x50\xaa\x16\x02\x82"
+                         "\xdf\x61\x33\x2e\x44\xce\x49\xc7"
+                         "\xe5\xc6\x2e\x76\xcf\x80\x52\xf0"
+                         "\x3d\x17\x34\x47\x3f\xd3\x80\x48"
+                         "\xa2\xba\xd5\xc7\x7b\x02\x28\xdb"
+                         "\xac\x44\xc7\x6e\x05\x5c\xc2\x79"
+                         "\xb3\x7d\x6a\x47\x77\x66\xf1\x38"
+                         "\xf0\xf5\x4f\x27\x1a\x31\xca\x6c"
+                         "\x72\x95\x92\x8e\x3f\xb0\xec\x1d"
+                         "\xc7\x2a\xff\x73\xee\xdf\x55\x80"
+                         "\x93\xd2\xbd\x34\xd3\x9f\x00\x51"
+                         "\xfb\x2e\x41\xba\x6c\x5a\x7c\x17"
+                         "\x7f\xe6\x70\xac\x8d\x39\x3f\x77"
+                         "\xe2\x23\xac\x8f\x72\x4e\xe4\x53"
+                         "\xcc\xf1\x1b\xf1\x35\xfe\x52\xa4"
+                         "\xd6\xb8\x40\x6b\xc1\xfd\xa0\xa1"
+                         "\xf5\x46\x65\xc2\x50\xbb\x43\xe2"
+                         "\xd1\x43\x28\x34\x74\xf5\x87\xa0"
+                         "\xf2\x5e\x27\x3b\x59\x2b\x3e\x49"
+                         "\xdf\x46\xee\xaf\x71\xd7\x32\x36"
+                         "\xc7\x14\x0b\x58\x6e\x3e\x2d\x41"
+                         "\xfa\x75\x66\x3a\x54\xe0\xb2\xb9"
+                         "\xaf\xdd\x04\x80\x15\x19\x3f\x6f"
+                         "\xce\x12\xb4\xd8\xe8\x89\x3c\x05"
+                         "\x30\xeb\xf3\x3d\xcd\x27\xec\xdc"
+                         "\x56\x70\x12\xcf\x78\x2b\x77\xbf"
+                         "\x22\xf0\x1b\x17\x9c\xcc\xd6\x1b"
+                         "\x2d\x3d\xa0\x3b\xd8\xc9\x70\xa4"
+                         "\x7a\x3e\x07\xb9\x06\xc3\xfa\xb0"
+                         "\x33\xee\xc1\xd8\xf6\xe0\xf0\xb2"
+                         "\x61\x12\x69\xb0\x5f\x28\x99\xda"
+                         "\xc3\x61\x48\xfa\x07\x16\x03\xc4"
+                         "\xa8\xe1\x3c\xe8\x0e\x64\x15\x30"
+                         "\xc1\x9d\x84\x2f\x73\x98\x0e\x3a"
+                         "\xf2\x86\x21\xa4\x9e\x1d\xb5\x86"
+                         "\x16\xdb\x2b\x9a\x06\x64\x8e\x79"
+                         "\x8d\x76\x3e\xc3\xc2\x64\x44\xe3"
+                         "\xda\xbc\x1a\x52\xd7\x61\x03\x65"
+                         "\x54\x32\x77\x01\xed\x9d\x8a\x43"
+                         "\x25\x24\xe3\xc1\xbe\xb8\x2f\xcb"
+                         "\x89\x14\x64\xab\xf6\xa0\x6e\x02"
+                         "\x57\xe4\x7d\xa9\x4e\x9a\x03\x36"
+                         "\xad\xf1\xb1\xfc\x0b\xe6\x79\x51"
+                         "\x9f\x81\x77\xc4\x14\x78\x9d\xbf"
+                         "\xb6\xd6\xa3\x8c\xba\x0b\x26\xe7"
+                         "\xc8\xb9\x5c\xcc\xe1\x5f\xd5\xc6"
+                         "\xc4\xca\xc2\xa3\x45\xba\x94\x13"
+                         "\xb2\x8f\xc3\x54\x01\x09\xe7\x8b"
+                         "\xda\x2a\x0a\x11\x02\x43\xcb\x57"
+                         "\xc9\xcc\xb5\x5c\xab\xc4\xec\x54"
+                         "\x00\x06\x34\xe1\x6e\x03\x89\x7c"
+                         "\xc6\xfb\x6a\xc7\x60\x43\xd6\xc5"
+                         "\xb5\x68\x72\x89\x8f\x42\xc3\x74"
+                         "\xbd\x25\xaa\x9f\x67\xb5\xdf\x26"
+                         "\x20\xe8\xb7\x01\x3c\xe4\x77\xce"
+                         "\xc4\x65\xa7\x23\x79\xea\x33\xc7"
+                         "\x82\x14\x5c\x82\xf2\x4e\x3d\xf6"
+                         "\xc6\x4a\x0e\x29\xbb\xec\x44\xcd"
+                         "\x2f\xd1\x4f\x21\x71\xa9\xce\x0f"
+                         "\x5c\xf2\x72\x5c\x08\x2e\x21\xd2"
+                         "\xc3\x29\x13\xd8\xac\xc3\xda\x13"
+                         "\x1a\x9d\xa7\x71\x1d\x27\x1d\x27"
+                         "\x1d\xea\xab\x44\x79\xad\xe5\xeb"
+                         "\xef\x1f\x22\x0a\x44\x4f\xcb\x87"
+                         "\xa7\x58\x71\x0e\x66\xf8\x60\xbf"
+                         "\x60\x74\x4a\xb4\xec\x2e\xfe\xd3"
+                         "\xf5\xb8\xfe\x46\x08\x50\x99\x6c"
+                         "\x66\xa5\xa8\x34\x44\xb5\xe5\xf0"
+                         "\xdd\x2c\x67\x4e\x35\x96\x8e\x67"
+                         "\x48\x3f\x5f\x37\x44\x60\x51\x2e"
+                         "\x14\x91\x5e\x57\xc3\x0e\x79\x77"
+                         "\x2f\x03\xf4\xe2\x1c\x72\xbf\x85"
+                         "\x5d\xd3\x17\xdf\x6c\xc5\x70\x24"
+                         "\x42\xdf\x51\x4e\x2a\xb2\xd2\x5b"
+                         "\x9e\x69\x83\x41\x11\xfe\x73\x22"
+                         "\xde\x8a\x9e\xd8\x8a\xfb\x20\x38"
+                         "\xd8\x47\x6f\xd5\xed\x8f\x41\xfd"
+                         "\x13\x7a\x18\x03\x7d\x0f\xcd\x7d"
+                         "\xa6\x7d\x31\x9e\xf1\x8f\x30\xa3"
+                         "\x8b\x4c\x24\xb7\xf5\x48\xd7\xd9"
+                         "\x12\xe7\x84\x97\x5c\x31\x6d\xfb"
+                         "\xdf\xf3\xd3\xd1\xd5\x0c\x30\x06"
+                         "\x01\x6a\xbc\x6c\x78\x7b\xa6\x50"
+                         "\xfa\x0f\x3c\x42\x2d\xa5\xa3\x3b"
+                         "\xcf\x62\x50\xff\x71\x6d\xe7\xda"
+                         "\x27\xab\xc6\x67\x16\x65\x68\x64"
+                         "\xc7\xd5\x5f\x81\xa9\xf6\x65\xb3"
+                         "\x5e\x43\x91\x16\xcd\x3d\x55\x37"
+                         "\x55\xb3\xf0\x28\xc5\x54\x19\xc0"
+                         "\xe0\xd6\x2a\x61\xd4\xc8\x72\x51"
+                         "\xe9\xa1\x7b\x48\x21\xad\x44\x09"
+                         "\xe4\x01\x61\x3c\x8a\x5b\xf9\xa1"
+                         "\x6e\x1b\xdf\xc0\x04\xa8\x8b\xf2"
+                         "\x21\xbe\x34\x7b\xfc\xa1\xcd\xc9"
+                         "\xa9\x96\xf4\xa4\x4c\xf7\x4e\x8f"
+                         "\x84\xcc\xd3\xa8\x92\x77\x8f\x36"
+                         "\xe2\x2e\x8c\x33\xe8\x84\xa6\x0c"
+                         "\x6c\x8a\xda\x14\x32\xc2\x96\xff"
+                         "\xc6\x4a\xc2\x9b\x30\x7f\xd1\x29"
+                         "\xc0\xd5\x78\x41\x00\x80\x80\x03"
+                         "\x2a\xb1\xde\x26\x03\x48\x49\xee"
+                         "\x57\x14\x76\x51\x3c\x36\x5d\x0a"
+                         "\x5c\x9f\xe8\xd8\x53\xdb\x4f\xd4"
+                         "\x38\xbf\x66\xc9\x75\x12\x18\x75"
+                         "\x34\x2d\x93\x22\x96\x51\x24\x6e"
+                         "\x4e\xd9\x30\xea\x67\xff\x92\x1c"
+                         "\x16\x26\xe9\xb5\x33\xab\x8c\x22"
+                         "\x47\xdb\xa0\x2c\x08\xf0\x12\x69"
+                         "\x7e\x93\x52\xda\xa5\xe5\xca\xc1"
+                         "\x0f\x55\x2a\xbd\x09\x30\x88\x1b"
+                         "\x9c\xc6\x9f\xe6\xdb\xa6\x92\xeb"
+                         "\xf4\xbd\x5c\xc4\xdb\xc6\x71\x09"
+                         "\xab\x5e\x48\x0c\xed\x6f\xda\x8e"
+                         "\x8d\x0c\x98\x71\x7d\x10\xd0\x9c"
+                         "\x20\x9b\x79\x53\x26\x5d\xb9\x85"
+                         "\x8a\x31\xb8\xc5\x1c\x97\xde\x88"
+                         "\x61\x55\x7f\x7c\x21\x06\xea\xc4"
+                         "\x5f\xaf\xf2\xf0\xd5\x5e\x7d\xb4"
+                         "\x6e\xcf\xe9\xae\x1b\x0e\x11\x80"
+                         "\xc1\x9a\x74\x7e\x52\x6f\xa0\xb7"
+                         "\x24\xcd\x8d\x0a\x11\x40\x63\x72"
+                         "\xfa\xe2\xc5\xb3\x94\xef\x29\xa2"
+                         "\x1a\x23\x43\x04\x37\x55\x0d\xe9"
+                         "\x83\xb2\x29\x51\x49\x64\xa0\xbd"
+                         "\xde\x73\xfd\xa5\x7c\x95\x70\x62"
+                         "\x58\xdc\xe2\xd0\xbf\x98\xf5\x8a"
+                         "\x6a\xfd\xce\xa8\x0e\x42\x2a\xeb"
+                         "\xd2\xff\x83\x27\x53\x5c\xa0\x6e"
+                         "\x93\xef\xe2\xb9\x5d\x35\xd6\x98"
+                         "\xf6\x71\x19\x7a\x54\xa1\xa7\xe8"
+                         "\x09\xfe\xf6\x9e\xc7\xbd\x3e\x29"
+                         "\xbd\x6b\x17\xf4\xe7\x3e\x10\x5c"
+                         "\xc1\xd2\x59\x4f\x4b\x12\x1a\x5b"
+                         "\x50\x80\x59\xb9\xec\x13\x66\xa8"
+                         "\xd2\x31\x7b\x6a\x61\x22\xdd\x7d"
+                         "\x61\xee\x87\x16\x46\x9f\xf9\xc7"
+                         "\x41\xee\x74\xf8\xd0\x96\x2c\x76"
+                         "\x2a\xac\x7d\x6e\x9f\x0e\x7f\x95"
+                         "\xfe\x50\x16\xb2\x23\xca\x62\xd5"
+                         "\x68\xcf\x07\x3f\x3f\x97\x85\x2a"
+                         "\x0c\x25\x45\xba\xdb\x32\xcb\x83"
+                         "\x8c\x4f\xe0\x6d\x9a\x99\xf9\xc9"
+                         "\xda\xd4\x19\x31\xc1\x7c\x6d\xd9"
+                         "\x9c\x56\xd3\xec\xc1\x81\x4c\xed"
+                         "\x28\x9d\x87\xeb\x19\xd7\x1a\x4f"
+                         "\x04\x6a\xcb\x1f\xcf\x1f\xa2\x16"
+                         "\xfc\x2a\x0d\xa1\x14\x2d\xfa\xc5"
+                         "\x5a\xd2\xc5\xf9\x19\x7c\x20\x1f"
+                         "\x2d\x10\xc0\x66\x7c\xd9\x2d\xe5"
+                         "\x88\x70\x59\xa7\x85\xd5\x2e\x7c"
+                         "\x5c\xe3\xb7\x12\xd6\x97\x3f\x29",
+               .psize  = 2048,
+               .digest = "\x37\x90\x92\xc2\xeb\x01\x87\xd9"
+                         "\x95\xc7\x91\xc3\x17\x8b\x38\x52",
+       }
+};
+
+
 /*
  * DES test vectors.
  */
include/crypto/nhpoly1305.h new file +74 -1
new file mode 100644
index 000000000000..53c04423c582
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Common values and helper functions for the NHPoly1305 hash function.
+ */
+
+#ifndef _NHPOLY1305_H
+#define _NHPOLY1305_H
+
+#include <crypto/hash.h>
+#include <crypto/poly1305.h>
+
+/* NH parameterization: */
+
+/* Endianness: little */
+/* Word size: 32 bits (works well on NEON, SSE2, AVX2) */
+
+/* Stride: 2 words (optimal on ARM32 NEON; works okay on other CPUs too) */
+#define NH_PAIR_STRIDE         2
+#define NH_MESSAGE_UNIT                (NH_PAIR_STRIDE * 2 * sizeof(u32))
+
+/* Num passes (Toeplitz iteration count): 4, to give ? = 2^{-128} */
+#define NH_NUM_PASSES          4
+#define NH_HASH_BYTES          (NH_NUM_PASSES * sizeof(u64))
+
+/* Max message size: 1024 bytes (32x compression factor) */
+#define NH_NUM_STRIDES         64
+#define NH_MESSAGE_WORDS       (NH_PAIR_STRIDE * 2 * NH_NUM_STRIDES)
+#define NH_MESSAGE_BYTES       (NH_MESSAGE_WORDS * sizeof(u32))
+#define NH_KEY_WORDS           (NH_MESSAGE_WORDS + \
+                                NH_PAIR_STRIDE * 2 * (NH_NUM_PASSES - 1))
+#define NH_KEY_BYTES           (NH_KEY_WORDS * sizeof(u32))
+
+#define NHPOLY1305_KEY_SIZE    (POLY1305_BLOCK_SIZE + NH_KEY_BYTES)
+
+struct nhpoly1305_key {
+       struct poly1305_key poly_key;
+       u32 nh_key[NH_KEY_WORDS];
+};
+
+struct nhpoly1305_state {
+
+       /* Running total of polynomial evaluation */
+       struct poly1305_state poly_state;
+
+       /* Partial block buffer */
+       u8 buffer[NH_MESSAGE_UNIT];
+       unsigned int buflen;
+
+       /*
+        * Number of bytes remaining until the current NH message reaches
+        * NH_MESSAGE_BYTES.  When nonzero, 'nh_hash' holds the partial NH hash.
+        */
+       unsigned int nh_remaining;
+
+       __le64 nh_hash[NH_NUM_PASSES];
+};
+
+typedef void (*nh_t)(const u32 *key, const u8 *message, size_t message_len,
+                    __le64 hash[NH_NUM_PASSES]);
+
+int crypto_nhpoly1305_setkey(struct crypto_shash *tfm,
+                            const u8 *key, unsigned int keylen);
+
+int crypto_nhpoly1305_init(struct shash_desc *desc);
+int crypto_nhpoly1305_update(struct shash_desc *desc,
+                            const u8 *src, unsigned int srclen);
+int crypto_nhpoly1305_update_helper(struct shash_desc *desc,
+                                   const u8 *src, unsigned int srclen,
+                                   nh_t nh_fn);
+int crypto_nhpoly1305_final(struct shash_desc *desc, u8 *dst);
+int crypto_nhpoly1305_final_helper(struct shash_desc *desc, u8 *dst,
+                                  nh_t nh_fn);
+
+#endif /* _NHPOLY1305_H */
--

2.19.1.1215.g8438c0b245-goog

author maintainer
#16 lore raw

PATCH v4 13/14 crypto: arm/nhpoly1305 - add NEON-accelerated NHPoly1305

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

Add an ARM NEON implementation of NHPoly1305, an ?-almost-?-universal hash function used in the Adiantum encryption mode. For now, only the NH portion is actually NEON-accelerated; the Poly1305 part is less performance-critical so is just implemented in C.

---
 arch/arm/crypto/Kconfig                |   5 ++
 arch/arm/crypto/Makefile               |   2 +
 arch/arm/crypto/nh-neon-core.S         | 116 +++++++++++++++++++++++++
 arch/arm/crypto/nhpoly1305-neon-glue.c |  77 ++++++++++++++++
 4 files changed, 200 insertions(+)
 create mode 100644 arch/arm/crypto/nh-neon-core.S
 create mode 100644 arch/arm/crypto/nhpoly1305-neon-glue.c
arch/arm/crypto/Kconfig +5 -0
index 59c674cf08ef..a95322b59799 100644
@@ -131,4 +131,9 @@ config CRYPTO_CHACHA20_NEON
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_CHACHA20
 
+config CRYPTO_NHPOLY1305_NEON
+	tristate "NEON accelerated NHPoly1305 hash function (for Adiantum)"
+	depends on KERNEL_MODE_NEON
+	select CRYPTO_NHPOLY1305
+
 endif
arch/arm/crypto/Makefile +2 -0
index 005482ff9504..b65d6bfab8e6 100644
@@ -10,6 +10,7 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
 obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
 obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o
 obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
+obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o
 
 ce-obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
 ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
@@ -53,6 +54,7 @@ ghash-arm-ce-y	:= ghash-ce-core.o ghash-ce-glue.o
 crct10dif-arm-ce-y	:= crct10dif-ce-core.o crct10dif-ce-glue.o
 crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o
 chacha-neon-y := chacha-neon-core.o chacha-neon-glue.o
+nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o
 
 ifdef REGENERATE_ARM_CRYPTO
 quiet_cmd_perl = PERL    $@
arch/arm/crypto/nh-neon-core.S new file +116 -0

116 lines not on this page · raw message

arch/arm/crypto/nhpoly1305-neon-glue.c new file +77 -0

77 lines not on this page · raw message

Signature · 1 line
2.19.1.1215.g8438c0b245-goog
Reviewed-by on v4 13/14
#17 lore raw

Re: [PATCH v4 13/14] crypto: arm/nhpoly1305 - add NEON-accelerated NHPoly1305

Quoted 9 lines · Eric Biggers

From: Eric Biggers <[email protected]>

Add an ARM NEON implementation of NHPoly1305, an ?-almost-?-universal hash function used in the Adiantum encryption mode. For now, only the NH portion is actually NEON-accelerated; the Poly1305 part is less performance-critical so is just implemented in C.

Quoted 251 lines
---
 arch/arm/crypto/Kconfig                |   5 ++
 arch/arm/crypto/Makefile               |   2 +
 arch/arm/crypto/nh-neon-core.S         | 116 +++++++++++++++++++++++++
 arch/arm/crypto/nhpoly1305-neon-glue.c |  77 ++++++++++++++++
 4 files changed, 200 insertions(+)
 create mode 100644 arch/arm/crypto/nh-neon-core.S
 create mode 100644 arch/arm/crypto/nhpoly1305-neon-glue.c
arch/arm/crypto/Kconfig +5 -0
index 59c674cf08ef..a95322b59799 100644
@@ -131,4 +131,9 @@ config CRYPTO_CHACHA20_NEON
        select CRYPTO_BLKCIPHER
        select CRYPTO_CHACHA20
 
+config CRYPTO_NHPOLY1305_NEON
+       tristate "NEON accelerated NHPoly1305 hash function (for Adiantum)"
+       depends on KERNEL_MODE_NEON
+       select CRYPTO_NHPOLY1305
+
 endif
arch/arm/crypto/Makefile +2 -0
index 005482ff9504..b65d6bfab8e6 100644
@@ -10,6 +10,7 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
 obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
 obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o
 obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
+obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o
 
 ce-obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
 ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
@@ -53,6 +54,7 @@ ghash-arm-ce-y        := ghash-ce-core.o ghash-ce-glue.o
 crct10dif-arm-ce-y     := crct10dif-ce-core.o crct10dif-ce-glue.o
 crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o
 chacha-neon-y := chacha-neon-core.o chacha-neon-glue.o
+nhpoly1305-neon-y := nh-neon-core.o nhpoly1305-neon-glue.o
 
 ifdef REGENERATE_ARM_CRYPTO
 quiet_cmd_perl = PERL    $@
arch/arm/crypto/nh-neon-core.S new file +116 -0
new file mode 100644
index 000000000000..434d80ab531c
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * NH - ?-almost-universal hash function, NEON accelerated version
+ *
+ * Copyright 2018 Google LLC
+ *
+ * Author: Eric Biggers <[email protected]>
+ */
+
+#include <linux/linkage.h>
+
+       .text
+       .fpu            neon
+
+       KEY             .req    r0
+       MESSAGE         .req    r1
+       MESSAGE_LEN     .req    r2
+       HASH            .req    r3
+
+       PASS0_SUMS      .req    q0
+       PASS0_SUM_A     .req    d0
+       PASS0_SUM_B     .req    d1
+       PASS1_SUMS      .req    q1
+       PASS1_SUM_A     .req    d2
+       PASS1_SUM_B     .req    d3
+       PASS2_SUMS      .req    q2
+       PASS2_SUM_A     .req    d4
+       PASS2_SUM_B     .req    d5
+       PASS3_SUMS      .req    q3
+       PASS3_SUM_A     .req    d6
+       PASS3_SUM_B     .req    d7
+       K0              .req    q4
+       K1              .req    q5
+       K2              .req    q6
+       K3              .req    q7
+       T0              .req    q8
+       T0_L            .req    d16
+       T0_H            .req    d17
+       T1              .req    q9
+       T1_L            .req    d18
+       T1_H            .req    d19
+       T2              .req    q10
+       T2_L            .req    d20
+       T2_H            .req    d21
+       T3              .req    q11
+       T3_L            .req    d22
+       T3_H            .req    d23
+
+.macro _nh_stride      k0, k1, k2, k3
+
+       // Load next message stride
+       vld1.8          {T3}, [MESSAGE]!
+
+       // Load next key stride
+       vld1.32         {\k3}, [KEY]!
+
+       // Add message words to key words
+       vadd.u32        T0, T3, \k0
+       vadd.u32        T1, T3, \k1
+       vadd.u32        T2, T3, \k2
+       vadd.u32        T3, T3, \k3
+
+       // Multiply 32x32 => 64 and accumulate
+       vmlal.u32       PASS0_SUMS, T0_L, T0_H
+       vmlal.u32       PASS1_SUMS, T1_L, T1_H
+       vmlal.u32       PASS2_SUMS, T2_L, T2_H
+       vmlal.u32       PASS3_SUMS, T3_L, T3_H
+.endm
+
+/*
+ * void nh_neon(const u32 *key, const u8 *message, size_t message_len,
+ *             u8 hash[NH_HASH_BYTES])
+ *
+ * It's guaranteed that message_len % 16 == 0.
+ */
+ENTRY(nh_neon)
+
+       vld1.32         {K0,K1}, [KEY]!
+         vmov.u64      PASS0_SUMS, #0
+         vmov.u64      PASS1_SUMS, #0
+       vld1.32         {K2}, [KEY]!
+         vmov.u64      PASS2_SUMS, #0
+         vmov.u64      PASS3_SUMS, #0
+
+       subs            MESSAGE_LEN, MESSAGE_LEN, #64
+       blt             .Lloop4_done
+.Lloop4:
+       _nh_stride      K0, K1, K2, K3
+       _nh_stride      K1, K2, K3, K0
+       _nh_stride      K2, K3, K0, K1
+       _nh_stride      K3, K0, K1, K2
+       subs            MESSAGE_LEN, MESSAGE_LEN, #64
+       bge             .Lloop4
+
+.Lloop4_done:
+       ands            MESSAGE_LEN, MESSAGE_LEN, #63
+       beq             .Ldone
+       _nh_stride      K0, K1, K2, K3
+
+       subs            MESSAGE_LEN, MESSAGE_LEN, #16
+       beq             .Ldone
+       _nh_stride      K1, K2, K3, K0
+
+       subs            MESSAGE_LEN, MESSAGE_LEN, #16
+       beq             .Ldone
+       _nh_stride      K2, K3, K0, K1
+
+.Ldone:
+       // Sum the accumulators for each pass, then store the sums to 'hash'
+       vadd.u64        T0_L, PASS0_SUM_A, PASS0_SUM_B
+       vadd.u64        T0_H, PASS1_SUM_A, PASS1_SUM_B
+       vadd.u64        T1_L, PASS2_SUM_A, PASS2_SUM_B
+       vadd.u64        T1_H, PASS3_SUM_A, PASS3_SUM_B
+       vst1.8          {T0-T1}, [HASH]
+       bx              lr
+ENDPROC(nh_neon)
arch/arm/crypto/nhpoly1305-neon-glue.c new file +77 -1
new file mode 100644
index 000000000000..49aae87cb2bc
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * NHPoly1305 - ?-almost-?-universal hash function for Adiantum
+ * (NEON accelerated version)
+ *
+ * Copyright 2018 Google LLC
+ */
+
+#include <asm/neon.h>
+#include <asm/simd.h>
+#include <crypto/internal/hash.h>
+#include <crypto/nhpoly1305.h>
+#include <linux/module.h>
+
+asmlinkage void nh_neon(const u32 *key, const u8 *message, size_t message_len,
+                       u8 hash[NH_HASH_BYTES]);
+
+/* wrapper to avoid indirect call to assembly, which doesn't work with CFI */
+static void _nh_neon(const u32 *key, const u8 *message, size_t message_len,
+                    __le64 hash[NH_NUM_PASSES])
+{
+       nh_neon(key, message, message_len, (u8 *)hash);
+}
+
+static int nhpoly1305_neon_update(struct shash_desc *desc,
+                                 const u8 *src, unsigned int srclen)
+{
+       if (srclen < 64 || !may_use_simd())
+               return crypto_nhpoly1305_update(desc, src, srclen);
+
+       do {
+               unsigned int n = min_t(unsigned int, srclen, PAGE_SIZE);
+
+               kernel_neon_begin();
+               crypto_nhpoly1305_update_helper(desc, src, n, _nh_neon);
+               kernel_neon_end();
+               src += n;
+               srclen -= n;
+       } while (srclen);
+       return 0;
+}
+
+static struct shash_alg nhpoly1305_alg = {
+       .base.cra_name          = "nhpoly1305",
+       .base.cra_driver_name   = "nhpoly1305-neon",
+       .base.cra_priority      = 200,
+       .base.cra_ctxsize       = sizeof(struct nhpoly1305_key),
+       .base.cra_module        = THIS_MODULE,
+       .digestsize             = POLY1305_DIGEST_SIZE,
+       .init                   = crypto_nhpoly1305_init,
+       .update                 = nhpoly1305_neon_update,
+       .final                  = crypto_nhpoly1305_final,
+       .setkey                 = crypto_nhpoly1305_setkey,
+       .descsize               = sizeof(struct nhpoly1305_state),
+};
+
+static int __init nhpoly1305_mod_init(void)
+{
+       if (!(elf_hwcap & HWCAP_NEON))
+               return -ENODEV;
+
+       return crypto_register_shash(&nhpoly1305_alg);
+}
+
+static void __exit nhpoly1305_mod_exit(void)
+{
+       crypto_unregister_shash(&nhpoly1305_alg);
+}
+
+module_init(nhpoly1305_mod_init);
+module_exit(nhpoly1305_mod_exit);
+
+MODULE_DESCRIPTION("NHPoly1305 ?-almost-?-universal hash function (NEON-accelerated)");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Eric Biggers <[email protected]>");
+MODULE_ALIAS_CRYPTO("nhpoly1305");
+MODULE_ALIAS_CRYPTO("nhpoly1305-neon");
--

2.19.1.1215.g8438c0b245-goog

author maintainer
#18 lore raw

PATCH v4 14/14 crypto: adiantum - add Adiantum support

In reply to Eric Biggers

From: Eric Biggers <[email protected]>

Add support for the Adiantum encryption mode. Adiantum was designed by Paul Crowley and is specified by our paper:

Adiantum: length-preserving encryption for entry-level processors
(https://eprint.iacr.org/2018/720.pdf)

See our paper for full details; this patch only provides an overview.

Adiantum is a tweakable, length-preserving encryption mode designed for fast and secure disk encryption, especially on CPUs without dedicated crypto instructions. Adiantum encrypts each sector using the XChaCha12 stream cipher, two passes of an ?-almost-?-universal (?A?U) hash function, and an invocation of the AES-256 block cipher on a single 16-byte block. On CPUs without AES instructions, Adiantum is much faster than AES-XTS; for example, on ARM Cortex-A7, on 4096-byte sectors Adiantum encryption is about 4 times faster than AES-256-XTS encryption, and decryption about 5 times faster.

Adiantum is a specialization of the more general HBSH construction. Our earlier proposal, HPolyC, was also a HBSH specialization, but it used a different ?A?U hash function, one based on Poly1305 only. Adiantum's ?A?U hash function, which is based primarily on the "NH" hash function like that used in UMAC (RFC4418), is about twice as fast as HPolyC's; consequently, Adiantum is about 20% faster than HPolyC.

This speed comes with no loss of security: Adiantum is provably just as secure as HPolyC, in fact slightly *more* secure. Like HPolyC, Adiantum's security is reducible to that of XChaCha12 and AES-256, subject to a security bound. XChaCha12 itself has a security reduction to ChaCha12. Therefore, one need not "trust" Adiantum; one need only trust ChaCha12 and AES-256. Note that the ?A?U hash function is only used for its proven combinatorical properties so cannot be "broken".

Adiantum is also a true wide-block encryption mode, so flipping any plaintext bit in the sector scrambles the entire ciphertext, and vice versa. No other such mode is available in the kernel currently; doing the same with XTS scrambles only 16 bytes. Adiantum also supports arbitrary-length tweaks and naturally supports any length input >= 16 bytes without needing "ciphertext stealing".

For the stream cipher, Adiantum uses XChaCha12 rather than XChaCha20 in order to make encryption feasible on the widest range of devices. Although the 20-round variant is quite popular, the best known attacks on ChaCha are on only 7 rounds, so ChaCha12 still has a substantial security margin; in fact, larger than AES-256's. 12-round Salsa20 is also the eSTREAM recommendation. For the block cipher, Adiantum uses AES-256, despite it having a lower security margin than XChaCha12 and needing table lookups, due to AES's extensive adoption and analysis making it the obvious first choice. Nevertheless, for flexibility this patch also permits the "adiantum" template to be instantiated with XChaCha20 and/or with an alternate block cipher.

We need Adiantum support in the kernel for use in dm-crypt and fscrypt, where currently the only other suitable options are block cipher modes such as AES-XTS. A big problem with this is that many low-end mobile devices (e.g. Android Go phones sold primarily in developing countries, as well as some smartwatches) still have CPUs that lack AES instructions, e.g. ARM Cortex-A7. Sadly, AES-XTS encryption is much too slow to be viable on these devices. We did find that some "lightweight" block ciphers are fast enough, but these suffer from problems such as not having much cryptanalysis or being too controversial.

The ChaCha stream cipher has excellent performance but is insecure to use directly for disk encryption, since each sector's IV is reused each time it is overwritten. Even restricting the threat model to offline attacks only isn't enough, since modern flash storage devices don't guarantee that "overwrites" are really overwrites, due to wear-leveling. Adiantum avoids this problem by constructing a
"tweakable super-pseudorandom permutation"; this is the strongest possible security model for length-preserving encryption.

Of course, storing random nonces along with the ciphertext would be the ideal solution. But doing that with existing hardware and filesystems runs into major practical problems; in most cases it would require data journaling (like dm-integrity) which severely degrades performance. Thus, for now length-preserving encryption is still needed.

---
 crypto/Kconfig    |  23 ++
 crypto/Makefile   |   1 +
 crypto/adiantum.c | 658 ++++++++++++++++++++++++++++++++++++++++++++++
 crypto/tcrypt.c   |  12 +
 crypto/testmgr.c  |  12 +
 crypto/testmgr.h  | 461 ++++++++++++++++++++++++++++++++
 6 files changed, 1167 insertions(+)
 create mode 100644 crypto/adiantum.c
crypto/Kconfig +23 -0
index eaeb8a986b7d..b6376d5d973e 100644
@@ -501,6 +501,29 @@ config CRYPTO_NHPOLY1305
 	select CRYPTO_HASH
 	select CRYPTO_POLY1305
 
+config CRYPTO_ADIANTUM
+	tristate "Adiantum support"
+	select CRYPTO_CHACHA20
+	select CRYPTO_POLY1305
+	select CRYPTO_NHPOLY1305
+	help
+	  Adiantum is a tweakable, length-preserving encryption mode
+	  designed for fast and secure disk encryption, especially on
+	  CPUs without dedicated crypto instructions.  It encrypts
+	  each sector using the XChaCha12 stream cipher, two passes of
+	  an ?-almost-?-universal hash function, and an invocation of
+	  the AES-256 block cipher on a single 16-byte block.  On CPUs
+	  without AES instructions, Adiantum is much faster than
+	  AES-XTS.
+
+	  Adiantum's security is provably reducible to that of its
+	  underlying stream and block ciphers, subject to a security
+	  bound.  Unlike XTS, Adiantum is a true wide-block encryption
+	  mode, so it actually provides an even stronger notion of
+	  security than XTS, subject to the security bound.
+
+	  If unsure, say N.
+
 comment "Hash modes"
 
 config CRYPTO_CMAC
crypto/Makefile +1 -0
index c3310c85f09f..5e789dc2d4fd 100644
@@ -85,6 +85,7 @@ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_XTS) += xts.o
 obj-$(CONFIG_CRYPTO_CTR) += ctr.o
 obj-$(CONFIG_CRYPTO_KEYWRAP) += keywrap.o
+obj-$(CONFIG_CRYPTO_ADIANTUM) += adiantum.o
 obj-$(CONFIG_CRYPTO_NHPOLY1305) += nhpoly1305.o
 obj-$(CONFIG_CRYPTO_GCM) += gcm.o
 obj-$(CONFIG_CRYPTO_CCM) += ccm.o
crypto/adiantum.c new file +658 -0

658 lines not on this page · raw message

crypto/tcrypt.c +12 -0
index 5fb120474902..0590a9204562 100644
@@ -2320,6 +2320,18 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
 		test_cipher_speed("ctr(sm4)", DECRYPT, sec, NULL, 0,
 				speed_template_16);
 		break;
+
+	case 219:
+		test_cipher_speed("adiantum(xchacha12,aes)", ENCRYPT, sec, NULL,
+				  0, speed_template_32);
+		test_cipher_speed("adiantum(xchacha12,aes)", DECRYPT, sec, NULL,
+				  0, speed_template_32);
+		test_cipher_speed("adiantum(xchacha20,aes)", ENCRYPT, sec, NULL,
+				  0, speed_template_32);
+		test_cipher_speed("adiantum(xchacha20,aes)", DECRYPT, sec, NULL,
+				  0, speed_template_32);
+		break;
+
 	case 300:
 		if (alg) {
 			test_hash_speed(alg, sec, generic_hash_speed_template);
crypto/testmgr.c +12 -0
index 665911c24786..0f684a414acb 100644
@@ -2404,6 +2404,18 @@ static int alg_test_null(const struct alg_test_desc *desc,
 /* Please keep this list sorted by algorithm name. */
 static const struct alg_test_desc alg_test_descs[] = {
 	{
+		.alg = "adiantum(xchacha12,aes)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = __VECS(adiantum_xchacha12_aes_tv_template)
+		},
+	}, {
+		.alg = "adiantum(xchacha20,aes)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = __VECS(adiantum_xchacha20_aes_tv_template)
+		},
+	}, {
 		.alg = "aegis128",
 		.test = alg_test_aead,
 		.suite = {
crypto/testmgr.h +461 -0

467 lines not on this page · raw message

Signature · 1 line
2.19.1.1215.g8438c0b245-goog
Reviewed-by on v4 14/14
#19 lore raw

Re: [PATCH v4 14/14] crypto: adiantum - add Adiantum support

Quoted 74 lines · Eric Biggers

From: Eric Biggers <[email protected]>

Add support for the Adiantum encryption mode. Adiantum was designed by Paul Crowley and is specified by our paper:

Adiantum: length-preserving encryption for entry-level processors
(https://eprint.iacr.org/2018/720.pdf)

See our paper for full details; this patch only provides an overview.

Adiantum is a tweakable, length-preserving encryption mode designed for fast and secure disk encryption, especially on CPUs without dedicated crypto instructions. Adiantum encrypts each sector using the XChaCha12 stream cipher, two passes of an ?-almost-?-universal (?A?U) hash function, and an invocation of the AES-256 block cipher on a single 16-byte block. On CPUs without AES instructions, Adiantum is much faster than AES-XTS; for example, on ARM Cortex-A7, on 4096-byte sectors Adiantum encryption is about 4 times faster than AES-256-XTS encryption, and decryption about 5 times faster.

Adiantum is a specialization of the more general HBSH construction. Our earlier proposal, HPolyC, was also a HBSH specialization, but it used a different ?A?U hash function, one based on Poly1305 only. Adiantum's ?A?U hash function, which is based primarily on the "NH" hash function like that used in UMAC (RFC4418), is about twice as fast as HPolyC's; consequently, Adiantum is about 20% faster than HPolyC.

This speed comes with no loss of security: Adiantum is provably just as secure as HPolyC, in fact slightly *more* secure. Like HPolyC, Adiantum's security is reducible to that of XChaCha12 and AES-256, subject to a security bound. XChaCha12 itself has a security reduction to ChaCha12. Therefore, one need not "trust" Adiantum; one need only trust ChaCha12 and AES-256. Note that the ?A?U hash function is only used for its proven combinatorical properties so cannot be "broken".

Adiantum is also a true wide-block encryption mode, so flipping any plaintext bit in the sector scrambles the entire ciphertext, and vice versa. No other such mode is available in the kernel currently; doing the same with XTS scrambles only 16 bytes. Adiantum also supports arbitrary-length tweaks and naturally supports any length input >= 16 bytes without needing "ciphertext stealing".

For the stream cipher, Adiantum uses XChaCha12 rather than XChaCha20 in order to make encryption feasible on the widest range of devices. Although the 20-round variant is quite popular, the best known attacks on ChaCha are on only 7 rounds, so ChaCha12 still has a substantial security margin; in fact, larger than AES-256's. 12-round Salsa20 is also the eSTREAM recommendation. For the block cipher, Adiantum uses AES-256, despite it having a lower security margin than XChaCha12 and needing table lookups, due to AES's extensive adoption and analysis making it the obvious first choice. Nevertheless, for flexibility this patch also permits the "adiantum" template to be instantiated with XChaCha20 and/or with an alternate block cipher.

We need Adiantum support in the kernel for use in dm-crypt and fscrypt, where currently the only other suitable options are block cipher modes such as AES-XTS. A big problem with this is that many low-end mobile devices (e.g. Android Go phones sold primarily in developing countries, as well as some smartwatches) still have CPUs that lack AES instructions, e.g. ARM Cortex-A7. Sadly, AES-XTS encryption is much too slow to be viable on these devices. We did find that some "lightweight" block ciphers are fast enough, but these suffer from problems such as not having much cryptanalysis or being too controversial.

The ChaCha stream cipher has excellent performance but is insecure to use directly for disk encryption, since each sector's IV is reused each time it is overwritten. Even restricting the threat model to offline attacks only isn't enough, since modern flash storage devices don't guarantee that "overwrites" are really overwrites, due to wear-leveling. Adiantum avoids this problem by constructing a
"tweakable super-pseudorandom permutation"; this is the strongest possible security model for length-preserving encryption.

Quoted 7 lines

Of course, storing random nonces along with the ciphertext would be the ideal solution. But doing that with existing hardware and filesystems runs into major practical problems; in most cases it would require data journaling (like dm-integrity) which severely degrades performance. Thus, for now length-preserving encryption is still needed.

Quoted 1,241 lines
---
 crypto/Kconfig    |  23 ++
 crypto/Makefile   |   1 +
 crypto/adiantum.c | 658 ++++++++++++++++++++++++++++++++++++++++++++++
 crypto/tcrypt.c   |  12 +
 crypto/testmgr.c  |  12 +
 crypto/testmgr.h  | 461 ++++++++++++++++++++++++++++++++
 6 files changed, 1167 insertions(+)
 create mode 100644 crypto/adiantum.c
crypto/Kconfig +23 -0
index eaeb8a986b7d..b6376d5d973e 100644
@@ -501,6 +501,29 @@ config CRYPTO_NHPOLY1305
        select CRYPTO_HASH
        select CRYPTO_POLY1305
 
+config CRYPTO_ADIANTUM
+       tristate "Adiantum support"
+       select CRYPTO_CHACHA20
+       select CRYPTO_POLY1305
+       select CRYPTO_NHPOLY1305
+       help
+         Adiantum is a tweakable, length-preserving encryption mode
+         designed for fast and secure disk encryption, especially on
+         CPUs without dedicated crypto instructions.  It encrypts
+         each sector using the XChaCha12 stream cipher, two passes of
+         an ?-almost-?-universal hash function, and an invocation of
+         the AES-256 block cipher on a single 16-byte block.  On CPUs
+         without AES instructions, Adiantum is much faster than
+         AES-XTS.
+
+         Adiantum's security is provably reducible to that of its
+         underlying stream and block ciphers, subject to a security
+         bound.  Unlike XTS, Adiantum is a true wide-block encryption
+         mode, so it actually provides an even stronger notion of
+         security than XTS, subject to the security bound.
+
+         If unsure, say N.
+
 comment "Hash modes"
 
 config CRYPTO_CMAC
crypto/Makefile +1 -0
index c3310c85f09f..5e789dc2d4fd 100644
@@ -85,6 +85,7 @@ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_XTS) += xts.o
 obj-$(CONFIG_CRYPTO_CTR) += ctr.o
 obj-$(CONFIG_CRYPTO_KEYWRAP) += keywrap.o
+obj-$(CONFIG_CRYPTO_ADIANTUM) += adiantum.o
 obj-$(CONFIG_CRYPTO_NHPOLY1305) += nhpoly1305.o
 obj-$(CONFIG_CRYPTO_GCM) += gcm.o
 obj-$(CONFIG_CRYPTO_CCM) += ccm.o
crypto/adiantum.c new file +658 -0
new file mode 100644
index 000000000000..2dfcf12fd452
@@ -0,0 +1,658 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Adiantum length-preserving encryption mode
+ *
+ * Copyright 2018 Google LLC
+ */
+
+/*
+ * Adiantum is a tweakable, length-preserving encryption mode designed for fast
+ * and secure disk encryption, especially on CPUs without dedicated crypto
+ * instructions.  Adiantum encrypts each sector using the XChaCha12 stream
+ * cipher, two passes of an ?-almost-?-universal (?A?U) hash function based on
+ * NH and Poly1305, and an invocation of the AES-256 block cipher on a single
+ * 16-byte block.  See the paper for details:
+ *
+ *     Adiantum: length-preserving encryption for entry-level processors
+ *      (https://eprint.iacr.org/2018/720.pdf)
+ *
+ * For flexibility, this implementation also allows other ciphers:
+ *
+ *     - Stream cipher: XChaCha12 or XChaCha20
+ *     - Block cipher: any with a 128-bit block size and 256-bit key
+ *
+ * This implementation doesn't currently allow other ?A?U hash functions, i.e.
+ * HPolyC is not supported.  This is because Adiantum is ~20% faster than HPolyC
+ * but still provably as secure, and also the ?A?U hash function of HBSH is
+ * formally defined to take two inputs (tweak, message) which makes it difficult
+ * to wrap with the crypto_shash API.  Rather, some details need to be handled
+ * here.  Nevertheless, if needed in the future, support for other ?A?U hash
+ * functions could be added here.
+ */
+
+#include <crypto/b128ops.h>
+#include <crypto/chacha.h>
+#include <crypto/internal/hash.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/nhpoly1305.h>
+#include <crypto/scatterwalk.h>
+#include <linux/module.h>
+
+#include "internal.h"
+
+/*
+ * Size of right-hand block of input data, in bytes; also the size of the block
+ * cipher's block size and the hash function's output.
+ */
+#define BLOCKCIPHER_BLOCK_SIZE         16
+
+/* Size of the block cipher key (K_E) in bytes */
+#define BLOCKCIPHER_KEY_SIZE           32
+
+/* Size of the hash key (K_H) in bytes */
+#define HASH_KEY_SIZE          (POLY1305_BLOCK_SIZE + NHPOLY1305_KEY_SIZE)
+
+/*
+ * The specification allows variable-length tweaks, but Linux's crypto API
+ * currently only allows algorithms to support a single length.  The "natural"
+ * tweak length for Adiantum is 16, since that fits into one Poly1305 block for
+ * the best performance.  But longer tweaks are useful for fscrypt, to avoid
+ * needing to derive per-file keys.  So instead we use two blocks, or 32 bytes.
+ */
+#define TWEAK_SIZE             32
+
+struct adiantum_instance_ctx {
+       struct crypto_skcipher_spawn streamcipher_spawn;
+       struct crypto_spawn blockcipher_spawn;
+       struct crypto_shash_spawn hash_spawn;
+};
+
+struct adiantum_tfm_ctx {
+       struct crypto_skcipher *streamcipher;
+       struct crypto_cipher *blockcipher;
+       struct crypto_shash *hash;
+       struct poly1305_key header_hash_key;
+};
+
+struct adiantum_request_ctx {
+
+       /*
+        * Buffer for right-hand block of data, i.e.
+        *
+        *    P_L => P_M => C_M => C_R when encrypting, or
+        *    C_R => C_M => P_M => P_L when decrypting.
+        *
+        * Also used to build the IV for the stream cipher.
+        */
+       union {
+               u8 bytes[XCHACHA_IV_SIZE];
+               __le32 words[XCHACHA_IV_SIZE / sizeof(__le32)];
+               le128 bignum;   /* interpret as element of Z/(2^{128}Z) */
+       } rbuf;
+
+       bool enc; /* true if encrypting, false if decrypting */
+
+       /*
+        * The result of the Poly1305 ?A?U hash function applied to
+        * (message length, tweak).
+        */
+       le128 header_hash;
+
+       /* Sub-requests, must be last */
+       union {
+               struct shash_desc hash_desc;
+               struct skcipher_request streamcipher_req;
+       } u;
+};
+
+/*
+ * Given the XChaCha stream key K_S, derive the block cipher key K_E and the
+ * hash key K_H as follows:
+ *
+ *     K_E || K_H || ... = XChaCha(key=K_S, nonce=1||0^191)
+ *
+ * Note that this denotes using bits from the XChaCha keystream, which here we
+ * get indirectly by encrypting a buffer containing all 0's.
+ */
+static int adiantum_setkey(struct crypto_skcipher *tfm, const u8 *key,
+                          unsigned int keylen)
+{
+       struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+       struct {
+               u8 iv[XCHACHA_IV_SIZE];
+               u8 derived_keys[BLOCKCIPHER_KEY_SIZE + HASH_KEY_SIZE];
+               struct scatterlist sg;
+               struct crypto_wait wait;
+               struct skcipher_request req; /* must be last */
+       } *data;
+       u8 *keyp;
+       int err;
+
+       /* Set the stream cipher key (K_S) */
+       crypto_skcipher_clear_flags(tctx->streamcipher, CRYPTO_TFM_REQ_MASK);
+       crypto_skcipher_set_flags(tctx->streamcipher,
+                                 crypto_skcipher_get_flags(tfm) &
+                                 CRYPTO_TFM_REQ_MASK);
+       err = crypto_skcipher_setkey(tctx->streamcipher, key, keylen);
+       crypto_skcipher_set_flags(tfm,
+                               crypto_skcipher_get_flags(tctx->streamcipher) &
+                               CRYPTO_TFM_RES_MASK);
+       if (err)
+               return err;
+
+       /* Derive the subkeys */
+       data = kzalloc(sizeof(*data) +
+                      crypto_skcipher_reqsize(tctx->streamcipher), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       data->iv[0] = 1;
+       sg_init_one(&data->sg, data->derived_keys, sizeof(data->derived_keys));
+       crypto_init_wait(&data->wait);
+       skcipher_request_set_tfm(&data->req, tctx->streamcipher);
+       skcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP |
+                                                 CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                     crypto_req_done, &data->wait);
+       skcipher_request_set_crypt(&data->req, &data->sg, &data->sg,
+                                  sizeof(data->derived_keys), data->iv);
+       err = crypto_wait_req(crypto_skcipher_encrypt(&data->req), &data->wait);
+       if (err)
+               goto out;
+       keyp = data->derived_keys;
+
+       /* Set the block cipher key (K_E) */
+       crypto_cipher_clear_flags(tctx->blockcipher, CRYPTO_TFM_REQ_MASK);
+       crypto_cipher_set_flags(tctx->blockcipher,
+                               crypto_skcipher_get_flags(tfm) &
+                               CRYPTO_TFM_REQ_MASK);
+       err = crypto_cipher_setkey(tctx->blockcipher, keyp,
+                                  BLOCKCIPHER_KEY_SIZE);
+       crypto_skcipher_set_flags(tfm,
+                                 crypto_cipher_get_flags(tctx->blockcipher) &
+                                 CRYPTO_TFM_RES_MASK);
+       if (err)
+               goto out;
+       keyp += BLOCKCIPHER_KEY_SIZE;
+
+       /* Set the hash key (K_H) */
+       poly1305_core_setkey(&tctx->header_hash_key, keyp);
+       keyp += POLY1305_BLOCK_SIZE;
+
+       crypto_shash_clear_flags(tctx->hash, CRYPTO_TFM_REQ_MASK);
+       crypto_shash_set_flags(tctx->hash, crypto_skcipher_get_flags(tfm) &
+                                          CRYPTO_TFM_REQ_MASK);
+       err = crypto_shash_setkey(tctx->hash, keyp, NHPOLY1305_KEY_SIZE);
+       crypto_skcipher_set_flags(tfm, crypto_shash_get_flags(tctx->hash) &
+                                      CRYPTO_TFM_RES_MASK);
+       keyp += NHPOLY1305_KEY_SIZE;
+       WARN_ON(keyp != &data->derived_keys[ARRAY_SIZE(data->derived_keys)]);
+out:
+       kzfree(data);
+       return err;
+}
+
+/* Addition in Z/(2^{128}Z) */
+static inline void le128_add(le128 *r, const le128 *v1, const le128 *v2)
+{
+       u64 x = le64_to_cpu(v1->b);
+       u64 y = le64_to_cpu(v2->b);
+
+       r->b = cpu_to_le64(x + y);
+       r->a = cpu_to_le64(le64_to_cpu(v1->a) + le64_to_cpu(v2->a) +
+                          (x + y < x));
+}
+
+/* Subtraction in Z/(2^{128}Z) */
+static inline void le128_sub(le128 *r, const le128 *v1, const le128 *v2)
+{
+       u64 x = le64_to_cpu(v1->b);
+       u64 y = le64_to_cpu(v2->b);
+
+       r->b = cpu_to_le64(x - y);
+       r->a = cpu_to_le64(le64_to_cpu(v1->a) - le64_to_cpu(v2->a) -
+                          (x - y > x));
+}
+
+/*
+ * Apply the Poly1305 ?A?U hash function to (message length, tweak) and save the
+ * result to rctx->header_hash.
+ *
+ * This value is reused in both the first and second hash steps.  Specifically,
+ * it's added to the result of an independently keyed ?A?U hash function (for
+ * equal length inputs only) taken over the message.  This gives the overall
+ * Adiantum hash of the (tweak, message) pair.
+ */
+static void adiantum_hash_header(struct skcipher_request *req)
+{
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+       const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+       struct adiantum_request_ctx *rctx = skcipher_request_ctx(req);
+       const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE;
+       struct {
+               __le64 message_bits;
+               __le64 padding;
+       } header = {
+               .message_bits = cpu_to_le64((u64)bulk_len * 8)
+       };
+       struct poly1305_state state;
+
+       poly1305_core_init(&state);
+
+       BUILD_BUG_ON(sizeof(header) % POLY1305_BLOCK_SIZE != 0);
+       poly1305_core_blocks(&state, &tctx->header_hash_key,
+                            &header, sizeof(header) / POLY1305_BLOCK_SIZE);
+
+       BUILD_BUG_ON(TWEAK_SIZE % POLY1305_BLOCK_SIZE != 0);
+       poly1305_core_blocks(&state, &tctx->header_hash_key, req->iv,
+                            TWEAK_SIZE / POLY1305_BLOCK_SIZE);
+
+       poly1305_core_emit(&state, &rctx->header_hash);
+}
+
+/* Hash the left-hand block (the "bulk") of the message using NHPoly1305 */
+static int adiantum_hash_message(struct skcipher_request *req,
+                                struct scatterlist *sgl, le128 *digest)
+{
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+       const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+       struct adiantum_request_ctx *rctx = skcipher_request_ctx(req);
+       const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE;
+       struct shash_desc *hash_desc = &rctx->u.hash_desc;
+       struct sg_mapping_iter miter;
+       unsigned int i, n;
+       int err;
+
+       hash_desc->tfm = tctx->hash;
+       hash_desc->flags = 0;
+
+       err = crypto_shash_init(hash_desc);
+       if (err)
+               return err;
+
+       sg_miter_start(&miter, sgl, sg_nents(sgl),
+                      SG_MITER_FROM_SG | SG_MITER_ATOMIC);
+       for (i = 0; i < bulk_len; i += n) {
+               sg_miter_next(&miter);
+               n = min_t(unsigned int, miter.length, bulk_len - i);
+               err = crypto_shash_update(hash_desc, miter.addr, n);
+               if (err)
+                       break;
+       }
+       sg_miter_stop(&miter);
+       if (err)
+               return err;
+
+       return crypto_shash_final(hash_desc, (u8 *)digest);
+}
+
+/* Continue Adiantum encryption/decryption after the stream cipher step */
+static int adiantum_finish(struct skcipher_request *req)
+{
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+       const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+       struct adiantum_request_ctx *rctx = skcipher_request_ctx(req);
+       const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE;
+       le128 digest;
+       int err;
+
+       /* If decrypting, decrypt C_M with the block cipher to get P_M */
+       if (!rctx->enc)
+               crypto_cipher_decrypt_one(tctx->blockcipher, rctx->rbuf.bytes,
+                                         rctx->rbuf.bytes);
+
+       /*
+        * Second hash step
+        *      enc: C_R = C_M - H_{K_H}(T, C_L)
+        *      dec: P_R = P_M - H_{K_H}(T, P_L)
+        */
+       err = adiantum_hash_message(req, req->dst, &digest);
+       if (err)
+               return err;
+       le128_add(&digest, &digest, &rctx->header_hash);
+       le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);
+       scatterwalk_map_and_copy(&rctx->rbuf.bignum, req->dst,
+                                bulk_len, BLOCKCIPHER_BLOCK_SIZE, 1);
+       return 0;
+}
+
+static void adiantum_streamcipher_done(struct crypto_async_request *areq,
+                                      int err)
+{
+       struct skcipher_request *req = areq->data;
+
+       if (!err)
+               err = adiantum_finish(req);
+
+       skcipher_request_complete(req, err);
+}
+
+static int adiantum_crypt(struct skcipher_request *req, bool enc)
+{
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+       const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+       struct adiantum_request_ctx *rctx = skcipher_request_ctx(req);
+       const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE;
+       unsigned int stream_len;
+       le128 digest;
+       int err;
+
+       if (req->cryptlen < BLOCKCIPHER_BLOCK_SIZE)
+               return -EINVAL;
+
+       rctx->enc = enc;
+
+       /*
+        * First hash step
+        *      enc: P_M = P_R + H_{K_H}(T, P_L)
+        *      dec: C_M = C_R + H_{K_H}(T, C_L)
+        */
+       adiantum_hash_header(req);
+       err = adiantum_hash_message(req, req->src, &digest);
+       if (err)
+               return err;
+       le128_add(&digest, &digest, &rctx->header_hash);
+       scatterwalk_map_and_copy(&rctx->rbuf.bignum, req->src,
+                                bulk_len, BLOCKCIPHER_BLOCK_SIZE, 0);
+       le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest);
+
+       /* If encrypting, encrypt P_M with the block cipher to get C_M */
+       if (enc)
+               crypto_cipher_encrypt_one(tctx->blockcipher, rctx->rbuf.bytes,
+                                         rctx->rbuf.bytes);
+
+       /* Initialize the rest of the XChaCha IV (first part is C_M) */
+       BUILD_BUG_ON(BLOCKCIPHER_BLOCK_SIZE != 16);
+       BUILD_BUG_ON(XCHACHA_IV_SIZE != 32);    /* nonce || stream position */
+       rctx->rbuf.words[4] = cpu_to_le32(1);
+       rctx->rbuf.words[5] = 0;
+       rctx->rbuf.words[6] = 0;
+       rctx->rbuf.words[7] = 0;
+
+       /*
+        * XChaCha needs to be done on all the data except the last 16 bytes;
+        * for disk encryption that usually means 4080 or 496 bytes.  But ChaCha
+        * implementations tend to be most efficient when passed a whole number
+        * of 64-byte ChaCha blocks, or sometimes even a multiple of 256 bytes.
+        * And here it doesn't matter whether the last 16 bytes are written to,
+        * as the second hash step will overwrite them.  Thus, round the XChaCha
+        * length up to the next 64-byte boundary if possible.
+        */
+       stream_len = bulk_len;
+       if (round_up(stream_len, CHACHA_BLOCK_SIZE) <= req->cryptlen)
+               stream_len = round_up(stream_len, CHACHA_BLOCK_SIZE);
+
+       skcipher_request_set_tfm(&rctx->u.streamcipher_req, tctx->streamcipher);
+       skcipher_request_set_crypt(&rctx->u.streamcipher_req, req->src,
+                                  req->dst, stream_len, &rctx->rbuf);
+       skcipher_request_set_callback(&rctx->u.streamcipher_req,
+                                     req->base.flags,
+                                     adiantum_streamcipher_done, req);
+       return crypto_skcipher_encrypt(&rctx->u.streamcipher_req) ?:
+               adiantum_finish(req);
+}
+
+static int adiantum_encrypt(struct skcipher_request *req)
+{
+       return adiantum_crypt(req, true);
+}
+
+static int adiantum_decrypt(struct skcipher_request *req)
+{
+       return adiantum_crypt(req, false);
+}
+
+static int adiantum_init_tfm(struct crypto_skcipher *tfm)
+{
+       struct skcipher_instance *inst = skcipher_alg_instance(tfm);
+       struct adiantum_instance_ctx *ictx = skcipher_instance_ctx(inst);
+       struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+       struct crypto_skcipher *streamcipher;
+       struct crypto_cipher *blockcipher;
+       struct crypto_shash *hash;
+       unsigned int subreq_size;
+       int err;
+
+       streamcipher = crypto_spawn_skcipher(&ictx->streamcipher_spawn);
+       if (IS_ERR(streamcipher))
+               return PTR_ERR(streamcipher);
+
+       blockcipher = crypto_spawn_cipher(&ictx->blockcipher_spawn);
+       if (IS_ERR(blockcipher)) {
+               err = PTR_ERR(blockcipher);
+               goto err_free_streamcipher;
+       }
+
+       hash = crypto_spawn_shash(&ictx->hash_spawn);
+       if (IS_ERR(hash)) {
+               err = PTR_ERR(hash);
+               goto err_free_blockcipher;
+       }
+
+       tctx->streamcipher = streamcipher;
+       tctx->blockcipher = blockcipher;
+       tctx->hash = hash;
+
+       BUILD_BUG_ON(offsetofend(struct adiantum_request_ctx, u) !=
+                    sizeof(struct adiantum_request_ctx));
+       subreq_size = max(FIELD_SIZEOF(struct adiantum_request_ctx,
+                                      u.hash_desc) +
+                         crypto_shash_descsize(hash),
+                         FIELD_SIZEOF(struct adiantum_request_ctx,
+                                      u.streamcipher_req) +
+                         crypto_skcipher_reqsize(streamcipher));
+
+       crypto_skcipher_set_reqsize(tfm,
+                                   offsetof(struct adiantum_request_ctx, u) +
+                                   subreq_size);
+       return 0;
+
+err_free_blockcipher:
+       crypto_free_cipher(blockcipher);
+err_free_streamcipher:
+       crypto_free_skcipher(streamcipher);
+       return err;
+}
+
+static void adiantum_exit_tfm(struct crypto_skcipher *tfm)
+{
+       struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+
+       crypto_free_skcipher(tctx->streamcipher);
+       crypto_free_cipher(tctx->blockcipher);
+       crypto_free_shash(tctx->hash);
+}
+
+static void adiantum_free_instance(struct skcipher_instance *inst)
+{
+       struct adiantum_instance_ctx *ictx = skcipher_instance_ctx(inst);
+
+       crypto_drop_skcipher(&ictx->streamcipher_spawn);
+       crypto_drop_spawn(&ictx->blockcipher_spawn);
+       crypto_drop_shash(&ictx->hash_spawn);
+       kfree(inst);
+}
+
+/*
+ * Check for a supported set of inner algorithms.
+ * See the comment at the beginning of this file.
+ */
+static bool adiantum_supported_algorithms(struct skcipher_alg *streamcipher_alg,
+                                         struct crypto_alg *blockcipher_alg,
+                                         struct shash_alg *hash_alg)
+{
+       if (strcmp(streamcipher_alg->base.cra_name, "xchacha12") != 0 &&
+           strcmp(streamcipher_alg->base.cra_name, "xchacha20") != 0)
+               return false;
+
+       if (blockcipher_alg->cra_cipher.cia_min_keysize > BLOCKCIPHER_KEY_SIZE ||
+           blockcipher_alg->cra_cipher.cia_max_keysize < BLOCKCIPHER_KEY_SIZE)
+               return false;
+       if (blockcipher_alg->cra_blocksize != BLOCKCIPHER_BLOCK_SIZE)
+               return false;
+
+       if (strcmp(hash_alg->base.cra_name, "nhpoly1305") != 0)
+               return false;
+
+       return true;
+}
+
+static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+       struct crypto_attr_type *algt;
+       const char *streamcipher_name;
+       const char *blockcipher_name;
+       const char *nhpoly1305_name;
+       struct skcipher_instance *inst;
+       struct adiantum_instance_ctx *ictx;
+       struct skcipher_alg *streamcipher_alg;
+       struct crypto_alg *blockcipher_alg;
+       struct crypto_alg *_hash_alg;
+       struct shash_alg *hash_alg;
+       int err;
+
+       algt = crypto_get_attr_type(tb);
+       if (IS_ERR(algt))
+               return PTR_ERR(algt);
+
+       if ((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask)
+               return -EINVAL;
+
+       streamcipher_name = crypto_attr_alg_name(tb[1]);
+       if (IS_ERR(streamcipher_name))
+               return PTR_ERR(streamcipher_name);
+
+       blockcipher_name = crypto_attr_alg_name(tb[2]);
+       if (IS_ERR(blockcipher_name))
+               return PTR_ERR(blockcipher_name);
+
+       nhpoly1305_name = crypto_attr_alg_name(tb[3]);
+       if (nhpoly1305_name == ERR_PTR(-ENOENT))
+               nhpoly1305_name = "nhpoly1305";
+       if (IS_ERR(nhpoly1305_name))
+               return PTR_ERR(nhpoly1305_name);
+
+       inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
+       if (!inst)
+               return -ENOMEM;
+       ictx = skcipher_instance_ctx(inst);
+
+       /* Stream cipher, e.g. "xchacha12" */
+       err = crypto_grab_skcipher(&ictx->streamcipher_spawn, streamcipher_name,
+                                  0, crypto_requires_sync(algt->type,
+                                                          algt->mask));
+       if (err)
+               goto out_free_inst;
+       streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn);
+
+       /* Block cipher, e.g. "aes" */
+       err = crypto_grab_spawn(&ictx->blockcipher_spawn, blockcipher_name,
+                               CRYPTO_ALG_TYPE_CIPHER, CRYPTO_ALG_TYPE_MASK);
+       if (err)
+               goto out_drop_streamcipher;
+       blockcipher_alg = ictx->blockcipher_spawn.alg;
+
+       /* NHPoly1305 ?A?U hash function */
+       _hash_alg = crypto_alg_mod_lookup(nhpoly1305_name,
+                                         CRYPTO_ALG_TYPE_SHASH,
+                                         CRYPTO_ALG_TYPE_MASK);
+       if (IS_ERR(_hash_alg)) {
+               err = PTR_ERR(_hash_alg);
+               goto out_drop_blockcipher;
+       }
+       hash_alg = __crypto_shash_alg(_hash_alg);
+       err = crypto_init_shash_spawn(&ictx->hash_spawn, hash_alg,
+                                     skcipher_crypto_instance(inst));
+       if (err) {
+               crypto_mod_put(_hash_alg);
+               goto out_drop_blockcipher;
+       }
+
+       /* Check the set of algorithms */
+       if (!adiantum_supported_algorithms(streamcipher_alg, blockcipher_alg,
+                                          hash_alg)) {
+               pr_warn("Unsupported Adiantum instantiation: (%s,%s,%s)\n",
+                       streamcipher_alg->base.cra_name,
+                       blockcipher_alg->cra_name, hash_alg->base.cra_name);
+               err = -EINVAL;
+               goto out_drop_hash;
+       }
+
+       /* Instance fields */
+
+       err = -ENAMETOOLONG;
+       if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
+                    "adiantum(%s,%s)", streamcipher_alg->base.cra_name,
+                    blockcipher_alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
+               goto out_drop_hash;
+       if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+                    "adiantum(%s,%s,%s)",
+                    streamcipher_alg->base.cra_driver_name,
+                    blockcipher_alg->cra_driver_name,
+                    hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+               goto out_drop_hash;
+
+       inst->alg.base.cra_blocksize = BLOCKCIPHER_BLOCK_SIZE;
+       inst->alg.base.cra_ctxsize = sizeof(struct adiantum_tfm_ctx);
+       inst->alg.base.cra_alignmask = streamcipher_alg->base.cra_alignmask |
+                                      hash_alg->base.cra_alignmask;
+       /*
+        * The block cipher is only invoked once per message, so for long
+        * messages (e.g. sectors for disk encryption) its performance doesn't
+        * matter as much as that of the stream cipher and hash function.  Thus,
+        * weigh the block cipher's ->cra_priority less.
+        */
+       inst->alg.base.cra_priority = (4 * streamcipher_alg->base.cra_priority +
+                                      2 * hash_alg->base.cra_priority +
+                                      blockcipher_alg->cra_priority) / 7;
+
+       inst->alg.setkey = adiantum_setkey;
+       inst->alg.encrypt = adiantum_encrypt;
+       inst->alg.decrypt = adiantum_decrypt;
+       inst->alg.init = adiantum_init_tfm;
+       inst->alg.exit = adiantum_exit_tfm;
+       inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(streamcipher_alg);
+       inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(streamcipher_alg);
+       inst->alg.ivsize = TWEAK_SIZE;
+
+       inst->free = adiantum_free_instance;
+
+       err = skcipher_register_instance(tmpl, inst);
+       if (err)
+               goto out_drop_hash;
+
+       return 0;
+
+out_drop_hash:
+       crypto_drop_shash(&ictx->hash_spawn);
+out_drop_blockcipher:
+       crypto_drop_spawn(&ictx->blockcipher_spawn);
+out_drop_streamcipher:
+       crypto_drop_skcipher(&ictx->streamcipher_spawn);
+out_free_inst:
+       kfree(inst);
+       return err;
+}
+
+/* adiantum(streamcipher_name, blockcipher_name [, nhpoly1305_name]) */
+static struct crypto_template adiantum_tmpl = {
+       .name = "adiantum",
+       .create = adiantum_create,
+       .module = THIS_MODULE,
+};
+
+static int __init adiantum_module_init(void)
+{
+       return crypto_register_template(&adiantum_tmpl);
+}
+
+static void __exit adiantum_module_exit(void)
+{
+       crypto_unregister_template(&adiantum_tmpl);
+}
+
+module_init(adiantum_module_init);
+module_exit(adiantum_module_exit);
+
+MODULE_DESCRIPTION("Adiantum length-preserving encryption mode");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Eric Biggers <[email protected]>");
+MODULE_ALIAS_CRYPTO("adiantum");
crypto/tcrypt.c +12 -0
index 5fb120474902..0590a9204562 100644
@@ -2320,6 +2320,18 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
                test_cipher_speed("ctr(sm4)", DECRYPT, sec, NULL, 0,
                                speed_template_16);
                break;
+
+       case 219:
+               test_cipher_speed("adiantum(xchacha12,aes)", ENCRYPT, sec, NULL,
+                                 0, speed_template_32);
+               test_cipher_speed("adiantum(xchacha12,aes)", DECRYPT, sec, NULL,
+                                 0, speed_template_32);
+               test_cipher_speed("adiantum(xchacha20,aes)", ENCRYPT, sec, NULL,
+                                 0, speed_template_32);
+               test_cipher_speed("adiantum(xchacha20,aes)", DECRYPT, sec, NULL,
+                                 0, speed_template_32);
+               break;
+
        case 300:
                if (alg) {
                        test_hash_speed(alg, sec, generic_hash_speed_template);
crypto/testmgr.c +12 -0
index 665911c24786..0f684a414acb 100644
@@ -2404,6 +2404,18 @@ static int alg_test_null(const struct alg_test_desc *desc,
 /* Please keep this list sorted by algorithm name. */
 static const struct alg_test_desc alg_test_descs[] = {
        {
+               .alg = "adiantum(xchacha12,aes)",
+               .test = alg_test_skcipher,
+               .suite = {
+                       .cipher = __VECS(adiantum_xchacha12_aes_tv_template)
+               },
+       }, {
+               .alg = "adiantum(xchacha20,aes)",
+               .test = alg_test_skcipher,
+               .suite = {
+                       .cipher = __VECS(adiantum_xchacha20_aes_tv_template)
+               },
+       }, {
                .alg = "aegis128",
                .test = alg_test_aead,
                .suite = {
crypto/testmgr.h +461 -1
index 50ea1f2705c7..e7e56a8febbc 100644
@@ -33381,6 +33381,467 @@ static const struct cipher_testvec xchacha12_tv_template[] = {
        },
 };
 
+/* Adiantum test vectors from https://github.com/google/adiantum */
+static const struct cipher_testvec adiantum_xchacha12_aes_tv_template[] = {
+       {
+               .key    = "\x9e\xeb\xb2\x49\x3c\x1c\xf5\xf4"
+                         "\x6a\x99\xc2\xc4\xdf\xb1\xf4\xdd"
+                         "\x75\x20\x57\xea\x2c\x4f\xcd\xb2"
+                         "\xa5\x3d\x7b\x49\x1e\xab\xfd\x0f",
+               .klen   = 32,
+               .iv     = "\xdf\x63\xd4\xab\xd2\x49\xf3\xd8"
+                         "\x33\x81\x37\x60\x7d\xfa\x73\x08"
+                         "\xd8\x49\x6d\x80\xe8\x2f\x62\x54"
+                         "\xeb\x0e\xa9\x39\x5b\x45\x7f\x8a",
+               .ptext  = "\x67\xc9\xf2\x30\x84\x41\x8e\x43"
+                         "\xfb\xf3\xb3\x3e\x79\x36\x7f\xe8",
+               .ctext  = "\x6d\x32\x86\x18\x67\x86\x0f\x3f"
+                         "\x96\x7c\x9d\x28\x0d\x53\xec\x9f",
+               .len    = 16,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 14, 2 },
+       }, {
+               .key    = "\x36\x2b\x57\x97\xf8\x5d\xcd\x99"
+                         "\x5f\x1a\x5a\x44\x1d\x92\x0f\x27"
+                         "\xcc\x16\xd7\x2b\x85\x63\x99\xd3"
+                         "\xba\x96\xa1\xdb\xd2\x60\x68\xda",
+               .klen   = 32,
+               .iv     = "\xef\x58\x69\xb1\x2c\x5e\x9a\x47"
+                         "\x24\xc1\xb1\x69\xe1\x12\x93\x8f"
+                         "\x43\x3d\x6d\x00\xdb\x5e\xd8\xd9"
+                         "\x12\x9a\xfe\xd9\xff\x2d\xaa\xc4",
+               .ptext  = "\x5e\xa8\x68\x19\x85\x98\x12\x23"
+                         "\x26\x0a\xcc\xdb\x0a\x04\xb9\xdf"
+                         "\x4d\xb3\x48\x7b\xb0\xe3\xc8\x19"
+                         "\x43\x5a\x46\x06\x94\x2d\xf2",
+               .ctext  = "\xc7\xc6\xf1\x73\x8f\xc4\xff\x4a"
+                         "\x39\xbe\x78\xbe\x8d\x28\xc8\x89"
+                         "\x46\x63\xe7\x0c\x7d\x87\xe8\x4e"
+                         "\xc9\x18\x7b\xbe\x18\x60\x50",
+               .len    = 31,
+       }, {
+               .key    = "\xa5\x28\x24\x34\x1a\x3c\xd8\xf7"
+                         "\x05\x91\x8f\xee\x85\x1f\x35\x7f"
+                         "\x80\x3d\xfc\x9b\x94\xf6\xfc\x9e"
+                         "\x19\x09\x00\xa9\x04\x31\x4f\x11",
+               .klen   = 32,
+               .iv     = "\xa1\xba\x49\x95\xff\x34\x6d\xb8"
+                         "\xcd\x87\x5d\x5e\xfd\xea\x85\xdb"
+                         "\x8a\x7b\x5e\xb2\x5d\x57\xdd\x62"
+                         "\xac\xa9\x8c\x41\x42\x94\x75\xb7",
+               .ptext  = "\x69\xb4\xe8\x8c\x37\xe8\x67\x82"
+                         "\xf1\xec\x5d\x04\xe5\x14\x91\x13"
+                         "\xdf\xf2\x87\x1b\x69\x81\x1d\x71"
+                         "\x70\x9e\x9c\x3b\xde\x49\x70\x11"
+                         "\xa0\xa3\xdb\x0d\x54\x4f\x66\x69"
+                         "\xd7\xdb\x80\xa7\x70\x92\x68\xce"
+                         "\x81\x04\x2c\xc6\xab\xae\xe5\x60"
+                         "\x15\xe9\x6f\xef\xaa\x8f\xa7\xa7"
+                         "\x63\x8f\xf2\xf0\x77\xf1\xa8\xea"
+                         "\xe1\xb7\x1f\x9e\xab\x9e\x4b\x3f"
+                         "\x07\x87\x5b\x6f\xcd\xa8\xaf\xb9"
+                         "\xfa\x70\x0b\x52\xb8\xa8\xa7\x9e"
+                         "\x07\x5f\xa6\x0e\xb3\x9b\x79\x13"
+                         "\x79\xc3\x3e\x8d\x1c\x2c\x68\xc8"
+                         "\x51\x1d\x3c\x7b\x7d\x79\x77\x2a"
+                         "\x56\x65\xc5\x54\x23\x28\xb0\x03",
+               .ctext  = "\x9e\x16\xab\xed\x4b\xa7\x42\x5a"
+                         "\xc6\xfb\x4e\x76\xff\xbe\x03\xa0"
+                         "\x0f\xe3\xad\xba\xe4\x98\x2b\x0e"
+                         "\x21\x48\xa0\xb8\x65\x48\x27\x48"
+                         "\x84\x54\x54\xb2\x9a\x94\x7b\xe6"
+                         "\x4b\x29\xe9\xcf\x05\x91\x80\x1a"
+                         "\x3a\xf3\x41\x96\x85\x1d\x9f\x74"
+                         "\x51\x56\x63\xfa\x7c\x28\x85\x49"
+                         "\xf7\x2f\xf9\xf2\x18\x46\xf5\x33"
+                         "\x80\xa3\x3c\xce\xb2\x57\x93\xf5"
+                         "\xae\xbd\xa9\xf5\x7b\x30\xc4\x93"
+                         "\x66\xe0\x30\x77\x16\xe4\xa0\x31"
+                         "\xba\x70\xbc\x68\x13\xf5\xb0\x9a"
+                         "\xc1\xfc\x7e\xfe\x55\x80\x5c\x48"
+                         "\x74\xa6\xaa\xa3\xac\xdc\xc2\xf5"
+                         "\x8d\xde\x34\x86\x78\x60\x75\x8d",
+               .len    = 128,
+               .also_non_np = 1,
+               .np     = 4,
+               .tap    = { 104, 16, 4, 4 },
+       }, {
+               .key    = "\xd3\x81\x72\x18\x23\xff\x6f\x4a"
+                         "\x25\x74\x29\x0d\x51\x8a\x0e\x13"
+                         "\xc1\x53\x5d\x30\x8d\xee\x75\x0d"
+                         "\x14\xd6\x69\xc9\x15\xa9\x0c\x60",
+               .klen   = 32,
+               .iv     = "\x65\x9b\xd4\xa8\x7d\x29\x1d\xf4"
+                         "\xc4\xd6\x9b\x6a\x28\xab\x64\xe2"
+                         "\x62\x81\x97\xc5\x81\xaa\xf9\x44"
+                         "\xc1\x72\x59\x82\xaf\x16\xc8\x2c",
+               .ptext  = "\xc7\x6b\x52\x6a\x10\xf0\xcc\x09"
+                         "\xc1\x12\x1d\x6d\x21\xa6\x78\xf5"
+                         "\x05\xa3\x69\x60\x91\x36\x98\x57"
+                         "\xba\x0c\x14\xcc\xf3\x2d\x73\x03"
+                         "\xc6\xb2\x5f\xc8\x16\x27\x37\x5d"
+                         "\xd0\x0b\x87\xb2\x50\x94\x7b\x58"
+                         "\x04\xf4\xe0\x7f\x6e\x57\x8e\xc9"
+                         "\x41\x84\xc1\xb1\x7e\x4b\x91\x12"
+                         "\x3a\x8b\x5d\x50\x82\x7b\xcb\xd9"
+                         "\x9a\xd9\x4e\x18\x06\x23\x9e\xd4"
+                         "\xa5\x20\x98\xef\xb5\xda\xe5\xc0"
+                         "\x8a\x6a\x83\x77\x15\x84\x1e\xae"
+                         "\x78\x94\x9d\xdf\xb7\xd1\xea\x67"
+                         "\xaa\xb0\x14\x15\xfa\x67\x21\x84"
+                         "\xd3\x41\x2a\xce\xba\x4b\x4a\xe8"
+                         "\x95\x62\xa9\x55\xf0\x80\xad\xbd"
+                         "\xab\xaf\xdd\x4f\xa5\x7c\x13\x36"
+                         "\xed\x5e\x4f\x72\xad\x4b\xf1\xd0"
+                         "\x88\x4e\xec\x2c\x88\x10\x5e\xea"
+                         "\x12\xc0\x16\x01\x29\xa3\xa0\x55"
+                         "\xaa\x68\xf3\xe9\x9d\x3b\x0d\x3b"
+                         "\x6d\xec\xf8\xa0\x2d\xf0\x90\x8d"
+                         "\x1c\xe2\x88\xd4\x24\x71\xf9\xb3"
+                         "\xc1\x9f\xc5\xd6\x76\x70\xc5\x2e"
+                         "\x9c\xac\xdb\x90\xbd\x83\x72\xba"
+                         "\x6e\xb5\xa5\x53\x83\xa9\xa5\xbf"
+                         "\x7d\x06\x0e\x3c\x2a\xd2\x04\xb5"
+                         "\x1e\x19\x38\x09\x16\xd2\x82\x1f"
+                         "\x75\x18\x56\xb8\x96\x0b\xa6\xf9"
+                         "\xcf\x62\xd9\x32\x5d\xa9\xd7\x1d"
+                         "\xec\xe4\xdf\x1b\xbe\xf1\x36\xee"
+                         "\xe3\x7b\xb5\x2f\xee\xf8\x53\x3d"
+                         "\x6a\xb7\x70\xa9\xfc\x9c\x57\x25"
+                         "\xf2\x89\x10\xd3\xb8\xa8\x8c\x30"
+                         "\xae\x23\x4f\x0e\x13\x66\x4f\xe1"
+                         "\xb6\xc0\xe4\xf8\xef\x93\xbd\x6e"
+                         "\x15\x85\x6b\xe3\x60\x81\x1d\x68"
+                         "\xd7\x31\x87\x89\x09\xab\xd5\x96"
+                         "\x1d\xf3\x6d\x67\x80\xca\x07\x31"
+                         "\x5d\xa7\xe4\xfb\x3e\xf2\x9b\x33"
+                         "\x52\x18\xc8\x30\xfe\x2d\xca\x1e"
+                         "\x79\x92\x7a\x60\x5c\xb6\x58\x87"
+                         "\xa4\x36\xa2\x67\x92\x8b\xa4\xb7"
+                         "\xf1\x86\xdf\xdc\xc0\x7e\x8f\x63"
+                         "\xd2\xa2\xdc\x78\xeb\x4f\xd8\x96"
+                         "\x47\xca\xb8\x91\xf9\xf7\x94\x21"
+                         "\x5f\x9a\x9f\x5b\xb8\x40\x41\x4b"
+                         "\x66\x69\x6a\x72\xd0\xcb\x70\xb7"
+                         "\x93\xb5\x37\x96\x05\x37\x4f\xe5"
+                         "\x8c\xa7\x5a\x4e\x8b\xb7\x84\xea"
+                         "\xc7\xfc\x19\x6e\x1f\x5a\xa1\xac"
+                         "\x18\x7d\x52\x3b\xb3\x34\x62\x99"
+                         "\xe4\x9e\x31\x04\x3f\xc0\x8d\x84"
+                         "\x17\x7c\x25\x48\x52\x67\x11\x27"
+                         "\x67\xbb\x5a\x85\xca\x56\xb2\x5c"
+                         "\xe6\xec\xd5\x96\x3d\x15\xfc\xfb"
+                         "\x22\x25\xf4\x13\xe5\x93\x4b\x9a"
+                         "\x77\xf1\x52\x18\xfa\x16\x5e\x49"
+                         "\x03\x45\xa8\x08\xfa\xb3\x41\x92"
+                         "\x79\x50\x33\xca\xd0\xd7\x42\x55"
+                         "\xc3\x9a\x0c\x4e\xd9\xa4\x3c\x86"
+                         "\x80\x9f\x53\xd1\xa4\x2e\xd1\xbc"
+                         "\xf1\x54\x6e\x93\xa4\x65\x99\x8e"
+                         "\xdf\x29\xc0\x64\x63\x07\xbb\xea",
+               .ctext  = "\x15\x97\xd0\x86\x18\x03\x9c\x51"
+                         "\xc5\x11\x36\x62\x13\x92\xe6\x73"
+                         "\x29\x79\xde\xa1\x00\x3e\x08\x64"
+                         "\x17\x1a\xbc\xd5\xfe\x33\x0e\x0c"
+                         "\x7c\x94\xa7\xc6\x3c\xbe\xac\xa2"
+                         "\x89\xe6\xbc\xdf\x0c\x33\x27\x42"
+                         "\x46\x73\x2f\xba\x4e\xa6\x46\x8f"
+                         "\xe4\xee\x39\x63\x42\x65\xa3\x88"
+                         "\x7a\xad\x33\x23\xa9\xa7\x20\x7f"
+                         "\x0b\xe6\x6a\xc3\x60\xda\x9e\xb4"
+                         "\xd6\x07\x8a\x77\x26\xd1\xab\x44"
+                         "\x99\x55\x03\x5e\xed\x8d\x7b\xbd"
+                         "\xc8\x21\xb7\x21\x30\x3f\xc0\xb5"
+                         "\xc8\xec\x6c\x23\xa6\xa3\x6d\xf1"
+                         "\x30\x0a\xd0\xa6\xa9\x28\x69\xae"
+                         "\x2a\xe6\x54\xac\x82\x9d\x6a\x95"
+                         "\x6f\x06\x44\xc5\x5a\x77\x6e\xec"
+                         "\xf8\xf8\x63\xb2\xe6\xaa\xbd\x8e"
+                         "\x0e\x8a\x62\x00\x03\xc8\x84\xdd"
+                         "\x47\x4a\xc3\x55\xba\xb7\xe7\xdf"
+                         "\x08\xbf\x62\xf5\xe8\xbc\xb6\x11"
+                         "\xe4\xcb\xd0\x66\x74\x32\xcf\xd4"
+                         "\xf8\x51\x80\x39\x14\x05\x12\xdb"
+                         "\x87\x93\xe2\x26\x30\x9c\x3a\x21"
+                         "\xe5\xd0\x38\x57\x80\x15\xe4\x08"
+                         "\x58\x05\x49\x7d\xe6\x92\x77\x70"
+                         "\xfb\x1e\x2d\x6a\x84\x00\xc8\x68"
+                         "\xf7\x1a\xdd\xf0\x7b\x38\x1e\xd8"
+                         "\x2c\x78\x78\x61\xcf\xe3\xde\x69"
+                         "\x1f\xd5\x03\xd5\x1a\xb4\xcf\x03"
+                         "\xc8\x7a\x70\x68\x35\xb4\xf6\xbe"
+                         "\x90\x62\xb2\x28\x99\x86\xf5\x44"
+                         "\x99\xeb\x31\xcf\xca\xdf\xd0\x21"
+                         "\xd6\x60\xf7\x0f\x40\xb4\x80\xb7"
+                         "\xab\xe1\x9b\x45\xba\x66\xda\xee"
+                         "\xdd\x04\x12\x40\x98\xe1\x69\xe5"
+                         "\x2b\x9c\x59\x80\xe7\x7b\xcc\x63"
+                         "\xa6\xc0\x3a\xa9\xfe\x8a\xf9\x62"
+                         "\x11\x34\x61\x94\x35\xfe\xf2\x99"
+                         "\xfd\xee\x19\xea\x95\xb6\x12\xbf"
+                         "\x1b\xdf\x02\x1a\xcc\x3e\x7e\x65"
+                         "\x78\x74\x10\x50\x29\x63\x28\xea"
+                         "\x6b\xab\xd4\x06\x4d\x15\x24\x31"
+                         "\xc7\x0a\xc9\x16\xb6\x48\xf0\xbf"
+                         "\x49\xdb\x68\x71\x31\x8f\x87\xe2"
+                         "\x13\x05\x64\xd6\x22\x0c\xf8\x36"
+                         "\x84\x24\x3e\x69\x5e\xb8\x9e\x16"
+                         "\x73\x6c\x83\x1e\xe0\x9f\x9e\xba"
+                         "\xe5\x59\x21\x33\x1b\xa9\x26\xc2"
+                         "\xc7\xd9\x30\x73\xb6\xa6\x73\x82"
+                         "\x19\xfa\x44\x4d\x40\x8b\x69\x04"
+                         "\x94\x74\xea\x6e\xb3\x09\x47\x01"
+                         "\x2a\xb9\x78\x34\x43\x11\xed\xd6"
+                         "\x8c\x95\x65\x1b\x85\x67\xa5\x40"
+                         "\xac\x9c\x05\x4b\x57\x4a\xa9\x96"
+                         "\x0f\xdd\x4f\xa1\xe0\xcf\x6e\xc7"
+                         "\x1b\xed\xa2\xb4\x56\x8c\x09\x6e"
+                         "\xa6\x65\xd7\x55\x81\xb7\xed\x11"
+                         "\x9b\x40\x75\xa8\x6b\x56\xaf\x16"
+                         "\x8b\x3d\xf4\xcb\xfe\xd5\x1d\x3d"
+                         "\x85\xc2\xc0\xde\x43\x39\x4a\x96"
+                         "\xba\x88\x97\xc0\xd6\x00\x0e\x27"
+                         "\x21\xb0\x21\x52\xba\xa7\x37\xaa"
+                         "\xcc\xbf\x95\xa8\xf4\xd0\x91\xf6",
+               .len    = 512,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 144, 368 },
+       }
+};
+
+/* Adiantum with XChaCha20 instead of XChaCha12 */
+/* Test vectors from https://github.com/google/adiantum */
+static const struct cipher_testvec adiantum_xchacha20_aes_tv_template[] = {
+       {
+               .key    = "\x9e\xeb\xb2\x49\x3c\x1c\xf5\xf4"
+                         "\x6a\x99\xc2\xc4\xdf\xb1\xf4\xdd"
+                         "\x75\x20\x57\xea\x2c\x4f\xcd\xb2"
+                         "\xa5\x3d\x7b\x49\x1e\xab\xfd\x0f",
+               .klen   = 32,
+               .iv     = "\xdf\x63\xd4\xab\xd2\x49\xf3\xd8"
+                         "\x33\x81\x37\x60\x7d\xfa\x73\x08"
+                         "\xd8\x49\x6d\x80\xe8\x2f\x62\x54"
+                         "\xeb\x0e\xa9\x39\x5b\x45\x7f\x8a",
+               .ptext  = "\x67\xc9\xf2\x30\x84\x41\x8e\x43"
+                         "\xfb\xf3\xb3\x3e\x79\x36\x7f\xe8",
+               .ctext  = "\xf6\x78\x97\xd6\xaa\x94\x01\x27"
+                         "\x2e\x4d\x83\xe0\x6e\x64\x9a\xdf",
+               .len    = 16,
+               .also_non_np = 1,
+               .np     = 3,
+               .tap    = { 5, 2, 9 },
+       }, {
+               .key    = "\x36\x2b\x57\x97\xf8\x5d\xcd\x99"
+                         "\x5f\x1a\x5a\x44\x1d\x92\x0f\x27"
+                         "\xcc\x16\xd7\x2b\x85\x63\x99\xd3"
+                         "\xba\x96\xa1\xdb\xd2\x60\x68\xda",
+               .klen   = 32,
+               .iv     = "\xef\x58\x69\xb1\x2c\x5e\x9a\x47"
+                         "\x24\xc1\xb1\x69\xe1\x12\x93\x8f"
+                         "\x43\x3d\x6d\x00\xdb\x5e\xd8\xd9"
+                         "\x12\x9a\xfe\xd9\xff\x2d\xaa\xc4",
+               .ptext  = "\x5e\xa8\x68\x19\x85\x98\x12\x23"
+                         "\x26\x0a\xcc\xdb\x0a\x04\xb9\xdf"
+                         "\x4d\xb3\x48\x7b\xb0\xe3\xc8\x19"
+                         "\x43\x5a\x46\x06\x94\x2d\xf2",
+               .ctext  = "\x4b\xb8\x90\x10\xdf\x7f\x64\x08"
+                         "\x0e\x14\x42\x5f\x00\x74\x09\x36"
+                         "\x57\x72\xb5\xfd\xb5\x5d\xb8\x28"
+                         "\x0c\x04\x91\x14\x91\xe9\x37",
+               .len    = 31,
+               .also_non_np = 1,
+               .np     = 2,
+               .tap    = { 16, 15 },
+       }, {
+               .key    = "\xa5\x28\x24\x34\x1a\x3c\xd8\xf7"
+                         "\x05\x91\x8f\xee\x85\x1f\x35\x7f"
+                         "\x80\x3d\xfc\x9b\x94\xf6\xfc\x9e"
+                         "\x19\x09\x00\xa9\x04\x31\x4f\x11",
+               .klen   = 32,
+               .iv     = "\xa1\xba\x49\x95\xff\x34\x6d\xb8"
+                         "\xcd\x87\x5d\x5e\xfd\xea\x85\xdb"
+                         "\x8a\x7b\x5e\xb2\x5d\x57\xdd\x62"
+                         "\xac\xa9\x8c\x41\x42\x94\x75\xb7",
+               .ptext  = "\x69\xb4\xe8\x8c\x37\xe8\x67\x82"
+                         "\xf1\xec\x5d\x04\xe5\x14\x91\x13"
+                         "\xdf\xf2\x87\x1b\x69\x81\x1d\x71"
+                         "\x70\x9e\x9c\x3b\xde\x49\x70\x11"
+                         "\xa0\xa3\xdb\x0d\x54\x4f\x66\x69"
+                         "\xd7\xdb\x80\xa7\x70\x92\x68\xce"
+                         "\x81\x04\x2c\xc6\xab\xae\xe5\x60"
+                         "\x15\xe9\x6f\xef\xaa\x8f\xa7\xa7"
+                         "\x63\x8f\xf2\xf0\x77\xf1\xa8\xea"
+                         "\xe1\xb7\x1f\x9e\xab\x9e\x4b\x3f"
+                         "\x07\x87\x5b\x6f\xcd\xa8\xaf\xb9"
+                         "\xfa\x70\x0b\x52\xb8\xa8\xa7\x9e"
+                         "\x07\x5f\xa6\x0e\xb3\x9b\x79\x13"
+                         "\x79\xc3\x3e\x8d\x1c\x2c\x68\xc8"
+                         "\x51\x1d\x3c\x7b\x7d\x79\x77\x2a"
+                         "\x56\x65\xc5\x54\x23\x28\xb0\x03",
+               .ctext  = "\xb1\x8b\xa0\x05\x77\xa8\x4d\x59"
+                         "\x1b\x8e\x21\xfc\x3a\x49\xfa\xd4"
+                         "\xeb\x36\xf3\xc4\xdf\xdc\xae\x67"
+                         "\x07\x3f\x70\x0e\xe9\x66\xf5\x0c"
+                         "\x30\x4d\x66\xc9\xa4\x2f\x73\x9c"
+                         "\x13\xc8\x49\x44\xcc\x0a\x90\x9d"
+                         "\x7c\xdd\x19\x3f\xea\x72\x8d\x58"
+                         "\xab\xe7\x09\x2c\xec\xb5\x44\xd2"
+                         "\xca\xa6\x2d\x7a\x5c\x9c\x2b\x15"
+                         "\xec\x2a\xa6\x69\x91\xf9\xf3\x13"
+                         "\xf7\x72\xc1\xc1\x40\xd5\xe1\x94"
+                         "\xf4\x29\xa1\x3e\x25\x02\xa8\x3e"
+                         "\x94\xc1\x91\x14\xa1\x14\xcb\xbe"
+                         "\x67\x4c\xb9\x38\xfe\xa7\xaa\x32"
+                         "\x29\x62\x0d\xb2\xf6\x3c\x58\x57"
+                         "\xc1\xd5\x5a\xbb\xd6\xa6\x2a\xe5",
+               .len    = 128,
+               .also_non_np = 1,
+               .np     = 4,
+               .tap    = { 112, 7, 8, 1 },
+       }, {
+               .key    = "\xd3\x81\x72\x18\x23\xff\x6f\x4a"
+                         "\x25\x74\x29\x0d\x51\x8a\x0e\x13"
+                         "\xc1\x53\x5d\x30\x8d\xee\x75\x0d"
+                         "\x14\xd6\x69\xc9\x15\xa9\x0c\x60",
+               .klen   = 32,
+               .iv     = "\x65\x9b\xd4\xa8\x7d\x29\x1d\xf4"
+                         "\xc4\xd6\x9b\x6a\x28\xab\x64\xe2"
+                         "\x62\x81\x97\xc5\x81\xaa\xf9\x44"
+                         "\xc1\x72\x59\x82\xaf\x16\xc8\x2c",
+               .ptext  = "\xc7\x6b\x52\x6a\x10\xf0\xcc\x09"
+                         "\xc1\x12\x1d\x6d\x21\xa6\x78\xf5"
+                         "\x05\xa3\x69\x60\x91\x36\x98\x57"
+                         "\xba\x0c\x14\xcc\xf3\x2d\x73\x03"
+                         "\xc6\xb2\x5f\xc8\x16\x27\x37\x5d"
+                         "\xd0\x0b\x87\xb2\x50\x94\x7b\x58"
+                         "\x04\xf4\xe0\x7f\x6e\x57\x8e\xc9"
+                         "\x41\x84\xc1\xb1\x7e\x4b\x91\x12"
+                         "\x3a\x8b\x5d\x50\x82\x7b\xcb\xd9"
+                         "\x9a\xd9\x4e\x18\x06\x23\x9e\xd4"
+                         "\xa5\x20\x98\xef\xb5\xda\xe5\xc0"
+                         "\x8a\x6a\x83\x77\x15\x84\x1e\xae"
+                         "\x78\x94\x9d\xdf\xb7\xd1\xea\x67"
+                         "\xaa\xb0\x14\x15\xfa\x67\x21\x84"
+                         "\xd3\x41\x2a\xce\xba\x4b\x4a\xe8"
+                         "\x95\x62\xa9\x55\xf0\x80\xad\xbd"
+                         "\xab\xaf\xdd\x4f\xa5\x7c\x13\x36"
+                         "\xed\x5e\x4f\x72\xad\x4b\xf1\xd0"
+                         "\x88\x4e\xec\x2c\x88\x10\x5e\xea"
+                         "\x12\xc0\x16\x01\x29\xa3\xa0\x55"
+                         "\xaa\x68\xf3\xe9\x9d\x3b\x0d\x3b"
+                         "\x6d\xec\xf8\xa0\x2d\xf0\x90\x8d"
+                         "\x1c\xe2\x88\xd4\x24\x71\xf9\xb3"
+                         "\xc1\x9f\xc5\xd6\x76\x70\xc5\x2e"
+                         "\x9c\xac\xdb\x90\xbd\x83\x72\xba"
+                         "\x6e\xb5\xa5\x53\x83\xa9\xa5\xbf"
+                         "\x7d\x06\x0e\x3c\x2a\xd2\x04\xb5"
+                         "\x1e\x19\x38\x09\x16\xd2\x82\x1f"
+                         "\x75\x18\x56\xb8\x96\x0b\xa6\xf9"
+                         "\xcf\x62\xd9\x32\x5d\xa9\xd7\x1d"
+                         "\xec\xe4\xdf\x1b\xbe\xf1\x36\xee"
+                         "\xe3\x7b\xb5\x2f\xee\xf8\x53\x3d"
+                         "\x6a\xb7\x70\xa9\xfc\x9c\x57\x25"
+                         "\xf2\x89\x10\xd3\xb8\xa8\x8c\x30"
+                         "\xae\x23\x4f\x0e\x13\x66\x4f\xe1"
+                         "\xb6\xc0\xe4\xf8\xef\x93\xbd\x6e"
+                         "\x15\x85\x6b\xe3\x60\x81\x1d\x68"
+                         "\xd7\x31\x87\x89\x09\xab\xd5\x96"
+                         "\x1d\xf3\x6d\x67\x80\xca\x07\x31"
+                         "\x5d\xa7\xe4\xfb\x3e\xf2\x9b\x33"
+                         "\x52\x18\xc8\x30\xfe\x2d\xca\x1e"
+                         "\x79\x92\x7a\x60\x5c\xb6\x58\x87"
+                         "\xa4\x36\xa2\x67\x92\x8b\xa4\xb7"
+                         "\xf1\x86\xdf\xdc\xc0\x7e\x8f\x63"
+                         "\xd2\xa2\xdc\x78\xeb\x4f\xd8\x96"
+                         "\x47\xca\xb8\x91\xf9\xf7\x94\x21"
+                         "\x5f\x9a\x9f\x5b\xb8\x40\x41\x4b"
+                         "\x66\x69\x6a\x72\xd0\xcb\x70\xb7"
+                         "\x93\xb5\x37\x96\x05\x37\x4f\xe5"
+                         "\x8c\xa7\x5a\x4e\x8b\xb7\x84\xea"
+                         "\xc7\xfc\x19\x6e\x1f\x5a\xa1\xac"
+                         "\x18\x7d\x52\x3b\xb3\x34\x62\x99"
+                         "\xe4\x9e\x31\x04\x3f\xc0\x8d\x84"
+                         "\x17\x7c\x25\x48\x52\x67\x11\x27"
+                         "\x67\xbb\x5a\x85\xca\x56\xb2\x5c"
+                         "\xe6\xec\xd5\x96\x3d\x15\xfc\xfb"
+                         "\x22\x25\xf4\x13\xe5\x93\x4b\x9a"
+                         "\x77\xf1\x52\x18\xfa\x16\x5e\x49"
+                         "\x03\x45\xa8\x08\xfa\xb3\x41\x92"
+                         "\x79\x50\x33\xca\xd0\xd7\x42\x55"
+                         "\xc3\x9a\x0c\x4e\xd9\xa4\x3c\x86"
+                         "\x80\x9f\x53\xd1\xa4\x2e\xd1\xbc"
+                         "\xf1\x54\x6e\x93\xa4\x65\x99\x8e"
+                         "\xdf\x29\xc0\x64\x63\x07\xbb\xea",
+               .ctext  = "\xe0\x33\xf6\xe0\xb4\xa5\xdd\x2b"
+                         "\xdd\xce\xfc\x12\x1e\xfc\x2d\xf2"
+                         "\x8b\xc7\xeb\xc1\xc4\x2a\xe8\x44"
+                         "\x0f\x3d\x97\x19\x2e\x6d\xa2\x38"
+                         "\x9d\xa6\xaa\xe1\x96\xb9\x08\xe8"
+                         "\x0b\x70\x48\x5c\xed\xb5\x9b\xcb"
+                         "\x8b\x40\x88\x7e\x69\x73\xf7\x16"
+                         "\x71\xbb\x5b\xfc\xa3\x47\x5d\xa6"
+                         "\xae\x3a\x64\xc4\xe7\xb8\xa8\xe7"
+                         "\xb1\x32\x19\xdb\xe3\x01\xb8\xf0"
+                         "\xa4\x86\xb4\x4c\xc2\xde\x5c\xd2"
+                         "\x6c\x77\xd2\xe8\x18\xb7\x0a\xc9"
+                         "\x3d\x53\xb5\xc4\x5c\xf0\x8c\x06"
+                         "\xdc\x90\xe0\x74\x47\x1b\x0b\xf6"
+                         "\xd2\x71\x6b\xc4\xf1\x97\x00\x2d"
+                         "\x63\x57\x44\x1f\x8c\xf4\xe6\x9b"
+                         "\xe0\x7a\xdd\xec\x32\x73\x42\x32"
+                         "\x7f\x35\x67\x60\x0d\xcf\x10\x52"
+                         "\x61\x22\x53\x8d\x8e\xbb\x33\x76"
+                         "\x59\xd9\x10\xce\xdf\xef\xc0\x41"
+                         "\xd5\x33\x29\x6a\xda\x46\xa4\x51"
+                         "\xf0\x99\x3d\x96\x31\xdd\xb5\xcb"
+                         "\x3e\x2a\x1f\xc7\x5c\x79\xd3\xc5"
+                         "\x20\xa1\xb1\x39\x1b\xc6\x0a\x70"
+                         "\x26\x39\x95\x07\xad\x7a\xc9\x69"
+                         "\xfe\x81\xc7\x88\x08\x38\xaf\xad"
+                         "\x9e\x8d\xfb\xe8\x24\x0d\x22\xb8"
+                         "\x0e\xed\xbe\x37\x53\x7c\xa6\xc6"
+                         "\x78\x62\xec\xa3\x59\xd9\xc6\x9d"
+                         "\xb8\x0e\x69\x77\x84\x2d\x6a\x4c"
+                         "\xc5\xd9\xb2\xa0\x2b\xa8\x80\xcc"
+                         "\xe9\x1e\x9c\x5a\xc4\xa1\xb2\x37"
+                         "\x06\x9b\x30\x32\x67\xf7\xe7\xd2"
+                         "\x42\xc7\xdf\x4e\xd4\xcb\xa0\x12"
+                         "\x94\xa1\x34\x85\x93\x50\x4b\x0a"
+                         "\x3c\x7d\x49\x25\x01\x41\x6b\x96"
+                         "\xa9\x12\xbb\x0b\xc0\xd7\xd0\x93"
+                         "\x1f\x70\x38\xb8\x21\xee\xf6\xa7"
+                         "\xee\xeb\xe7\x81\xa4\x13\xb4\x87"
+                         "\xfa\xc1\xb0\xb5\x37\x8b\x74\xa2"
+                         "\x4e\xc7\xc2\xad\x3d\x62\x3f\xf8"
+                         "\x34\x42\xe5\xae\x45\x13\x63\xfe"
+                         "\xfc\x2a\x17\x46\x61\xa9\xd3\x1c"
+                         "\x4c\xaf\xf0\x09\x62\x26\x66\x1e"
+                         "\x74\xcf\xd6\x68\x3d\x7d\xd8\xb7"
+                         "\xe7\xe6\xf8\xf0\x08\x20\xf7\x47"
+                         "\x1c\x52\xaa\x0f\x3e\x21\xa3\xf2"
+                         "\xbf\x2f\x95\x16\xa8\xc8\xc8\x8c"
+                         "\x99\x0f\x5d\xfb\xfa\x2b\x58\x8a"
+                         "\x7e\xd6\x74\x02\x60\xf0\xd0\x5b"
+                         "\x65\xa8\xac\xea\x8d\x68\x46\x34"
+                         "\x26\x9d\x4f\xb1\x9a\x8e\xc0\x1a"
+                         "\xf1\xed\xc6\x7a\x83\xfd\x8a\x57"
+                         "\xf2\xe6\xe4\xba\xfc\xc6\x3c\xad"
+                         "\x5b\x19\x50\x2f\x3a\xcc\x06\x46"
+                         "\x04\x51\x3f\x91\x97\xf0\xd2\x07"
+                         "\xe7\x93\x89\x7e\xb5\x32\x0f\x03"
+                         "\xe5\x58\x9e\x74\x72\xeb\xc2\x38"
+                         "\x00\x0c\x91\x72\x69\xed\x7d\x6d"
+                         "\xc8\x71\xf0\xec\xff\x80\xd9\x1c"
+                         "\x9e\xd2\xfa\x15\xfc\x6c\x4e\xbc"
+                         "\xb1\xa6\xbd\xbd\x70\x40\xca\x20"
+                         "\xb8\x78\xd2\xa3\xc6\xf3\x79\x9c"
+                         "\xc7\x27\xe1\x6a\x29\xad\xa4\x03",
+               .len    = 512,
+       }
+};
+
 /*
  * CTS (Cipher Text Stealing) mode tests
  */
--

2.19.1.1215.g8438c0b245-goog

maintainer
#20 lore raw
In reply to Eric Biggers
Quoted 168 lines · Eric Biggers

Hello,

We've been working to find a way to bring storage encryption to entry-level Android devices like the inexpensive "Android Go" devices sold in developing countries, and some smartwatches. Unfortunately, often these devices still ship with no encryption, since for cost reasons they have to use older CPUs like ARM Cortex-A7; and these CPUs lack the ARMv8 Cryptography Extensions, making AES-XTS much too slow.

We're trying to change this, since we believe encryption is for everyone, not just those who can afford it. And while it's unknown how long CPUs without AES support will be around, there will likely always be a "low end"; and in any case it's immensely valuable to provide a software-optimized cipher that doesn't depend on hardware support. Lack of hardware support should not be an excuse for no encryption.

But after an extensive search (e.g. see [1]) we were unable to find an existing cipher that simultaneously meets the very strict performance requirements on ARM processors, is secure (including having sufficient security parameters as well as sufficient cryptanalysis of any primitive(s) used), is suitable for practical use in dm-crypt and fscrypt, *and* avoids any particularly controversial primitive.

Therefore, we (well, Paul Crowley did the real work) designed a new encryption mode, Adiantum. In essence, Adiantum makes it secure to use the ChaCha stream cipher for disk encryption. Adiantum is specified by our paper here: https://eprint.iacr.org/2018/720.pdf ("Adiantum:
length-preserving encryption for entry-level processors"). Reference code and test vectors are here: https://github.com/google/adiantum.
Most of the high-level concepts of Adiantum are not new; similar existing modes include XCB, HCTR, and HCH. Adiantum and these modes are true wide-block modes (tweakable super-pseudorandom permutations), so they actually provide a stronger notion of security than XTS.

Adiantum is an improved version of our previous algorithm, HPolyC [2]. Like HPolyC, Adiantum uses XChaCha12, two passes of an ?-almost-?-universal (?A?U) hash function, and one AES-256 encryption of a single 16-byte block. On ARM Cortex-A7, on 4096-byte messages Adiantum is about 4x faster than AES-256-XTS (about 5x for decryption), and about 30% faster than Speck128/256-XTS.

Adiantum is a construction, not a primitive. Its security is reducible to that of XChaCha12 and AES-256, subject to a security bound; the proof is in Section 5 of our paper. Therefore, one need not "trust" Adiantum; they only need trust XChaCha12 and AES-256. Note that of these two primitives, AES-256 currently has the lower security margin.

Adiantum is ~20% faster than HPolyC, with no loss of security; in fact, Adiantum's security bound is slightly better than HPolyC's. It does this by choosing a faster ?A?U hash function: it still uses Poly1305's ?A?U hash function, but now a hash function from the "NH" family of hash functions is used to "compress" the message by 32x first. NH is ?AU (as shown in the UMAC paper[3]) but is over twice as fast as Poly1305. Key agility is reduced, but that's acceptable for disk encryption.

NH is also very simple, and it's easy to implement in SIMD assembly, e.g. in ARM NEON. Now, to get good performance only a SIMD implementation of NH is required, not Poly1305. Therefore, Adiantum can be easier to port to new platforms than HPolyC, despite Adiantum's slightly increased complexity. For now this patchset only includes an ARM32 NEON implementation of NH, but as a proof of concept I've also written SSE2, AVX2, and ARM64 NEON implementations of NH; see
https://github.com/google/adiantum/tree/master/benchmark/src.

This patchset adds Adiantum to Linux's crypto API, focusing on generic and ARM32 implementations. Patches 1-9 add support for XChaCha20 and XChaCha12. Patches 10-13 add NHPoly1305 support, needed for Adiantum hashing. Patch 14 adds Adiantum support as a skcipher template.

This patchset applies to cryptodev. It can also be found in git at branch "adiantum-v4" of:
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git

With this patchset, Adiantum is already usable in dm-crypt via the "capi:" cipher syntax. I'll also be adding Adiantum support to fscrypt via the patch https://patchwork.kernel.org/patch/10669339/, but I dropped it from this series for now since it will be taken through the fscrypt git tree instead. Note that in fscrypt, Adiantum will also fix an information leak in filenames encryption when filenames share a common prefix, and Adiantum's long IV support make it safe to use the same key for many files, improving performance even more.

Again, for more details please read our paper:

Adiantum: length-preserving encryption for entry-level processors
(https://eprint.iacr.org/2018/720.pdf)

References:
[1] https://www.spinics.net/lists/linux-crypto/msg33000.html
[2] https://patchwork.kernel.org/cover/10558059/
[3] https://fastcrypto.org/umac/umac_proc.pdf

Changed since v3:
- Rebase onto cryptodev because of recent ChaCha20 changes.
- Drop fscrypt patch; I'm sending it as a standalone patch.

Changed since v2:
- Simplify the generic NH implementation.
- Add patches to reduce atomic walks and disabling preemption.
- Split Poly1305 changes into two patches.
- Add tcrypt test mode for Adiantum.
- Make NEON 'chacha_permute' a function rather than a macro.
- Use .base.* style when declaring algorithms.
- Replace BUG_ON() in chacha_permute() with WARN_ON_ONCE().
- Set Adiantum instance {min,max}_keysize correctly in all cases.
- Make the Adiantum template take the nhpoly1305 driver name as optional third argument (useful for testing).

Thanks to Ard Biesheuvel for reviewing the patches.

Changed since v1:
- Replace HPolyC with Adiantum (uses a faster hash function).
- Drop ARM accelerated Poly1305.
- Add fscrypt patch.

Eric Biggers (14):
crypto: chacha20-generic - add HChaCha20 library function
crypto: chacha20-generic - don't unnecessarily use atomic walk
crypto: chacha20-generic - add XChaCha20 support
crypto: chacha20-generic - refactor to allow varying number of rounds
crypto: chacha - add XChaCha12 support
crypto: arm/chacha20 - limit the preemption-disabled section
crypto: arm/chacha20 - add XChaCha20 support
crypto: arm/chacha20 - refactor to allow varying number of rounds
crypto: arm/chacha - add XChaCha12 support
crypto: poly1305 - use structures for key and accumulator
crypto: poly1305 - add Poly1305 core API
crypto: nhpoly1305 - add NHPoly1305 support
crypto: arm/nhpoly1305 - add NEON-accelerated NHPoly1305
crypto: adiantum - add Adiantum support

 arch/arm/crypto/Kconfig                       |    7 +-
 arch/arm/crypto/Makefile                      |    6 +-
 ...hacha20-neon-core.S => chacha-neon-core.S} |   98 +-
 arch/arm/crypto/chacha-neon-glue.c            |  201 ++
 arch/arm/crypto/chacha20-neon-glue.c          |  127 -
 arch/arm/crypto/nh-neon-core.S                |  116 +
 arch/arm/crypto/nhpoly1305-neon-glue.c        |   77 +
 arch/arm64/crypto/chacha20-neon-glue.c        |   40 +-
 arch/x86/crypto/chacha20_glue.c               |   48 +-
 arch/x86/crypto/poly1305_glue.c               |   20 +-
 crypto/Kconfig                                |   46 +-
 crypto/Makefile                               |    4 +-
 crypto/adiantum.c                             |  658 ++++
 crypto/chacha20_generic.c                     |  137 -
 crypto/chacha20poly1305.c                     |   10 +-
 crypto/chacha_generic.c                       |  217 ++
 crypto/nhpoly1305.c                           |  254 ++
 crypto/poly1305_generic.c                     |  174 +-
 crypto/tcrypt.c                               |   12 +
 crypto/testmgr.c                              |   30 +
 crypto/testmgr.h                              | 2856 ++++++++++++++++-
 drivers/char/random.c                         |   51 +-
 drivers/crypto/caam/caamalg.c                 |    2 +-
 drivers/crypto/caam/caamalg_qi2.c             |    8 +-
 drivers/crypto/caam/compat.h                  |    2 +-
 include/crypto/chacha.h                       |   54 +
 include/crypto/chacha20.h                     |   28 -
 include/crypto/nhpoly1305.h                   |   74 +
 include/crypto/poly1305.h                     |   28 +-
 lib/Makefile                                  |    2 +-
 lib/{chacha20.c => chacha.c}                  |   59 +-
 31 files changed, 4931 insertions(+), 515 deletions(-)
 rename arch/arm/crypto/{chacha20-neon-core.S => chacha-neon-core.S} (90%)
 create mode 100644 arch/arm/crypto/chacha-neon-glue.c
 delete mode 100644 arch/arm/crypto/chacha20-neon-glue.c
 create mode 100644 arch/arm/crypto/nh-neon-core.S
 create mode 100644 arch/arm/crypto/nhpoly1305-neon-glue.c
Quoted 8 lines
 create mode 100644 crypto/adiantum.c
 delete mode 100644 crypto/chacha20_generic.c
 create mode 100644 crypto/chacha_generic.c
 create mode 100644 crypto/nhpoly1305.c
 create mode 100644 include/crypto/chacha.h
 delete mode 100644 include/crypto/chacha20.h
 create mode 100644 include/crypto/nhpoly1305.h
 rename lib/{chacha20.c => chacha.c} (58%)

All applied. Thanks.

Signature · 3 lines
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
author maintainer
#21 lore raw
In reply to Eric Biggers
Quoted 12 lines · Eric Biggers

Therefore, we (well, Paul Crowley did the real work) designed a new encryption mode, Adiantum. In essence, Adiantum makes it secure to use the ChaCha stream cipher for disk encryption. Adiantum is specified by our paper here: https://eprint.iacr.org/2018/720.pdf ("Adiantum:
length-preserving encryption for entry-level processors"). Reference code and test vectors are here: https://github.com/google/adiantum.
Most of the high-level concepts of Adiantum are not new; similar existing modes include XCB, HCTR, and HCH. Adiantum and these modes are true wide-block modes (tweakable super-pseudorandom permutations), so they actually provide a stronger notion of security than XTS.

In case anyone is interested: Paul and I have made some improvements to the Adiantum paper and have updated the preprint at the above link. The algorithm is still the same, but explanations have been improved and the proof has been redone using a different technique that is easier to follow. It also matches the version that will be published in IACR Transactions on Symmetric Cryptology (ToSC) Volume 2018 Issue 4.

All versions of our paper can be found at https://eprint.iacr.org/2018/720, and the .tex source is at https://github.com/google/adiantum/tree/master/specification.

- Eric