2019-12-01 21:55:10

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 0/7] crypto: more self-test improvements

This series makes some more improvements to the crypto self-tests, the
largest of which is making the AEAD fuzz tests test inauthentic inputs,
i.e. cases where decryption is expected to fail due to the (ciphertext,
AAD) pair not being the correct result of an encryption with the key.

It also updates the self-tests to test passing misaligned buffers to the
various setkey() functions, and to check that skciphers have the same
min_keysize as the corresponding generic implementation.

I haven't seen any test failures from this on x86_64, arm64, or arm32.
But as usual I haven't tested drivers for crypto accelerators.

For this series to apply this cleanly, my other series
"crypto: skcipher - simplifications due to {,a}blkcipher removal"
needs to be applied first, due to a conflict in skcipher.h.

This can also be retrieved from git at
https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git
tag "crypto-self-tests_2019-12-01".

Eric Biggers (7):
crypto: aead - move crypto_aead_maxauthsize() to <crypto/aead.h>
crypto: skcipher - add crypto_skcipher_min_keysize()
crypto: testmgr - don't try to decrypt uninitialized buffers
crypto: testmgr - check skcipher min_keysize
crypto: testmgr - test setting misaligned keys
crypto: testmgr - create struct aead_extra_tests_ctx
crypto: testmgr - generate inauthentic AEAD test vectors

crypto/testmgr.c | 574 +++++++++++++++++++++++++--------
crypto/testmgr.h | 14 +-
include/crypto/aead.h | 10 +
include/crypto/internal/aead.h | 10 -
include/crypto/skcipher.h | 6 +
5 files changed, 461 insertions(+), 153 deletions(-)

--
2.24.0


2019-12-01 21:55:34

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 3/7] crypto: testmgr - don't try to decrypt uninitialized buffers

From: Eric Biggers <[email protected]>

Currently if the comparison fuzz tests encounter an encryption error
when generating an skcipher or AEAD test vector, they will still test
the decryption side (passing it the uninitialized ciphertext buffer)
and expect it to fail with the same error.

This is sort of broken because it's not well-defined usage of the API to
pass an uninitialized buffer, and furthermore in the AEAD case it's
acceptable for the decryption error to be EBADMSG (meaning "inauthentic
input") even if the encryption error was something else like EINVAL.

Fix this for skcipher by explicitly initializing the ciphertext buffer
on error, and for AEAD by skipping the decryption test on error.

Reported-by: Pascal Van Leeuwen <[email protected]>
Fixes: d435e10e67be ("crypto: testmgr - fuzz skciphers against their generic implementation")
Fixes: 40153b10d91c ("crypto: testmgr - fuzz AEADs against their generic implementation")
Signed-off-by: Eric Biggers <[email protected]>
---
crypto/testmgr.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 85d720a57bb0..a8940415512f 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2102,6 +2102,7 @@ static void generate_random_aead_testvec(struct aead_request *req,
* If the key or authentication tag size couldn't be set, no need to
* continue to encrypt.
*/
+ vec->crypt_error = 0;
if (vec->setkey_error || vec->setauthsize_error)
goto done;

@@ -2245,10 +2246,12 @@ static int test_aead_vs_generic_impl(const char *driver,
req, tsgls);
if (err)
goto out;
- err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, cfg,
- req, tsgls);
- if (err)
- goto out;
+ if (vec.crypt_error == 0) {
+ err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name,
+ cfg, req, tsgls);
+ if (err)
+ goto out;
+ }
cond_resched();
}
err = 0;
@@ -2678,6 +2681,15 @@ static void generate_random_cipher_testvec(struct skcipher_request *req,
skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
skcipher_request_set_crypt(req, &src, &dst, vec->len, iv);
vec->crypt_error = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
+ if (vec->crypt_error != 0) {
+ /*
+ * The only acceptable error here is for an invalid length, so
+ * skcipher decryption should fail with the same error too.
+ * We'll test for this. But to keep the API usage well-defined,
+ * explicitly initialize the ciphertext buffer too.
+ */
+ memset((u8 *)vec->ctext, 0, vec->len);
+ }
done:
snprintf(name, max_namelen, "\"random: len=%u klen=%u\"",
vec->len, vec->klen);
--
2.24.0

2019-12-01 21:56:11

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 4/7] crypto: testmgr - check skcipher min_keysize

From: Eric Biggers <[email protected]>

When checking two implementations of the same skcipher algorithm for
consistency, require that the minimum key size be the same, not just the
maximum key size. There's no good reason to allow different minimum key
sizes.

Signed-off-by: Eric Biggers <[email protected]>
---
crypto/testmgr.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index a8940415512f..3d7c1c1529cf 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2764,6 +2764,15 @@ static int test_skcipher_vs_generic_impl(const char *driver,

/* Check the algorithm properties for consistency. */

+ if (crypto_skcipher_min_keysize(tfm) !=
+ crypto_skcipher_min_keysize(generic_tfm)) {
+ pr_err("alg: skcipher: min keysize for %s (%u) doesn't match generic impl (%u)\n",
+ driver, crypto_skcipher_min_keysize(tfm),
+ crypto_skcipher_min_keysize(generic_tfm));
+ err = -EINVAL;
+ goto out;
+ }
+
if (maxkeysize != crypto_skcipher_max_keysize(generic_tfm)) {
pr_err("alg: skcipher: max keysize for %s (%u) doesn't match generic impl (%u)\n",
driver, maxkeysize,
--
2.24.0

2019-12-01 21:56:11

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 7/7] crypto: testmgr - generate inauthentic AEAD test vectors

From: Eric Biggers <[email protected]>

The whole point of using an AEAD over length-preserving encryption is
that the data is authenticated. However currently the fuzz tests don't
test any inauthentic inputs to verify that the data is actually being
authenticated. And only two algorithms ("rfc4543(gcm(aes))" and
"ccm(aes)") even have any inauthentic test vectors at all.

Therefore, update the AEAD fuzz tests to sometimes generate inauthentic
test vectors, either by generating a (ciphertext, AAD) pair without
using the key, or by mutating an authentic pair that was generated.

To avoid flakiness, only assume this works reliably if the auth tag is
at least 8 bytes. Also account for the rfc4106, rfc4309, and rfc7539esp
algorithms intentionally ignoring the last 8 AAD bytes, and for some
algorithms doing extra checks that result in EINVAL rather than EBADMSG.

Signed-off-by: Eric Biggers <[email protected]>
---
crypto/testmgr.c | 320 +++++++++++++++++++++++++++++++++++++----------
crypto/testmgr.h | 14 ++-
2 files changed, 261 insertions(+), 73 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 4fe210845e78..88f33c0efb23 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -82,6 +82,19 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
struct aead_test_suite {
const struct aead_testvec *vecs;
unsigned int count;
+
+ /*
+ * Set if trying to decrypt an inauthentic ciphertext with this
+ * algorithm might result in EINVAL rather than EBADMSG, due to other
+ * validation the algorithm does on the inputs such as length checks.
+ */
+ unsigned int einval_allowed : 1;
+
+ /*
+ * Set if the algorithm intentionally ignores the last 8 bytes of the
+ * AAD buffer during decryption.
+ */
+ unsigned int esp_aad : 1;
};

struct cipher_test_suite {
@@ -814,27 +827,39 @@ static unsigned int generate_random_length(unsigned int max_len)
}
}

-/* Sometimes make some random changes to the given data buffer */
-static void mutate_buffer(u8 *buf, size_t count)
+/* Flip a random bit in the given nonempty data buffer */
+static void flip_random_bit(u8 *buf, size_t size)
+{
+ size_t bitpos;
+
+ bitpos = prandom_u32() % (size * 8);
+ buf[bitpos / 8] ^= 1 << (bitpos % 8);
+}
+
+/* Flip a random byte in the given nonempty data buffer */
+static void flip_random_byte(u8 *buf, size_t size)
+{
+ buf[prandom_u32() % size] ^= 0xff;
+}
+
+/* Sometimes make some random changes to the given nonempty data buffer */
+static void mutate_buffer(u8 *buf, size_t size)
{
size_t num_flips;
size_t i;
- size_t pos;

/* Sometimes flip some bits */
if (prandom_u32() % 4 == 0) {
- num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count * 8);
- for (i = 0; i < num_flips; i++) {
- pos = prandom_u32() % (count * 8);
- buf[pos / 8] ^= 1 << (pos % 8);
- }
+ num_flips = min_t(size_t, 1 << (prandom_u32() % 8), size * 8);
+ for (i = 0; i < num_flips; i++)
+ flip_random_bit(buf, size);
}

/* Sometimes flip some bytes */
if (prandom_u32() % 4 == 0) {
- num_flips = min_t(size_t, 1 << (prandom_u32() % 8), count);
+ num_flips = min_t(size_t, 1 << (prandom_u32() % 8), size);
for (i = 0; i < num_flips; i++)
- buf[prandom_u32() % count] ^= 0xff;
+ flip_random_byte(buf, size);
}
}

@@ -1915,7 +1940,6 @@ static int test_aead_vec_cfg(const char *driver, int enc,
cfg->iv_offset +
(cfg->iv_offset_relative_to_alignmask ? alignmask : 0);
struct kvec input[2];
- int expected_error;
int err;

/* Set the key */
@@ -2036,20 +2060,31 @@ static int test_aead_vec_cfg(const char *driver, int enc,
return -EINVAL;
}

- /* Check for success or failure */
- expected_error = vec->novrfy ? -EBADMSG : vec->crypt_error;
- if (err) {
- if (err == expected_error)
- return 0;
- pr_err("alg: aead: %s %s failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
- driver, op, vec_name, expected_error, err, cfg->name);
- return err;
- }
- if (expected_error) {
- pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
+ /* Check for unexpected success or failure, or wrong error code */
+ if ((err == 0 && vec->novrfy) ||
+ (err != vec->crypt_error && !(err == -EBADMSG && vec->novrfy))) {
+ char expected_error[32];
+
+ if (vec->novrfy &&
+ vec->crypt_error != 0 && vec->crypt_error != -EBADMSG)
+ sprintf(expected_error, "-EBADMSG or %d",
+ vec->crypt_error);
+ else if (vec->novrfy)
+ sprintf(expected_error, "-EBADMSG");
+ else
+ sprintf(expected_error, "%d", vec->crypt_error);
+ if (err) {
+ pr_err("alg: aead: %s %s failed on test vector %s; expected_error=%s, actual_error=%d, cfg=\"%s\"\n",
+ driver, op, vec_name, expected_error, err,
+ cfg->name);
+ return err;
+ }
+ pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %s; expected_error=%s, cfg=\"%s\"\n",
driver, op, vec_name, expected_error, cfg->name);
return -EINVAL;
}
+ if (err) /* Expectedly failed. */
+ return 0;

/* Check for the correct output (ciphertext or plaintext) */
err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext,
@@ -2128,24 +2163,112 @@ struct aead_extra_tests_ctx {
};

/*
- * Generate an AEAD test vector from the given implementation.
- * Assumes the buffers in 'vec' were already allocated.
+ * Make at least one random change to a (ciphertext, AAD) pair. "Ciphertext"
+ * here means the full ciphertext including the authentication tag. The
+ * authentication tag (and hence also the ciphertext) is assumed to be nonempty.
+ */
+static void mutate_aead_message(struct aead_testvec *vec, bool esp_aad)
+{
+ const unsigned int aad_tail_size = esp_aad ? 8 : 0;
+ const unsigned int authsize = vec->clen - vec->plen;
+
+ if (prandom_u32() % 2 == 0 && vec->alen > aad_tail_size) {
+ /* Mutate the AAD */
+ flip_random_bit((u8 *)vec->assoc, vec->alen - aad_tail_size);
+ if (prandom_u32() % 2 == 0)
+ return;
+ }
+ if (prandom_u32() % 2 == 0) {
+ /* Mutate auth tag (assuming it's at the end of ciphertext) */
+ flip_random_bit((u8 *)vec->ctext + vec->plen, authsize);
+ } else {
+ /* Mutate any part of the ciphertext */
+ flip_random_bit((u8 *)vec->ctext, vec->clen);
+ }
+}
+
+/*
+ * Minimum authentication tag size in bytes at which we assume that we can
+ * reliably generate inauthentic messages, i.e. not generate an authentic
+ * message by chance.
+ */
+#define MIN_COLLISION_FREE_AUTHSIZE 8
+
+static void generate_aead_message(struct aead_request *req,
+ const struct aead_test_suite *suite,
+ struct aead_testvec *vec,
+ bool prefer_inauthentic)
+{
+ struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+ const unsigned int ivsize = crypto_aead_ivsize(tfm);
+ const unsigned int authsize = vec->clen - vec->plen;
+ const bool inauthentic = (authsize >= MIN_COLLISION_FREE_AUTHSIZE) &&
+ (prefer_inauthentic || prandom_u32() % 4 == 0);
+
+ /* Generate the AAD. */
+ generate_random_bytes((u8 *)vec->assoc, vec->alen);
+
+ if (inauthentic && prandom_u32() % 2 == 0) {
+ /* Generate a random ciphertext. */
+ generate_random_bytes((u8 *)vec->ctext, vec->clen);
+ } else {
+ int i = 0;
+ struct scatterlist src[2], dst;
+ u8 iv[MAX_IVLEN];
+ DECLARE_CRYPTO_WAIT(wait);
+
+ /* Generate a random plaintext and encrypt it. */
+ sg_init_table(src, 2);
+ if (vec->alen)
+ sg_set_buf(&src[i++], vec->assoc, vec->alen);
+ if (vec->plen) {
+ generate_random_bytes((u8 *)vec->ptext, vec->plen);
+ sg_set_buf(&src[i++], vec->ptext, vec->plen);
+ }
+ sg_init_one(&dst, vec->ctext, vec->alen + vec->clen);
+ memcpy(iv, vec->iv, ivsize);
+ aead_request_set_callback(req, 0, crypto_req_done, &wait);
+ aead_request_set_crypt(req, src, &dst, vec->plen, iv);
+ aead_request_set_ad(req, vec->alen);
+ vec->crypt_error = crypto_wait_req(crypto_aead_encrypt(req),
+ &wait);
+ /* If encryption failed, we're done. */
+ if (vec->crypt_error != 0)
+ return;
+ memmove((u8 *)vec->ctext, vec->ctext + vec->alen, vec->clen);
+ if (!inauthentic)
+ return;
+ /*
+ * Mutate the authentic (ciphertext, AAD) pair to get an
+ * inauthentic one.
+ */
+ mutate_aead_message(vec, suite->esp_aad);
+ }
+ vec->novrfy = 1;
+ if (suite->einval_allowed)
+ vec->crypt_error = -EINVAL;
+}
+
+/*
+ * Generate an AEAD test vector 'vec' using the implementation specified by
+ * 'req'. The buffers in 'vec' must already be allocated.
+ *
+ * If 'prefer_inauthentic' is true, then this function will generate inauthentic
+ * test vectors (i.e. vectors with 'vec->novrfy=1') more often.
*/
static void generate_random_aead_testvec(struct aead_request *req,
struct aead_testvec *vec,
+ const struct aead_test_suite *suite,
unsigned int maxkeysize,
unsigned int maxdatasize,
- char *name, size_t max_namelen)
+ char *name, size_t max_namelen,
+ bool prefer_inauthentic)
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
const unsigned int ivsize = crypto_aead_ivsize(tfm);
const unsigned int maxauthsize = crypto_aead_maxauthsize(tfm);
unsigned int authsize;
unsigned int total_len;
- int i;
- struct scatterlist src[2], dst;
- u8 iv[MAX_IVLEN];
- DECLARE_CRYPTO_WAIT(wait);

/* Key: length in [0, maxkeysize], but usually choose maxkeysize */
vec->klen = maxkeysize;
@@ -2161,50 +2284,83 @@ static void generate_random_aead_testvec(struct aead_request *req,
authsize = maxauthsize;
if (prandom_u32() % 4 == 0)
authsize = prandom_u32() % (maxauthsize + 1);
+ if (prefer_inauthentic && authsize < MIN_COLLISION_FREE_AUTHSIZE)
+ authsize = MIN_COLLISION_FREE_AUTHSIZE;
if (WARN_ON(authsize > maxdatasize))
authsize = maxdatasize;
maxdatasize -= authsize;
vec->setauthsize_error = crypto_aead_setauthsize(tfm, authsize);

- /* Plaintext and associated data */
+ /* AAD, plaintext, and ciphertext lengths */
total_len = generate_random_length(maxdatasize);
if (prandom_u32() % 4 == 0)
vec->alen = 0;
else
vec->alen = generate_random_length(total_len);
vec->plen = total_len - vec->alen;
- generate_random_bytes((u8 *)vec->assoc, vec->alen);
- generate_random_bytes((u8 *)vec->ptext, vec->plen);
-
vec->clen = vec->plen + authsize;

/*
- * If the key or authentication tag size couldn't be set, no need to
- * continue to encrypt.
+ * Generate the AAD, plaintext, and ciphertext. Not applicable if the
+ * key or the authentication tag size couldn't be set.
*/
+ vec->novrfy = 0;
vec->crypt_error = 0;
- if (vec->setkey_error || vec->setauthsize_error)
- goto done;
-
- /* Ciphertext */
- sg_init_table(src, 2);
- i = 0;
- if (vec->alen)
- sg_set_buf(&src[i++], vec->assoc, vec->alen);
- if (vec->plen)
- sg_set_buf(&src[i++], vec->ptext, vec->plen);
- sg_init_one(&dst, vec->ctext, vec->alen + vec->clen);
- memcpy(iv, vec->iv, ivsize);
- aead_request_set_callback(req, 0, crypto_req_done, &wait);
- aead_request_set_crypt(req, src, &dst, vec->plen, iv);
- aead_request_set_ad(req, vec->alen);
- vec->crypt_error = crypto_wait_req(crypto_aead_encrypt(req), &wait);
- if (vec->crypt_error == 0)
- memmove((u8 *)vec->ctext, vec->ctext + vec->alen, vec->clen);
-done:
+ if (vec->setkey_error == 0 && vec->setauthsize_error == 0)
+ generate_aead_message(req, suite, vec, prefer_inauthentic);
snprintf(name, max_namelen,
- "\"random: alen=%u plen=%u authsize=%u klen=%u\"",
- vec->alen, vec->plen, authsize, vec->klen);
+ "\"random: alen=%u plen=%u authsize=%u klen=%u novrfy=%d\"",
+ vec->alen, vec->plen, authsize, vec->klen, vec->novrfy);
+}
+
+static void try_to_generate_inauthentic_testvec(
+ struct aead_extra_tests_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ generate_random_aead_testvec(ctx->req, &ctx->vec,
+ &ctx->test_desc->suite.aead,
+ ctx->maxkeysize, ctx->maxdatasize,
+ ctx->vec_name,
+ sizeof(ctx->vec_name), true);
+ if (ctx->vec.novrfy)
+ return;
+ }
+}
+
+/*
+ * Generate inauthentic test vectors (i.e. ciphertext, AAD pairs that aren't the
+ * result of an encryption with the key) and verify that decryption fails.
+ */
+static int test_aead_inauthentic_inputs(struct aead_extra_tests_ctx *ctx)
+{
+ unsigned int i;
+ int err;
+
+ for (i = 0; i < fuzz_iterations * 8; i++) {
+ /*
+ * Since this part of the tests isn't comparing the
+ * implementation to another, there's no point in testing any
+ * test vectors other than inauthentic ones (vec.novrfy=1) here.
+ *
+ * If we're having trouble generating such a test vector, e.g.
+ * if the algorithm keeps rejecting the generated keys, don't
+ * retry forever; just continue on.
+ */
+ try_to_generate_inauthentic_testvec(ctx);
+ if (ctx->vec.novrfy) {
+ generate_random_testvec_config(&ctx->cfg, ctx->cfgname,
+ sizeof(ctx->cfgname));
+ err = test_aead_vec_cfg(ctx->driver, DECRYPT, &ctx->vec,
+ ctx->vec_name, &ctx->cfg,
+ ctx->req, ctx->tsgls);
+ if (err)
+ return err;
+ }
+ cond_resched();
+ }
+ return 0;
}

/*
@@ -2285,17 +2441,20 @@ static int test_aead_vs_generic_impl(struct aead_extra_tests_ctx *ctx)
*/
for (i = 0; i < fuzz_iterations * 8; i++) {
generate_random_aead_testvec(generic_req, &ctx->vec,
+ &ctx->test_desc->suite.aead,
ctx->maxkeysize, ctx->maxdatasize,
ctx->vec_name,
- sizeof(ctx->vec_name));
+ sizeof(ctx->vec_name), false);
generate_random_testvec_config(&ctx->cfg, ctx->cfgname,
sizeof(ctx->cfgname));
- err = test_aead_vec_cfg(driver, ENCRYPT, &ctx->vec,
- ctx->vec_name, &ctx->cfg,
- ctx->req, ctx->tsgls);
- if (err)
- goto out;
- if (ctx->vec.crypt_error == 0) {
+ if (!ctx->vec.novrfy) {
+ err = test_aead_vec_cfg(driver, ENCRYPT, &ctx->vec,
+ ctx->vec_name, &ctx->cfg,
+ ctx->req, ctx->tsgls);
+ if (err)
+ goto out;
+ }
+ if (ctx->vec.crypt_error == 0 || ctx->vec.novrfy) {
err = test_aead_vec_cfg(driver, DECRYPT, &ctx->vec,
ctx->vec_name, &ctx->cfg,
ctx->req, ctx->tsgls);
@@ -2348,6 +2507,10 @@ static int test_aead_extra(const char *driver,
goto out;
}

+ err = test_aead_inauthentic_inputs(ctx);
+ if (err)
+ goto out;
+
err = test_aead_vs_generic_impl(ctx);
out:
kfree(ctx->vec.key);
@@ -3978,7 +4141,8 @@ static int alg_test_null(const struct alg_test_desc *desc,
return 0;
}

-#define __VECS(tv) { .vecs = tv, .count = ARRAY_SIZE(tv) }
+#define ____VECS(tv) .vecs = tv, .count = ARRAY_SIZE(tv)
+#define __VECS(tv) { ____VECS(tv) }

/* Please keep this list sorted by algorithm name. */
static const struct alg_test_desc alg_test_descs[] = {
@@ -4284,7 +4448,10 @@ static const struct alg_test_desc alg_test_descs[] = {
.test = alg_test_aead,
.fips_allowed = 1,
.suite = {
- .aead = __VECS(aes_ccm_tv_template)
+ .aead = {
+ ____VECS(aes_ccm_tv_template),
+ .einval_allowed = 1,
+ }
}
}, {
.alg = "cfb(aes)",
@@ -5032,7 +5199,11 @@ static const struct alg_test_desc alg_test_descs[] = {
.test = alg_test_aead,
.fips_allowed = 1,
.suite = {
- .aead = __VECS(aes_gcm_rfc4106_tv_template)
+ .aead = {
+ ____VECS(aes_gcm_rfc4106_tv_template),
+ .einval_allowed = 1,
+ .esp_aad = 1,
+ }
}
}, {
.alg = "rfc4309(ccm(aes))",
@@ -5040,14 +5211,21 @@ static const struct alg_test_desc alg_test_descs[] = {
.test = alg_test_aead,
.fips_allowed = 1,
.suite = {
- .aead = __VECS(aes_ccm_rfc4309_tv_template)
+ .aead = {
+ ____VECS(aes_ccm_rfc4309_tv_template),
+ .einval_allowed = 1,
+ .esp_aad = 1,
+ }
}
}, {
.alg = "rfc4543(gcm(aes))",
.generic_driver = "rfc4543(gcm_base(ctr(aes-generic),ghash-generic))",
.test = alg_test_aead,
.suite = {
- .aead = __VECS(aes_gcm_rfc4543_tv_template)
+ .aead = {
+ ____VECS(aes_gcm_rfc4543_tv_template),
+ .einval_allowed = 1,
+ }
}
}, {
.alg = "rfc7539(chacha20,poly1305)",
@@ -5059,7 +5237,11 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "rfc7539esp(chacha20,poly1305)",
.test = alg_test_aead,
.suite = {
- .aead = __VECS(rfc7539esp_tv_template)
+ .aead = {
+ ____VECS(rfc7539esp_tv_template),
+ .einval_allowed = 1,
+ .esp_aad = 1,
+ }
}
}, {
.alg = "rmd128",
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 48da646651cb..d29983908c38 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -85,16 +85,22 @@ struct cipher_testvec {
* @ctext: Pointer to the full authenticated ciphertext. For AEADs that
* produce a separate "ciphertext" and "authentication tag", these
* two parts are concatenated: ciphertext || tag.
- * @novrfy: Decryption verification failure expected?
+ * @novrfy: If set, this is an inauthentic input test: only decryption is
+ * tested, and it is expected to fail with either -EBADMSG or
+ * @crypt_error if it is nonzero.
* @wk: Does the test need CRYPTO_TFM_REQ_FORBID_WEAK_KEYS?
* (e.g. setkey() needs to fail due to a weak key)
* @klen: Length of @key in bytes
* @plen: Length of @ptext in bytes
* @alen: Length of @assoc in bytes
* @clen: Length of @ctext in bytes
- * @setkey_error: Expected error from setkey()
- * @setauthsize_error: Expected error from setauthsize()
- * @crypt_error: Expected error from encrypt() and decrypt()
+ * @setkey_error: Expected error from setkey(). If set, neither encryption nor
+ * decryption is tested.
+ * @setauthsize_error: Expected error from setauthsize(). If set, neither
+ * encryption nor decryption is tested.
+ * @crypt_error: When @novrfy=0, the expected error from encrypt(). When
+ * @novrfy=1, an optional alternate error code that is acceptable
+ * for decrypt() to return besides -EBADMSG.
*/
struct aead_testvec {
const char *key;
--
2.24.0

2019-12-01 21:56:18

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 5/7] crypto: testmgr - test setting misaligned keys

From: Eric Biggers <[email protected]>

The alignment bug in ghash_setkey() fixed by commit 5c6bc4dfa515
("crypto: ghash - fix unaligned memory access in ghash_setkey()")
wasn't reliably detected by the crypto self-tests on ARM because the
tests only set the keys directly from the test vectors.

To improve test coverage, update the tests to sometimes pass misaligned
keys to setkey(). This applies to shash, ahash, skcipher, and aead.

Signed-off-by: Eric Biggers <[email protected]>
---
crypto/testmgr.c | 73 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 69 insertions(+), 4 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 3d7c1c1529cf..d1ffa8f73948 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -259,6 +259,9 @@ struct test_sg_division {
* where 0 is aligned to a 2*(MAX_ALGAPI_ALIGNMASK+1) byte boundary
* @iv_offset_relative_to_alignmask: if true, add the algorithm's alignmask to
* the @iv_offset
+ * @key_offset: misalignment of the key, where 0 is default alignment
+ * @key_offset_relative_to_alignmask: if true, add the algorithm's alignmask to
+ * the @key_offset
* @finalization_type: what finalization function to use for hashes
* @nosimd: execute with SIMD disabled? Requires !CRYPTO_TFM_REQ_MAY_SLEEP.
*/
@@ -269,7 +272,9 @@ struct testvec_config {
struct test_sg_division src_divs[XBUFSIZE];
struct test_sg_division dst_divs[XBUFSIZE];
unsigned int iv_offset;
+ unsigned int key_offset;
bool iv_offset_relative_to_alignmask;
+ bool key_offset_relative_to_alignmask;
enum finalization_type finalization_type;
bool nosimd;
};
@@ -297,6 +302,7 @@ static const struct testvec_config default_cipher_testvec_configs[] = {
.name = "unaligned buffer, offset=1",
.src_divs = { { .proportion_of_total = 10000, .offset = 1 } },
.iv_offset = 1,
+ .key_offset = 1,
}, {
.name = "buffer aligned only to alignmask",
.src_divs = {
@@ -308,6 +314,8 @@ static const struct testvec_config default_cipher_testvec_configs[] = {
},
.iv_offset = 1,
.iv_offset_relative_to_alignmask = true,
+ .key_offset = 1,
+ .key_offset_relative_to_alignmask = true,
}, {
.name = "two even aligned splits",
.src_divs = {
@@ -323,6 +331,7 @@ static const struct testvec_config default_cipher_testvec_configs[] = {
{ .proportion_of_total = 4800, .offset = 18 },
},
.iv_offset = 3,
+ .key_offset = 3,
}, {
.name = "misaligned splits crossing pages, inplace",
.inplace = true,
@@ -355,6 +364,7 @@ static const struct testvec_config default_hash_testvec_configs[] = {
.name = "init+update+final misaligned buffer",
.src_divs = { { .proportion_of_total = 10000, .offset = 1 } },
.finalization_type = FINALIZATION_TYPE_FINAL,
+ .key_offset = 1,
}, {
.name = "digest buffer aligned only to alignmask",
.src_divs = {
@@ -365,6 +375,8 @@ static const struct testvec_config default_hash_testvec_configs[] = {
},
},
.finalization_type = FINALIZATION_TYPE_DIGEST,
+ .key_offset = 1,
+ .key_offset_relative_to_alignmask = true,
}, {
.name = "init+update+update+final two even splits",
.src_divs = {
@@ -740,6 +752,49 @@ static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls,
alignmask, dst_total_len, NULL, NULL);
}

+/*
+ * Support for testing passing a misaligned key to setkey():
+ *
+ * If cfg->key_offset is set, copy the key into a new buffer at that offset,
+ * optionally adding alignmask. Else, just use the key directly.
+ */
+static int prepare_keybuf(const u8 *key, unsigned int ksize,
+ const struct testvec_config *cfg,
+ unsigned int alignmask,
+ const u8 **keybuf_ret, const u8 **keyptr_ret)
+{
+ unsigned int key_offset = cfg->key_offset;
+ u8 *keybuf = NULL, *keyptr = (u8 *)key;
+
+ if (key_offset != 0) {
+ if (cfg->key_offset_relative_to_alignmask)
+ key_offset += alignmask;
+ keybuf = kmalloc(key_offset + ksize, GFP_KERNEL);
+ if (!keybuf)
+ return -ENOMEM;
+ keyptr = keybuf + key_offset;
+ memcpy(keyptr, key, ksize);
+ }
+ *keybuf_ret = keybuf;
+ *keyptr_ret = keyptr;
+ return 0;
+}
+
+/* Like setkey_f(tfm, key, ksize), but sometimes misalign the key */
+#define do_setkey(setkey_f, tfm, key, ksize, cfg, alignmask) \
+({ \
+ const u8 *keybuf, *keyptr; \
+ int err; \
+ \
+ err = prepare_keybuf((key), (ksize), (cfg), (alignmask), \
+ &keybuf, &keyptr); \
+ if (err == 0) { \
+ err = setkey_f((tfm), keyptr, (ksize)); \
+ kfree(keybuf); \
+ } \
+ err; \
+})
+
#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS

/* Generate a random length in range [0, max_len], but prefer smaller values */
@@ -966,6 +1021,11 @@ static void generate_random_testvec_config(struct testvec_config *cfg,
p += scnprintf(p, end - p, " iv_offset=%u", cfg->iv_offset);
}

+ if (prandom_u32() % 2 == 0) {
+ cfg->key_offset = 1 + (prandom_u32() % MAX_ALGAPI_ALIGNMASK);
+ p += scnprintf(p, end - p, " key_offset=%u", cfg->key_offset);
+ }
+
WARN_ON_ONCE(!valid_testvec_config(cfg));
}

@@ -1103,7 +1163,8 @@ static int test_shash_vec_cfg(const char *driver,

/* Set the key, if specified */
if (vec->ksize) {
- err = crypto_shash_setkey(tfm, vec->key, vec->ksize);
+ err = do_setkey(crypto_shash_setkey, tfm, vec->key, vec->ksize,
+ cfg, alignmask);
if (err) {
if (err == vec->setkey_error)
return 0;
@@ -1290,7 +1351,8 @@ static int test_ahash_vec_cfg(const char *driver,

/* Set the key, if specified */
if (vec->ksize) {
- err = crypto_ahash_setkey(tfm, vec->key, vec->ksize);
+ err = do_setkey(crypto_ahash_setkey, tfm, vec->key, vec->ksize,
+ cfg, alignmask);
if (err) {
if (err == vec->setkey_error)
return 0;
@@ -1861,7 +1923,9 @@ static int test_aead_vec_cfg(const char *driver, int enc,
crypto_aead_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
else
crypto_aead_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
- err = crypto_aead_setkey(tfm, vec->key, vec->klen);
+
+ err = do_setkey(crypto_aead_setkey, tfm, vec->key, vec->klen,
+ cfg, alignmask);
if (err && err != vec->setkey_error) {
pr_err("alg: aead: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
driver, vec_name, vec->setkey_error, err,
@@ -2460,7 +2524,8 @@ static int test_skcipher_vec_cfg(const char *driver, int enc,
else
crypto_skcipher_clear_flags(tfm,
CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
- err = crypto_skcipher_setkey(tfm, vec->key, vec->klen);
+ err = do_setkey(crypto_skcipher_setkey, tfm, vec->key, vec->klen,
+ cfg, alignmask);
if (err) {
if (err == vec->setkey_error)
return 0;
--
2.24.0

2019-12-01 21:56:55

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 6/7] crypto: testmgr - create struct aead_extra_tests_ctx

From: Eric Biggers <[email protected]>

In preparation for adding inauthentic input fuzz tests, which don't
require that a generic implementation of the algorithm be available,
refactor test_aead_vs_generic_impl() so that instead there's a
higher-level function test_aead_extra() which initializes a struct
aead_extra_tests_ctx and then calls test_aead_vs_generic_impl() with a
pointer to that struct.

As a bonus, this reduces stack usage.

Also switch from crypto_aead_alg(tfm)->maxauthsize to
crypto_aead_maxauthsize(), now that the latter is available in
<crypto/aead.h>.

Signed-off-by: Eric Biggers <[email protected]>
---
crypto/testmgr.c | 170 +++++++++++++++++++++++++++--------------------
1 file changed, 99 insertions(+), 71 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index d1ffa8f73948..4fe210845e78 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2111,6 +2111,22 @@ static int test_aead_vec(const char *driver, int enc,
}

#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
+
+struct aead_extra_tests_ctx {
+ struct aead_request *req;
+ struct crypto_aead *tfm;
+ const char *driver;
+ const struct alg_test_desc *test_desc;
+ struct cipher_test_sglists *tsgls;
+ unsigned int maxdatasize;
+ unsigned int maxkeysize;
+
+ struct aead_testvec vec;
+ char vec_name[64];
+ char cfgname[TESTVEC_CONFIG_NAMELEN];
+ struct testvec_config cfg;
+};
+
/*
* Generate an AEAD test vector from the given implementation.
* Assumes the buffers in 'vec' were already allocated.
@@ -2123,7 +2139,7 @@ static void generate_random_aead_testvec(struct aead_request *req,
{
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
const unsigned int ivsize = crypto_aead_ivsize(tfm);
- unsigned int maxauthsize = crypto_aead_alg(tfm)->maxauthsize;
+ const unsigned int maxauthsize = crypto_aead_maxauthsize(tfm);
unsigned int authsize;
unsigned int total_len;
int i;
@@ -2192,35 +2208,21 @@ static void generate_random_aead_testvec(struct aead_request *req,
}

/*
- * Test the AEAD algorithm represented by @req against the corresponding generic
- * implementation, if one is available.
+ * Test the AEAD algorithm against the corresponding generic implementation, if
+ * one is available.
*/
-static int test_aead_vs_generic_impl(const char *driver,
- const struct alg_test_desc *test_desc,
- struct aead_request *req,
- struct cipher_test_sglists *tsgls)
+static int test_aead_vs_generic_impl(struct aead_extra_tests_ctx *ctx)
{
- struct crypto_aead *tfm = crypto_aead_reqtfm(req);
- const unsigned int ivsize = crypto_aead_ivsize(tfm);
- const unsigned int maxauthsize = crypto_aead_alg(tfm)->maxauthsize;
- const unsigned int blocksize = crypto_aead_blocksize(tfm);
- const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
+ struct crypto_aead *tfm = ctx->tfm;
const char *algname = crypto_aead_alg(tfm)->base.cra_name;
- const char *generic_driver = test_desc->generic_driver;
+ const char *driver = ctx->driver;
+ const char *generic_driver = ctx->test_desc->generic_driver;
char _generic_driver[CRYPTO_MAX_ALG_NAME];
struct crypto_aead *generic_tfm = NULL;
struct aead_request *generic_req = NULL;
- unsigned int maxkeysize;
unsigned int i;
- struct aead_testvec vec = { 0 };
- char vec_name[64];
- struct testvec_config *cfg;
- char cfgname[TESTVEC_CONFIG_NAMELEN];
int err;

- if (noextratests)
- return 0;
-
if (!generic_driver) { /* Use default naming convention? */
err = build_generic_driver_name(algname, _generic_driver);
if (err)
@@ -2244,12 +2246,6 @@ static int test_aead_vs_generic_impl(const char *driver,
return err;
}

- cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
- if (!cfg) {
- err = -ENOMEM;
- goto out;
- }
-
generic_req = aead_request_alloc(generic_tfm, GFP_KERNEL);
if (!generic_req) {
err = -ENOMEM;
@@ -2258,24 +2254,27 @@ static int test_aead_vs_generic_impl(const char *driver,

/* Check the algorithm properties for consistency. */

- if (maxauthsize != crypto_aead_alg(generic_tfm)->maxauthsize) {
+ if (crypto_aead_maxauthsize(tfm) !=
+ crypto_aead_maxauthsize(generic_tfm)) {
pr_err("alg: aead: maxauthsize for %s (%u) doesn't match generic impl (%u)\n",
- driver, maxauthsize,
- crypto_aead_alg(generic_tfm)->maxauthsize);
+ driver, crypto_aead_maxauthsize(tfm),
+ crypto_aead_maxauthsize(generic_tfm));
err = -EINVAL;
goto out;
}

- if (ivsize != crypto_aead_ivsize(generic_tfm)) {
+ if (crypto_aead_ivsize(tfm) != crypto_aead_ivsize(generic_tfm)) {
pr_err("alg: aead: ivsize for %s (%u) doesn't match generic impl (%u)\n",
- driver, ivsize, crypto_aead_ivsize(generic_tfm));
+ driver, crypto_aead_ivsize(tfm),
+ crypto_aead_ivsize(generic_tfm));
err = -EINVAL;
goto out;
}

- if (blocksize != crypto_aead_blocksize(generic_tfm)) {
+ if (crypto_aead_blocksize(tfm) != crypto_aead_blocksize(generic_tfm)) {
pr_err("alg: aead: blocksize for %s (%u) doesn't match generic impl (%u)\n",
- driver, blocksize, crypto_aead_blocksize(generic_tfm));
+ driver, crypto_aead_blocksize(tfm),
+ crypto_aead_blocksize(generic_tfm));
err = -EINVAL;
goto out;
}
@@ -2284,35 +2283,22 @@ static int test_aead_vs_generic_impl(const char *driver,
* Now generate test vectors using the generic implementation, and test
* the other implementation against them.
*/
-
- maxkeysize = 0;
- for (i = 0; i < test_desc->suite.aead.count; i++)
- maxkeysize = max_t(unsigned int, maxkeysize,
- test_desc->suite.aead.vecs[i].klen);
-
- vec.key = kmalloc(maxkeysize, GFP_KERNEL);
- vec.iv = kmalloc(ivsize, GFP_KERNEL);
- vec.assoc = kmalloc(maxdatasize, GFP_KERNEL);
- vec.ptext = kmalloc(maxdatasize, GFP_KERNEL);
- vec.ctext = kmalloc(maxdatasize, GFP_KERNEL);
- if (!vec.key || !vec.iv || !vec.assoc || !vec.ptext || !vec.ctext) {
- err = -ENOMEM;
- goto out;
- }
-
for (i = 0; i < fuzz_iterations * 8; i++) {
- generate_random_aead_testvec(generic_req, &vec,
- maxkeysize, maxdatasize,
- vec_name, sizeof(vec_name));
- generate_random_testvec_config(cfg, cfgname, sizeof(cfgname));
-
- err = test_aead_vec_cfg(driver, ENCRYPT, &vec, vec_name, cfg,
- req, tsgls);
+ generate_random_aead_testvec(generic_req, &ctx->vec,
+ ctx->maxkeysize, ctx->maxdatasize,
+ ctx->vec_name,
+ sizeof(ctx->vec_name));
+ generate_random_testvec_config(&ctx->cfg, ctx->cfgname,
+ sizeof(ctx->cfgname));
+ err = test_aead_vec_cfg(driver, ENCRYPT, &ctx->vec,
+ ctx->vec_name, &ctx->cfg,
+ ctx->req, ctx->tsgls);
if (err)
goto out;
- if (vec.crypt_error == 0) {
- err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name,
- cfg, req, tsgls);
+ if (ctx->vec.crypt_error == 0) {
+ err = test_aead_vec_cfg(driver, DECRYPT, &ctx->vec,
+ ctx->vec_name, &ctx->cfg,
+ ctx->req, ctx->tsgls);
if (err)
goto out;
}
@@ -2320,21 +2306,63 @@ static int test_aead_vs_generic_impl(const char *driver,
}
err = 0;
out:
- kfree(cfg);
- kfree(vec.key);
- kfree(vec.iv);
- kfree(vec.assoc);
- kfree(vec.ptext);
- kfree(vec.ctext);
crypto_free_aead(generic_tfm);
aead_request_free(generic_req);
return err;
}
+
+static int test_aead_extra(const char *driver,
+ const struct alg_test_desc *test_desc,
+ struct aead_request *req,
+ struct cipher_test_sglists *tsgls)
+{
+ struct aead_extra_tests_ctx *ctx;
+ unsigned int i;
+ int err;
+
+ if (noextratests)
+ return 0;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ ctx->req = req;
+ ctx->tfm = crypto_aead_reqtfm(req);
+ ctx->driver = driver;
+ ctx->test_desc = test_desc;
+ ctx->tsgls = tsgls;
+ ctx->maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
+ ctx->maxkeysize = 0;
+ for (i = 0; i < test_desc->suite.aead.count; i++)
+ ctx->maxkeysize = max_t(unsigned int, ctx->maxkeysize,
+ test_desc->suite.aead.vecs[i].klen);
+
+ ctx->vec.key = kmalloc(ctx->maxkeysize, GFP_KERNEL);
+ ctx->vec.iv = kmalloc(crypto_aead_ivsize(ctx->tfm), GFP_KERNEL);
+ ctx->vec.assoc = kmalloc(ctx->maxdatasize, GFP_KERNEL);
+ ctx->vec.ptext = kmalloc(ctx->maxdatasize, GFP_KERNEL);
+ ctx->vec.ctext = kmalloc(ctx->maxdatasize, GFP_KERNEL);
+ if (!ctx->vec.key || !ctx->vec.iv || !ctx->vec.assoc ||
+ !ctx->vec.ptext || !ctx->vec.ctext) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = test_aead_vs_generic_impl(ctx);
+out:
+ kfree(ctx->vec.key);
+ kfree(ctx->vec.iv);
+ kfree(ctx->vec.assoc);
+ kfree(ctx->vec.ptext);
+ kfree(ctx->vec.ctext);
+ kfree(ctx);
+ return err;
+}
#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
-static int test_aead_vs_generic_impl(const char *driver,
- const struct alg_test_desc *test_desc,
- struct aead_request *req,
- struct cipher_test_sglists *tsgls)
+static int test_aead_extra(const char *driver,
+ const struct alg_test_desc *test_desc,
+ struct aead_request *req,
+ struct cipher_test_sglists *tsgls)
{
return 0;
}
@@ -2403,7 +2431,7 @@ static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
if (err)
goto out;

- err = test_aead_vs_generic_impl(driver, desc, req, tsgls);
+ err = test_aead_extra(driver, desc, req, tsgls);
out:
free_cipher_test_sglists(tsgls);
aead_request_free(req);
--
2.24.0

2019-12-03 12:39:52

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [PATCH 0/7] crypto: more self-test improvements

On Sun, 1 Dec 2019 at 21:54, Eric Biggers <[email protected]> wrote:
>
> This series makes some more improvements to the crypto self-tests, the
> largest of which is making the AEAD fuzz tests test inauthentic inputs,
> i.e. cases where decryption is expected to fail due to the (ciphertext,
> AAD) pair not being the correct result of an encryption with the key.
>
> It also updates the self-tests to test passing misaligned buffers to the
> various setkey() functions, and to check that skciphers have the same
> min_keysize as the corresponding generic implementation.
>
> I haven't seen any test failures from this on x86_64, arm64, or arm32.
> But as usual I haven't tested drivers for crypto accelerators.
>
> For this series to apply this cleanly, my other series
> "crypto: skcipher - simplifications due to {,a}blkcipher removal"
> needs to be applied first, due to a conflict in skcipher.h.
>
> This can also be retrieved from git at
> https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git
> tag "crypto-self-tests_2019-12-01".
>
> Eric Biggers (7):
> crypto: aead - move crypto_aead_maxauthsize() to <crypto/aead.h>
> crypto: skcipher - add crypto_skcipher_min_keysize()
> crypto: testmgr - don't try to decrypt uninitialized buffers
> crypto: testmgr - check skcipher min_keysize
> crypto: testmgr - test setting misaligned keys
> crypto: testmgr - create struct aead_extra_tests_ctx
> crypto: testmgr - generate inauthentic AEAD test vectors
>

I've dropped this into kernelci again, let's see if anything turns out
to be broken.

For this series,

Acked-by: Ard Biesheuvel <[email protected]>

> crypto/testmgr.c | 574 +++++++++++++++++++++++++--------
> crypto/testmgr.h | 14 +-
> include/crypto/aead.h | 10 +
> include/crypto/internal/aead.h | 10 -
> include/crypto/skcipher.h | 6 +
> 5 files changed, 461 insertions(+), 153 deletions(-)
>
> --
> 2.24.0
>

2019-12-04 14:43:58

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [PATCH 0/7] crypto: more self-test improvements

On Tue, 3 Dec 2019 at 12:39, Ard Biesheuvel <[email protected]> wrote:
>
> On Sun, 1 Dec 2019 at 21:54, Eric Biggers <[email protected]> wrote:
> >
> > This series makes some more improvements to the crypto self-tests, the
> > largest of which is making the AEAD fuzz tests test inauthentic inputs,
> > i.e. cases where decryption is expected to fail due to the (ciphertext,
> > AAD) pair not being the correct result of an encryption with the key.
> >
> > It also updates the self-tests to test passing misaligned buffers to the
> > various setkey() functions, and to check that skciphers have the same
> > min_keysize as the corresponding generic implementation.
> >
> > I haven't seen any test failures from this on x86_64, arm64, or arm32.
> > But as usual I haven't tested drivers for crypto accelerators.
> >
> > For this series to apply this cleanly, my other series
> > "crypto: skcipher - simplifications due to {,a}blkcipher removal"
> > needs to be applied first, due to a conflict in skcipher.h.
> >
> > This can also be retrieved from git at
> > https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git
> > tag "crypto-self-tests_2019-12-01".
> >
> > Eric Biggers (7):
> > crypto: aead - move crypto_aead_maxauthsize() to <crypto/aead.h>
> > crypto: skcipher - add crypto_skcipher_min_keysize()
> > crypto: testmgr - don't try to decrypt uninitialized buffers
> > crypto: testmgr - check skcipher min_keysize
> > crypto: testmgr - test setting misaligned keys
> > crypto: testmgr - create struct aead_extra_tests_ctx
> > crypto: testmgr - generate inauthentic AEAD test vectors
> >
>
> I've dropped this into kernelci again, let's see if anything turns out
> to be broken.
>
> For this series,
>
> Acked-by: Ard Biesheuvel <[email protected]>
>

Results here:
https://kernelci.org/boot/all/job/ardb/branch/for-kernelci/kernel/v5.4-9340-g16839329da69/

Only the usual suspects failed (rk3288)


> > crypto/testmgr.c | 574 +++++++++++++++++++++++++--------
> > crypto/testmgr.h | 14 +-
> > include/crypto/aead.h | 10 +
> > include/crypto/internal/aead.h | 10 -
> > include/crypto/skcipher.h | 6 +
> > 5 files changed, 461 insertions(+), 153 deletions(-)
> >
> > --
> > 2.24.0
> >

2019-12-04 17:04:48

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH 0/7] crypto: more self-test improvements

On Wed, Dec 04, 2019 at 02:42:58PM +0000, Ard Biesheuvel wrote:
> On Tue, 3 Dec 2019 at 12:39, Ard Biesheuvel <[email protected]> wrote:
> >
> > On Sun, 1 Dec 2019 at 21:54, Eric Biggers <[email protected]> wrote:
> > >
> > > This series makes some more improvements to the crypto self-tests, the
> > > largest of which is making the AEAD fuzz tests test inauthentic inputs,
> > > i.e. cases where decryption is expected to fail due to the (ciphertext,
> > > AAD) pair not being the correct result of an encryption with the key.
> > >
> > > It also updates the self-tests to test passing misaligned buffers to the
> > > various setkey() functions, and to check that skciphers have the same
> > > min_keysize as the corresponding generic implementation.
> > >
> > > I haven't seen any test failures from this on x86_64, arm64, or arm32.
> > > But as usual I haven't tested drivers for crypto accelerators.
> > >
> > > For this series to apply this cleanly, my other series
> > > "crypto: skcipher - simplifications due to {,a}blkcipher removal"
> > > needs to be applied first, due to a conflict in skcipher.h.
> > >
> > > This can also be retrieved from git at
> > > https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git
> > > tag "crypto-self-tests_2019-12-01".
> > >
> > > Eric Biggers (7):
> > > crypto: aead - move crypto_aead_maxauthsize() to <crypto/aead.h>
> > > crypto: skcipher - add crypto_skcipher_min_keysize()
> > > crypto: testmgr - don't try to decrypt uninitialized buffers
> > > crypto: testmgr - check skcipher min_keysize
> > > crypto: testmgr - test setting misaligned keys
> > > crypto: testmgr - create struct aead_extra_tests_ctx
> > > crypto: testmgr - generate inauthentic AEAD test vectors
> > >
> >
> > I've dropped this into kernelci again, let's see if anything turns out
> > to be broken.
> >
> > For this series,
> >
> > Acked-by: Ard Biesheuvel <[email protected]>
> >
>
> Results here:
> https://kernelci.org/boot/all/job/ardb/branch/for-kernelci/kernel/v5.4-9340-g16839329da69/
>
> Only the usual suspects failed (rk3288)
>

Great, thanks. I wouldn't be surprised if all AEAD implementations are
correctly rejecting inauthentic inputs at the moment, but we should still have
the test just in case.

- Eric

2019-12-11 09:44:21

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH 0/7] crypto: more self-test improvements

Eric Biggers <[email protected]> wrote:
> This series makes some more improvements to the crypto self-tests, the
> largest of which is making the AEAD fuzz tests test inauthentic inputs,
> i.e. cases where decryption is expected to fail due to the (ciphertext,
> AAD) pair not being the correct result of an encryption with the key.
>
> It also updates the self-tests to test passing misaligned buffers to the
> various setkey() functions, and to check that skciphers have the same
> min_keysize as the corresponding generic implementation.
>
> I haven't seen any test failures from this on x86_64, arm64, or arm32.
> But as usual I haven't tested drivers for crypto accelerators.
>
> For this series to apply this cleanly, my other series
> "crypto: skcipher - simplifications due to {,a}blkcipher removal"
> needs to be applied first, due to a conflict in skcipher.h.
>
> This can also be retrieved from git at
> https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git
> tag "crypto-self-tests_2019-12-01".
>
> Eric Biggers (7):
> crypto: aead - move crypto_aead_maxauthsize() to <crypto/aead.h>
> crypto: skcipher - add crypto_skcipher_min_keysize()
> crypto: testmgr - don't try to decrypt uninitialized buffers
> crypto: testmgr - check skcipher min_keysize
> crypto: testmgr - test setting misaligned keys
> crypto: testmgr - create struct aead_extra_tests_ctx
> crypto: testmgr - generate inauthentic AEAD test vectors
>
> crypto/testmgr.c | 574 +++++++++++++++++++++++++--------
> crypto/testmgr.h | 14 +-
> include/crypto/aead.h | 10 +
> include/crypto/internal/aead.h | 10 -
> include/crypto/skcipher.h | 6 +
> 5 files changed, 461 insertions(+), 153 deletions(-)

All applied. Thanks.
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt