Commit 5283a8ee authored by Eric Biggers's avatar Eric Biggers Committed by Herbert Xu

crypto: testmgr - expand ability to test for errors

Update testmgr to support testing for specific errors from setkey() and
digest() for hashes; setkey() and encrypt()/decrypt() for skciphers and
ciphers; and setkey(), setauthsize(), and encrypt()/decrypt() for AEADs.
This is useful because algorithms usually restrict the lengths or format
of the message, key, and/or authentication tag in some way.  And bad
inputs should be tested too, not just good inputs.

As part of this change, remove the ambiguously-named 'fail' flag and
replace it with 'setkey_error = -EINVAL' for the only test vector that
used it -- the DES weak key test vector.  Note that this tightens the
test to require -EINVAL rather than any error code, but AFAICS this
won't cause any test failure.

Other than that, these new fields aren't set on any test vectors yet.
Later patches will do so.
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent be08f0c6
......@@ -971,11 +971,18 @@ static int test_hash_vec_cfg(const char *driver,
if (vec->ksize) {
err = crypto_ahash_setkey(tfm, vec->key, vec->ksize);
if (err) {
pr_err("alg: hash: %s setkey failed with err %d on test vector %u; flags=%#x\n",
driver, err, vec_num,
if (err == vec->setkey_error)
return 0;
pr_err("alg: hash: %s setkey failed on test vector %u; expected_error=%d, actual_error=%d, flags=%#x\n",
driver, vec_num, vec->setkey_error, err,
crypto_ahash_get_flags(tfm));
return err;
}
if (vec->setkey_error) {
pr_err("alg: hash: %s setkey unexpectedly succeeded on test vector %u; expected_error=%d\n",
driver, vec_num, vec->setkey_error);
return -EINVAL;
}
}
/* Build the scatterlist for the source data */
......@@ -995,17 +1002,26 @@ static int test_hash_vec_cfg(const char *driver,
testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
testmgr_poison(result, digestsize + TESTMGR_POISON_LEN);
if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST) {
if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST ||
vec->digest_error) {
/* Just using digest() */
ahash_request_set_callback(req, req_flags, crypto_req_done,
&wait);
ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize);
err = do_ahash_op(crypto_ahash_digest, req, &wait, cfg->nosimd);
if (err) {
pr_err("alg: hash: %s digest() failed with err %d on test vector %u, cfg=\"%s\"\n",
driver, err, vec_num, cfg->name);
if (err == vec->digest_error)
return 0;
pr_err("alg: hash: %s digest() failed on test vector %u; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
driver, vec_num, vec->digest_error, err,
cfg->name);
return err;
}
if (vec->digest_error) {
pr_err("alg: hash: %s digest() unexpectedly succeeded on test vector %u; expected_error=%d, cfg=\"%s\"\n",
driver, vec_num, vec->digest_error, cfg->name);
return -EINVAL;
}
goto result_ready;
}
......@@ -1262,6 +1278,7 @@ 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 */
......@@ -1270,26 +1287,33 @@ static int test_aead_vec_cfg(const char *driver, int enc,
else
crypto_aead_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
err = crypto_aead_setkey(tfm, vec->key, vec->klen);
if (err) {
if (vec->fail) /* expectedly failed to set key? */
return 0;
pr_err("alg: aead: %s setkey failed with err %d on test vector %u; flags=%#x\n",
driver, err, vec_num, crypto_aead_get_flags(tfm));
if (err && err != vec->setkey_error) {
pr_err("alg: aead: %s setkey failed on test vector %u; expected_error=%d, actual_error=%d, flags=%#x\n",
driver, vec_num, vec->setkey_error, err,
crypto_aead_get_flags(tfm));
return err;
}
if (vec->fail) {
pr_err("alg: aead: %s setkey unexpectedly succeeded on test vector %u\n",
driver, vec_num);
if (!err && vec->setkey_error) {
pr_err("alg: aead: %s setkey unexpectedly succeeded on test vector %u; expected_error=%d\n",
driver, vec_num, vec->setkey_error);
return -EINVAL;
}
/* Set the authentication tag size */
err = crypto_aead_setauthsize(tfm, authsize);
if (err) {
pr_err("alg: aead: %s setauthsize failed with err %d on test vector %u\n",
driver, err, vec_num);
if (err && err != vec->setauthsize_error) {
pr_err("alg: aead: %s setauthsize failed on test vector %u; expected_error=%d, actual_error=%d\n",
driver, vec_num, vec->setauthsize_error, err);
return err;
}
if (!err && vec->setauthsize_error) {
pr_err("alg: aead: %s setauthsize unexpectedly succeeded on test vector %u; expected_error=%d\n",
driver, vec_num, vec->setauthsize_error);
return -EINVAL;
}
if (vec->setkey_error || vec->setauthsize_error)
return 0;
/* The IV must be copied to a buffer, as the algorithm may modify it */
if (WARN_ON(ivsize > MAX_IVLEN))
......@@ -1328,18 +1352,6 @@ static int test_aead_vec_cfg(const char *driver, int enc,
if (cfg->nosimd)
crypto_reenable_simd_for_test();
err = crypto_wait_req(err, &wait);
if (err) {
if (err == -EBADMSG && vec->novrfy)
return 0;
pr_err("alg: aead: %s %s failed with err %d on test vector %u, cfg=\"%s\"\n",
driver, op, err, vec_num, cfg->name);
return err;
}
if (vec->novrfy) {
pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %u, cfg=\"%s\"\n",
driver, op, vec_num, cfg->name);
return -EINVAL;
}
/* Check that the algorithm didn't overwrite things it shouldn't have */
if (req->cryptlen != (enc ? vec->plen : vec->clen) ||
......@@ -1385,6 +1397,21 @@ 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 %u; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
driver, op, vec_num, expected_error, err, cfg->name);
return err;
}
if (expected_error) {
pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %u; expected_error=%d, cfg=\"%s\"\n",
driver, op, vec_num, expected_error, cfg->name);
return -EINVAL;
}
/* Check for the correct output (ciphertext or plaintext) */
err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext,
enc ? vec->clen : vec->plen,
......@@ -1550,13 +1577,20 @@ static int test_cipher(struct crypto_cipher *tfm, int enc,
ret = crypto_cipher_setkey(tfm, template[i].key,
template[i].klen);
if (template[i].fail == !ret) {
printk(KERN_ERR "alg: cipher: setkey failed "
"on test %d for %s: flags=%x\n", j,
algo, crypto_cipher_get_flags(tfm));
goto out;
} else if (ret)
if (ret) {
if (ret == template[i].setkey_error)
continue;
pr_err("alg: cipher: %s setkey failed on test vector %u; expected_error=%d, actual_error=%d, flags=%#x\n",
algo, j, template[i].setkey_error, ret,
crypto_cipher_get_flags(tfm));
goto out;
}
if (template[i].setkey_error) {
pr_err("alg: cipher: %s setkey unexpectedly succeeded on test vector %u; expected_error=%d\n",
algo, j, template[i].setkey_error);
ret = -EINVAL;
goto out;
}
for (k = 0; k < template[i].len;
k += crypto_cipher_blocksize(tfm)) {
......@@ -1614,15 +1648,16 @@ static int test_skcipher_vec_cfg(const char *driver, int enc,
CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
err = crypto_skcipher_setkey(tfm, vec->key, vec->klen);
if (err) {
if (vec->fail) /* expectedly failed to set key? */
if (err == vec->setkey_error)
return 0;
pr_err("alg: skcipher: %s setkey failed with err %d on test vector %u; flags=%#x\n",
driver, err, vec_num, crypto_skcipher_get_flags(tfm));
pr_err("alg: skcipher: %s setkey failed on test vector %u; expected_error=%d, actual_error=%d, flags=%#x\n",
driver, vec_num, vec->setkey_error, err,
crypto_skcipher_get_flags(tfm));
return err;
}
if (vec->fail) {
pr_err("alg: skcipher: %s setkey unexpectedly succeeded on test vector %u\n",
driver, vec_num);
if (vec->setkey_error) {
pr_err("alg: skcipher: %s setkey unexpectedly succeeded on test vector %u; expected_error=%d\n",
driver, vec_num, vec->setkey_error);
return -EINVAL;
}
......@@ -1667,11 +1702,6 @@ static int test_skcipher_vec_cfg(const char *driver, int enc,
if (cfg->nosimd)
crypto_reenable_simd_for_test();
err = crypto_wait_req(err, &wait);
if (err) {
pr_err("alg: skcipher: %s %s failed with err %d on test vector %u, cfg=\"%s\"\n",
driver, op, err, vec_num, cfg->name);
return err;
}
/* Check that the algorithm didn't overwrite things it shouldn't have */
if (req->cryptlen != vec->len ||
......@@ -1714,6 +1744,20 @@ static int test_skcipher_vec_cfg(const char *driver, int enc,
return -EINVAL;
}
/* Check for success or failure */
if (err) {
if (err == vec->crypt_error)
return 0;
pr_err("alg: skcipher: %s %s failed on test vector %u; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
driver, op, vec_num, vec->crypt_error, err, cfg->name);
return err;
}
if (vec->crypt_error) {
pr_err("alg: skcipher: %s %s unexpectedly succeeded on test vector %u; expected_error=%d, cfg=\"%s\"\n",
driver, op, vec_num, vec->crypt_error, cfg->name);
return -EINVAL;
}
/* Check for the correct output (ciphertext or plaintext) */
err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext,
vec->len, 0, true);
......
......@@ -36,6 +36,8 @@
* @digest: Pointer to expected digest
* @psize: Length of source data in bytes
* @ksize: Length of @key in bytes (0 if no key)
* @setkey_error: Expected error from setkey()
* @digest_error: Expected error from digest()
*/
struct hash_testvec {
const char *key;
......@@ -43,6 +45,8 @@ struct hash_testvec {
const char *digest;
unsigned short psize;
unsigned short ksize;
int setkey_error;
int digest_error;
};
/*
......@@ -54,12 +58,13 @@ struct hash_testvec {
* @ptext: Pointer to plaintext
* @ctext: Pointer to ciphertext
* @len: Length of @ptext and @ctext in bytes
* @fail: If set to one, the test need to fail
* @wk: Does the test need CRYPTO_TFM_REQ_FORBID_WEAK_KEYS?
* ( e.g. test needs to fail due to a weak key )
* @fips_skip: Skip the test vector in FIPS mode
* @generates_iv: Encryption should ignore the given IV, and output @iv_out.
* Decryption takes @iv_out. Needed for AES Keywrap ("kw(aes)").
* @setkey_error: Expected error from setkey()
* @crypt_error: Expected error from encrypt() and decrypt()
*/
struct cipher_testvec {
const char *key;
......@@ -67,12 +72,13 @@ struct cipher_testvec {
const char *iv_out;
const char *ptext;
const char *ctext;
bool fail;
unsigned char wk; /* weak key flag */
unsigned char klen;
unsigned short len;
bool fips_skip;
bool generates_iv;
int setkey_error;
int crypt_error;
};
/*
......@@ -84,7 +90,6 @@ 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.
* @fail: setkey() failure expected?
* @novrfy: Decryption verification failure expected?
* @wk: Does the test need CRYPTO_TFM_REQ_FORBID_WEAK_KEYS?
* (e.g. setkey() needs to fail due to a weak key)
......@@ -92,6 +97,9 @@ struct cipher_testvec {
* @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()
*/
struct aead_testvec {
const char *key;
......@@ -99,13 +107,15 @@ struct aead_testvec {
const char *ptext;
const char *assoc;
const char *ctext;
bool fail;
unsigned char novrfy;
unsigned char wk;
unsigned char klen;
unsigned short plen;
unsigned short clen;
unsigned short alen;
int setkey_error;
int setauthsize_error;
int crypt_error;
};
struct cprng_testvec {
......@@ -7201,7 +7211,7 @@ static const struct cipher_testvec des_tv_template[] = {
"\xb4\x99\x26\xf7\x1f\xe1\xd4\x90",
.len = 24,
}, { /* Weak key */
.fail = true,
.setkey_error = -EINVAL,
.wk = 1,
.key = "\x01\x01\x01\x01\x01\x01\x01\x01",
.klen = 8,
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment