public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: Nathan Huckleberry <nhuck@google.com>
Cc: linux-crypto@vger.kernel.org,
	Herbert Xu <herbert@gondor.apana.org.au>,
	"David S. Miller" <davem@davemloft.net>,
	linux-arm-kernel@lists.infradead.org,
	Paul Crowley <paulcrowley@google.com>,
	Sami Tolvanen <samitolvanen@google.com>,
	Ard Biesheuvel <ardb@kernel.org>
Subject: Re: [RFC PATCH v2 3/7] crypto: hctr2 - Add HCTR2 support
Date: Wed, 16 Feb 2022 17:07:06 -0800	[thread overview]
Message-ID: <Yg2fusq8IyWsiDQj@sol.localdomain> (raw)
In-Reply-To: <20220210232812.798387-4-nhuck@google.com>

On Thu, Feb 10, 2022 at 11:28:08PM +0000, Nathan Huckleberry wrote:
> Changes since v1:
>  * Rename streamcipher -> xctr
>  * Rename hash -> polyval
>  * Use __le64 instead of u64 for little-endian length
>  * memzero_explicit in set_key
>  * Use crypto request length instead of scatterlist length for polyval
>  * Add comments referencing the paper's pseudocode
>  * Derive blockcipher name from xctr name
>  * Pass IV through request context
>  * Use .generic_driver
>  * Make tests more comprehensive

This is looking much better than v1.  A few comments below.

> +static int hctr2_hash_tweak(struct skcipher_request *req)
> +{
> +	__le64 tweak_length_block[2];
> +	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
> +	const struct hctr2_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
> +	struct hctr2_request_ctx *rctx = skcipher_request_ctx(req);
> +	struct shash_desc *hash_desc = &rctx->u.hash_desc;
> +	int err;
> +
> +	memset(tweak_length_block, 0, sizeof(tweak_length_block));
> +	if (req->cryptlen % POLYVAL_BLOCK_SIZE == 0)
> +		tweak_length_block[0] = cpu_to_le64(TWEAK_SIZE * 8 * 2 + 2);
> +	else
> +		tweak_length_block[0] = cpu_to_le64(TWEAK_SIZE * 8 * 2 + 3);
> +
> +	hash_desc->tfm = tctx->polyval;
> +	err = crypto_shash_init(hash_desc);
> +	if (err)
> +		return err;
> +
> +	err = crypto_shash_update(hash_desc, (u8 *)tweak_length_block,
> +				  sizeof(tweak_length_block));
> +	if (err)
> +		return err;
> +	return crypto_shash_update(hash_desc, req->iv, TWEAK_SIZE);
> +}

Have you considered taking advantage of the hash function precomputation that is
possible?  That should improve the performance a bit, especially on short
inputs.  Per-key, a hash state could be precomputed containing the
tweak_length_block, since it will always have the same contents, due to this
implementation only supporting a single tweak length.  hctr2_setkey() could
compute that and export it using crypto_shash_export() into the hctr2_tfm_ctx.
hctr2_crypt() could import it using crypto_shash_import().

Similarly, the tweak only needs to be hashed once per request, as the state
could be exported after hashing it the first time, then imported for the second
hash step.  The saved state would need to be part of the hctr2_request_ctx.

> +static int hctr2_finish(struct skcipher_request *req)
> +{
> +	struct hctr2_request_ctx *rctx = skcipher_request_ctx(req);
> +	u8 digest[POLYVAL_DIGEST_SIZE];
> +	int err;
> +
> +	// U = UU ^ H(T || V)
> +	err = hctr2_hash_tweak(req);
> +	if (err)
> +		return err;
> +	err = hctr2_hash_message(req, rctx->bulk_part_dst, digest);
> +	if (err)
> +		return err;
> +	crypto_xor(rctx->first_block, digest, BLOCKCIPHER_BLOCK_SIZE);
> +
> +	// Copy U into dst scatterlist
> +	scatterwalk_map_and_copy(rctx->first_block, req->dst,
> +				 0, BLOCKCIPHER_BLOCK_SIZE, 1);
> +	return 0;
> +}

The comments here and in hctr2_crypt() are assuming encryption, but the code
also handles decryption.  It would be helpful to give the pseudocode for both,
e.g.:

	//    U = UU ^ H(T || V)
	// or M = MM ^ H(T || N)

> +static int hctr2_create_base(struct crypto_template *tmpl, struct rtattr **tb)
> +{
> +	const char *xctr_name;
> +	const char *polyval_name;
> +	char blockcipher_name[CRYPTO_MAX_ALG_NAME];
> +	int len;
> +
> +	xctr_name = crypto_attr_alg_name(tb[1]);
> +	if (IS_ERR(xctr_name))
> +		return PTR_ERR(xctr_name);
> +
> +	if (!strncmp(xctr_name, "xctr(", 5)) {
> +		len = strscpy(blockcipher_name, xctr_name + 5,
> +			    sizeof(blockcipher_name));
> +
> +		if (len < 1)
> +			return -EINVAL;
> +
> +		if (blockcipher_name[len - 1] != ')')
> +			return -EINVAL;
> +
> +		blockcipher_name[len - 1] = 0;
> +	} else
> +		return -EINVAL;

I don't think this is exactly what Herbert and I had in mind.  It's close, but
the problem with grabbing the block cipher name from the raw string the user
passes in is that the string could be an implementation name like "xctr-aes-ni",
rather than an algorithm name like "xctr(aes)".

The correct way to do this is to wait to determine the block cipher algorithm
until after calling crypto_grab_skcipher().  Then it will be available in the
->cra_name of the skcipher algorithm (that should be xctr).

> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index da3736e51982..a16b631730e9 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -33630,4 +33630,674 @@ static const struct hash_testvec polyval_tv_template[] = {
>  	},
>  };
>  
> +/*
> + * Test vectors generated using https://github.com/google/hctr2
> + */
> +static const struct cipher_testvec aes_hctr2_tv_template[] = {
> +		.klen	= 16,
> +		.len	= 16,
> +	},
> +	{
[...]
> +		.klen	= 16,
> +		.len	= 16,
> +	},
> +	{
[...]
> +		.klen	= 16,
> +		.len	= 17,
> +	},
> +	{
[...]
> +		.klen	= 16,
> +		.len	= 17,
> +	},
> +	{
[...]
> +		.klen	= 24,
> +		.len	= 31,
> +	},
> +	{
> +		.klen	= 24,
> +		.len	= 31,
> +	},
[...]
> +	{
> +		.klen	= 24,
> +		.len	= 48,
> +	},
[...]
> +		.klen	= 24,
> +		.len	= 48,
[...]
> +		.klen	= 32,
> +		.len	= 128,
[...]
> +		.klen	= 32,
> +		.len	= 128,
[...]
> +		.klen	= 32,
> +		.len	= 255,
[...]
> +		.klen	= 32,
> +		.len	= 255,
[...]
> +		.klen	= 32,
> +		.len	= 512,
[...]
> +		.klen	= 32,
> +		.len	= 512,

These are better but still could use some improvement.  There are two test
vectors for each message length, but they also have the same key length.  That
provides little additional test coverage over having just half the test vectors.
It would be better to use different key lengths within each pair.  Maybe always
use klen=32 for one test vector, and randomly choose klen=16 or klen=24 for the
other test vector.  The overall point is: we can't test a zillion test vectors,
so we should make sure to get as most test coverage as possible with the smaller
set that will actually be included.

- Eric

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2022-02-17  1:09 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-10 23:28 [RFC PATCH v2 0/7] crypto: HCTR2 support Nathan Huckleberry
2022-02-10 23:28 ` [RFC PATCH v2 1/7] crypto: xctr - Add XCTR support Nathan Huckleberry
2022-02-16 23:00   ` Eric Biggers
2022-02-17  7:07     ` Arnd Bergmann
2022-02-10 23:28 ` [RFC PATCH v2 2/7] crypto: polyval - Add POLYVAL support Nathan Huckleberry
2022-02-16 23:16   ` Eric Biggers
2022-02-10 23:28 ` [RFC PATCH v2 3/7] crypto: hctr2 - Add HCTR2 support Nathan Huckleberry
2022-02-17  1:07   ` Eric Biggers [this message]
2022-02-10 23:28 ` [RFC PATCH v2 4/7] crypto: x86/aesni-xctr: Add accelerated implementation of XCTR Nathan Huckleberry
2022-02-19  1:28   ` Eric Biggers
2022-02-10 23:28 ` [RFC PATCH v2 5/7] crypto: arm64/aes-xctr: " Nathan Huckleberry
2022-02-11 11:48   ` Ard Biesheuvel
2022-02-11 20:30     ` Nathan Huckleberry
2022-02-12 10:08       ` Ard Biesheuvel
2022-02-10 23:28 ` [RFC PATCH v2 6/7] crypto: x86/polyval: Add PCLMULQDQ accelerated implementation of POLYVAL Nathan Huckleberry
2022-02-19  0:34   ` Eric Biggers
2022-02-19  0:54     ` Eric Biggers
2022-02-10 23:28 ` [RFC PATCH v2 7/7] crypto: arm64/polyval: Add PMULL " Nathan Huckleberry
2022-02-19  1:21   ` Eric Biggers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Yg2fusq8IyWsiDQj@sol.localdomain \
    --to=ebiggers@kernel.org \
    --cc=ardb@kernel.org \
    --cc=davem@davemloft.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=nhuck@google.com \
    --cc=paulcrowley@google.com \
    --cc=samitolvanen@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox