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, ...@@ -971,11 +971,18 @@ static int test_hash_vec_cfg(const char *driver,
if (vec->ksize) { if (vec->ksize) {
err = crypto_ahash_setkey(tfm, vec->key, vec->ksize); err = crypto_ahash_setkey(tfm, vec->key, vec->ksize);
if (err) { if (err) {
pr_err("alg: hash: %s setkey failed with err %d on test vector %u; flags=%#x\n", if (err == vec->setkey_error)
driver, err, vec_num, 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)); crypto_ahash_get_flags(tfm));
return err; 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 */ /* Build the scatterlist for the source data */
...@@ -995,17 +1002,26 @@ static int test_hash_vec_cfg(const char *driver, ...@@ -995,17 +1002,26 @@ static int test_hash_vec_cfg(const char *driver,
testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm)); testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
testmgr_poison(result, digestsize + TESTMGR_POISON_LEN); 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() */ /* Just using digest() */
ahash_request_set_callback(req, req_flags, crypto_req_done, ahash_request_set_callback(req, req_flags, crypto_req_done,
&wait); &wait);
ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize); ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize);
err = do_ahash_op(crypto_ahash_digest, req, &wait, cfg->nosimd); err = do_ahash_op(crypto_ahash_digest, req, &wait, cfg->nosimd);
if (err) { if (err) {
pr_err("alg: hash: %s digest() failed with err %d on test vector %u, cfg=\"%s\"\n", if (err == vec->digest_error)
driver, err, vec_num, cfg->name); 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; 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; goto result_ready;
} }
...@@ -1262,6 +1278,7 @@ static int test_aead_vec_cfg(const char *driver, int enc, ...@@ -1262,6 +1278,7 @@ static int test_aead_vec_cfg(const char *driver, int enc,
cfg->iv_offset + cfg->iv_offset +
(cfg->iv_offset_relative_to_alignmask ? alignmask : 0); (cfg->iv_offset_relative_to_alignmask ? alignmask : 0);
struct kvec input[2]; struct kvec input[2];
int expected_error;
int err; int err;
/* Set the key */ /* Set the key */
...@@ -1270,26 +1287,33 @@ static int test_aead_vec_cfg(const char *driver, int enc, ...@@ -1270,26 +1287,33 @@ static int test_aead_vec_cfg(const char *driver, int enc,
else else
crypto_aead_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); crypto_aead_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
err = crypto_aead_setkey(tfm, vec->key, vec->klen); err = crypto_aead_setkey(tfm, vec->key, vec->klen);
if (err) { if (err && err != vec->setkey_error) {
if (vec->fail) /* expectedly failed to set key? */ pr_err("alg: aead: %s setkey failed on test vector %u; expected_error=%d, actual_error=%d, flags=%#x\n",
return 0; driver, vec_num, vec->setkey_error, err,
pr_err("alg: aead: %s setkey failed with err %d on test vector %u; flags=%#x\n", crypto_aead_get_flags(tfm));
driver, err, vec_num, crypto_aead_get_flags(tfm));
return err; return err;
} }
if (vec->fail) { if (!err && vec->setkey_error) {
pr_err("alg: aead: %s setkey unexpectedly succeeded on test vector %u\n", pr_err("alg: aead: %s setkey unexpectedly succeeded on test vector %u; expected_error=%d\n",
driver, vec_num); driver, vec_num, vec->setkey_error);
return -EINVAL; return -EINVAL;
} }
/* Set the authentication tag size */ /* Set the authentication tag size */
err = crypto_aead_setauthsize(tfm, authsize); err = crypto_aead_setauthsize(tfm, authsize);
if (err) { if (err && err != vec->setauthsize_error) {
pr_err("alg: aead: %s setauthsize failed with err %d on test vector %u\n", pr_err("alg: aead: %s setauthsize failed on test vector %u; expected_error=%d, actual_error=%d\n",
driver, err, vec_num); driver, vec_num, vec->setauthsize_error, err);
return 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 */ /* The IV must be copied to a buffer, as the algorithm may modify it */
if (WARN_ON(ivsize > MAX_IVLEN)) if (WARN_ON(ivsize > MAX_IVLEN))
...@@ -1328,18 +1352,6 @@ static int test_aead_vec_cfg(const char *driver, int enc, ...@@ -1328,18 +1352,6 @@ static int test_aead_vec_cfg(const char *driver, int enc,
if (cfg->nosimd) if (cfg->nosimd)
crypto_reenable_simd_for_test(); crypto_reenable_simd_for_test();
err = crypto_wait_req(err, &wait); 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 */ /* Check that the algorithm didn't overwrite things it shouldn't have */
if (req->cryptlen != (enc ? vec->plen : vec->clen) || if (req->cryptlen != (enc ? vec->plen : vec->clen) ||
...@@ -1385,6 +1397,21 @@ static int test_aead_vec_cfg(const char *driver, int enc, ...@@ -1385,6 +1397,21 @@ static int test_aead_vec_cfg(const char *driver, int enc,
return -EINVAL; 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) */ /* Check for the correct output (ciphertext or plaintext) */
err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext, err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext,
enc ? vec->clen : vec->plen, enc ? vec->clen : vec->plen,
...@@ -1550,13 +1577,20 @@ static int test_cipher(struct crypto_cipher *tfm, int enc, ...@@ -1550,13 +1577,20 @@ static int test_cipher(struct crypto_cipher *tfm, int enc,
ret = crypto_cipher_setkey(tfm, template[i].key, ret = crypto_cipher_setkey(tfm, template[i].key,
template[i].klen); template[i].klen);
if (template[i].fail == !ret) { if (ret) {
printk(KERN_ERR "alg: cipher: setkey failed " if (ret == template[i].setkey_error)
"on test %d for %s: flags=%x\n", j, continue;
algo, crypto_cipher_get_flags(tfm)); 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; goto out;
} else if (ret) }
continue; 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; for (k = 0; k < template[i].len;
k += crypto_cipher_blocksize(tfm)) { k += crypto_cipher_blocksize(tfm)) {
...@@ -1614,15 +1648,16 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, ...@@ -1614,15 +1648,16 @@ static int test_skcipher_vec_cfg(const char *driver, int enc,
CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
err = crypto_skcipher_setkey(tfm, vec->key, vec->klen); err = crypto_skcipher_setkey(tfm, vec->key, vec->klen);
if (err) { if (err) {
if (vec->fail) /* expectedly failed to set key? */ if (err == vec->setkey_error)
return 0; return 0;
pr_err("alg: skcipher: %s setkey failed with err %d on test vector %u; flags=%#x\n", pr_err("alg: skcipher: %s setkey failed on test vector %u; expected_error=%d, actual_error=%d, flags=%#x\n",
driver, err, vec_num, crypto_skcipher_get_flags(tfm)); driver, vec_num, vec->setkey_error, err,
crypto_skcipher_get_flags(tfm));
return err; return err;
} }
if (vec->fail) { if (vec->setkey_error) {
pr_err("alg: skcipher: %s setkey unexpectedly succeeded on test vector %u\n", pr_err("alg: skcipher: %s setkey unexpectedly succeeded on test vector %u; expected_error=%d\n",
driver, vec_num); driver, vec_num, vec->setkey_error);
return -EINVAL; return -EINVAL;
} }
...@@ -1667,11 +1702,6 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, ...@@ -1667,11 +1702,6 @@ static int test_skcipher_vec_cfg(const char *driver, int enc,
if (cfg->nosimd) if (cfg->nosimd)
crypto_reenable_simd_for_test(); crypto_reenable_simd_for_test();
err = crypto_wait_req(err, &wait); 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 */ /* Check that the algorithm didn't overwrite things it shouldn't have */
if (req->cryptlen != vec->len || if (req->cryptlen != vec->len ||
...@@ -1714,6 +1744,20 @@ static int test_skcipher_vec_cfg(const char *driver, int enc, ...@@ -1714,6 +1744,20 @@ static int test_skcipher_vec_cfg(const char *driver, int enc,
return -EINVAL; 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) */ /* Check for the correct output (ciphertext or plaintext) */
err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext, err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext,
vec->len, 0, true); vec->len, 0, true);
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
* @digest: Pointer to expected digest * @digest: Pointer to expected digest
* @psize: Length of source data in bytes * @psize: Length of source data in bytes
* @ksize: Length of @key in bytes (0 if no key) * @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 { struct hash_testvec {
const char *key; const char *key;
...@@ -43,6 +45,8 @@ struct hash_testvec { ...@@ -43,6 +45,8 @@ struct hash_testvec {
const char *digest; const char *digest;
unsigned short psize; unsigned short psize;
unsigned short ksize; unsigned short ksize;
int setkey_error;
int digest_error;
}; };
/* /*
...@@ -54,12 +58,13 @@ struct hash_testvec { ...@@ -54,12 +58,13 @@ struct hash_testvec {
* @ptext: Pointer to plaintext * @ptext: Pointer to plaintext
* @ctext: Pointer to ciphertext * @ctext: Pointer to ciphertext
* @len: Length of @ptext and @ctext in bytes * @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? * @wk: Does the test need CRYPTO_TFM_REQ_FORBID_WEAK_KEYS?
* ( e.g. test needs to fail due to a weak key ) * ( e.g. test needs to fail due to a weak key )
* @fips_skip: Skip the test vector in FIPS mode * @fips_skip: Skip the test vector in FIPS mode
* @generates_iv: Encryption should ignore the given IV, and output @iv_out. * @generates_iv: Encryption should ignore the given IV, and output @iv_out.
* Decryption takes @iv_out. Needed for AES Keywrap ("kw(aes)"). * 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 { struct cipher_testvec {
const char *key; const char *key;
...@@ -67,12 +72,13 @@ struct cipher_testvec { ...@@ -67,12 +72,13 @@ struct cipher_testvec {
const char *iv_out; const char *iv_out;
const char *ptext; const char *ptext;
const char *ctext; const char *ctext;
bool fail;
unsigned char wk; /* weak key flag */ unsigned char wk; /* weak key flag */
unsigned char klen; unsigned char klen;
unsigned short len; unsigned short len;
bool fips_skip; bool fips_skip;
bool generates_iv; bool generates_iv;
int setkey_error;
int crypt_error;
}; };
/* /*
...@@ -84,7 +90,6 @@ struct cipher_testvec { ...@@ -84,7 +90,6 @@ struct cipher_testvec {
* @ctext: Pointer to the full authenticated ciphertext. For AEADs that * @ctext: Pointer to the full authenticated ciphertext. For AEADs that
* produce a separate "ciphertext" and "authentication tag", these * produce a separate "ciphertext" and "authentication tag", these
* two parts are concatenated: ciphertext || tag. * two parts are concatenated: ciphertext || tag.
* @fail: setkey() failure expected?
* @novrfy: Decryption verification failure expected? * @novrfy: Decryption verification failure expected?
* @wk: Does the test need CRYPTO_TFM_REQ_FORBID_WEAK_KEYS? * @wk: Does the test need CRYPTO_TFM_REQ_FORBID_WEAK_KEYS?
* (e.g. setkey() needs to fail due to a weak key) * (e.g. setkey() needs to fail due to a weak key)
...@@ -92,6 +97,9 @@ struct cipher_testvec { ...@@ -92,6 +97,9 @@ struct cipher_testvec {
* @plen: Length of @ptext in bytes * @plen: Length of @ptext in bytes
* @alen: Length of @assoc in bytes * @alen: Length of @assoc in bytes
* @clen: Length of @ctext 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 { struct aead_testvec {
const char *key; const char *key;
...@@ -99,13 +107,15 @@ struct aead_testvec { ...@@ -99,13 +107,15 @@ struct aead_testvec {
const char *ptext; const char *ptext;
const char *assoc; const char *assoc;
const char *ctext; const char *ctext;
bool fail;
unsigned char novrfy; unsigned char novrfy;
unsigned char wk; unsigned char wk;
unsigned char klen; unsigned char klen;
unsigned short plen; unsigned short plen;
unsigned short clen; unsigned short clen;
unsigned short alen; unsigned short alen;
int setkey_error;
int setauthsize_error;
int crypt_error;
}; };
struct cprng_testvec { struct cprng_testvec {
...@@ -7201,7 +7211,7 @@ static const struct cipher_testvec des_tv_template[] = { ...@@ -7201,7 +7211,7 @@ static const struct cipher_testvec des_tv_template[] = {
"\xb4\x99\x26\xf7\x1f\xe1\xd4\x90", "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90",
.len = 24, .len = 24,
}, { /* Weak key */ }, { /* Weak key */
.fail = true, .setkey_error = -EINVAL,
.wk = 1, .wk = 1,
.key = "\x01\x01\x01\x01\x01\x01\x01\x01", .key = "\x01\x01\x01\x01\x01\x01\x01\x01",
.klen = 8, .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