Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto updates from Herbert Xu: "Here is the crypto update for 5.3: API: - Test shash interface directly in testmgr - cra_driver_name is now mandatory Algorithms: - Replace arc4 crypto_cipher with library helper - Implement 5 way interleave for ECB, CBC and CTR on arm64 - Add xxhash - Add continuous self-test on noise source to drbg - Update jitter RNG Drivers: - Add support for SHA204A random number generator - Add support for 7211 in iproc-rng200 - Fix fuzz test failures in inside-secure - Fix fuzz test failures in talitos - Fix fuzz test failures in qat" * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (143 commits) crypto: stm32/hash - remove interruptible condition for dma crypto: stm32/hash - Fix hmac issue more than 256 bytes crypto: stm32/crc32 - rename driver file crypto: amcc - remove memset after dma_alloc_coherent crypto: ccp - Switch to SPDX license identifiers crypto: ccp - Validate the the error value used to index error messages crypto: doc - Fix formatting of new crypto engine content crypto: doc - Add parameter documentation crypto: arm64/aes-ce - implement 5 way interleave for ECB, CBC and CTR crypto: arm64/aes-ce - add 5 way interleave routines crypto: talitos - drop icv_ool crypto: talitos - fix hash on SEC1. crypto: talitos - move struct talitos_edesc into talitos.h lib/scatterlist: Fix mapping iterator when sg->offset is greater than PAGE_SIZE crypto/NX: Set receive window credits to max number of CRBs in RxFIFO crypto: asymmetric_keys - select CRYPTO_HASH where needed crypto: serpent - mark __serpent_setkey_sbox noinline crypto: testmgr - dynamically allocate crypto_shash crypto: testmgr - dynamically allocate testvec_config crypto: talitos - eliminate unneeded 'done' functions at build time ...
This commit is contained in:
478
crypto/testmgr.c
478
crypto/testmgr.c
@@ -1032,6 +1032,205 @@ static void crypto_reenable_simd_for_test(void)
|
||||
}
|
||||
#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
|
||||
|
||||
static int build_hash_sglist(struct test_sglist *tsgl,
|
||||
const struct hash_testvec *vec,
|
||||
const struct testvec_config *cfg,
|
||||
unsigned int alignmask,
|
||||
const struct test_sg_division *divs[XBUFSIZE])
|
||||
{
|
||||
struct kvec kv;
|
||||
struct iov_iter input;
|
||||
|
||||
kv.iov_base = (void *)vec->plaintext;
|
||||
kv.iov_len = vec->psize;
|
||||
iov_iter_kvec(&input, WRITE, &kv, 1, vec->psize);
|
||||
return build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize,
|
||||
&input, divs);
|
||||
}
|
||||
|
||||
static int check_hash_result(const char *type,
|
||||
const u8 *result, unsigned int digestsize,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const char *driver,
|
||||
const struct testvec_config *cfg)
|
||||
{
|
||||
if (memcmp(result, vec->digest, digestsize) != 0) {
|
||||
pr_err("alg: %s: %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
|
||||
type, driver, vec_name, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) {
|
||||
pr_err("alg: %s: %s overran result buffer on test vector %s, cfg=\"%s\"\n",
|
||||
type, driver, vec_name, cfg->name);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int check_shash_op(const char *op, int err,
|
||||
const char *driver, const char *vec_name,
|
||||
const struct testvec_config *cfg)
|
||||
{
|
||||
if (err)
|
||||
pr_err("alg: shash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
driver, op, err, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline const void *sg_data(struct scatterlist *sg)
|
||||
{
|
||||
return page_address(sg_page(sg)) + sg->offset;
|
||||
}
|
||||
|
||||
/* Test one hash test vector in one configuration, using the shash API */
|
||||
static int test_shash_vec_cfg(const char *driver,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const struct testvec_config *cfg,
|
||||
struct shash_desc *desc,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
struct crypto_shash *tfm = desc->tfm;
|
||||
const unsigned int alignmask = crypto_shash_alignmask(tfm);
|
||||
const unsigned int digestsize = crypto_shash_digestsize(tfm);
|
||||
const unsigned int statesize = crypto_shash_statesize(tfm);
|
||||
const struct test_sg_division *divs[XBUFSIZE];
|
||||
unsigned int i;
|
||||
u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN];
|
||||
int err;
|
||||
|
||||
/* Set the key, if specified */
|
||||
if (vec->ksize) {
|
||||
err = crypto_shash_setkey(tfm, vec->key, vec->ksize);
|
||||
if (err) {
|
||||
if (err == vec->setkey_error)
|
||||
return 0;
|
||||
pr_err("alg: shash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
|
||||
driver, vec_name, vec->setkey_error, err,
|
||||
crypto_shash_get_flags(tfm));
|
||||
return err;
|
||||
}
|
||||
if (vec->setkey_error) {
|
||||
pr_err("alg: shash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
|
||||
driver, vec_name, vec->setkey_error);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the scatterlist for the source data */
|
||||
err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
|
||||
if (err) {
|
||||
pr_err("alg: shash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Do the actual hashing */
|
||||
|
||||
testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm));
|
||||
testmgr_poison(result, digestsize + TESTMGR_POISON_LEN);
|
||||
|
||||
if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST ||
|
||||
vec->digest_error) {
|
||||
/* Just using digest() */
|
||||
if (tsgl->nents != 1)
|
||||
return 0;
|
||||
if (cfg->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_digest(desc, sg_data(&tsgl->sgl[0]),
|
||||
tsgl->sgl[0].length, result);
|
||||
if (cfg->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
if (err) {
|
||||
if (err == vec->digest_error)
|
||||
return 0;
|
||||
pr_err("alg: shash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
|
||||
driver, vec_name, vec->digest_error, err,
|
||||
cfg->name);
|
||||
return err;
|
||||
}
|
||||
if (vec->digest_error) {
|
||||
pr_err("alg: shash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
|
||||
driver, vec_name, vec->digest_error, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
goto result_ready;
|
||||
}
|
||||
|
||||
/* Using init(), zero or more update(), then final() or finup() */
|
||||
|
||||
if (cfg->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_init(desc);
|
||||
if (cfg->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
err = check_shash_op("init", err, driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < tsgl->nents; i++) {
|
||||
if (i + 1 == tsgl->nents &&
|
||||
cfg->finalization_type == FINALIZATION_TYPE_FINUP) {
|
||||
if (divs[i]->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_finup(desc, sg_data(&tsgl->sgl[i]),
|
||||
tsgl->sgl[i].length, result);
|
||||
if (divs[i]->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
err = check_shash_op("finup", err, driver, vec_name,
|
||||
cfg);
|
||||
if (err)
|
||||
return err;
|
||||
goto result_ready;
|
||||
}
|
||||
if (divs[i]->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_update(desc, sg_data(&tsgl->sgl[i]),
|
||||
tsgl->sgl[i].length);
|
||||
if (divs[i]->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
err = check_shash_op("update", err, driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
if (divs[i]->flush_type == FLUSH_TYPE_REIMPORT) {
|
||||
/* Test ->export() and ->import() */
|
||||
testmgr_poison(hashstate + statesize,
|
||||
TESTMGR_POISON_LEN);
|
||||
err = crypto_shash_export(desc, hashstate);
|
||||
err = check_shash_op("export", err, driver, vec_name,
|
||||
cfg);
|
||||
if (err)
|
||||
return err;
|
||||
if (!testmgr_is_poison(hashstate + statesize,
|
||||
TESTMGR_POISON_LEN)) {
|
||||
pr_err("alg: shash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm));
|
||||
err = crypto_shash_import(desc, hashstate);
|
||||
err = check_shash_op("import", err, driver, vec_name,
|
||||
cfg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg->nosimd)
|
||||
crypto_disable_simd_for_test();
|
||||
err = crypto_shash_final(desc, result);
|
||||
if (cfg->nosimd)
|
||||
crypto_reenable_simd_for_test();
|
||||
err = check_shash_op("final", err, driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
result_ready:
|
||||
return check_hash_result("shash", result, digestsize, vec, vec_name,
|
||||
driver, cfg);
|
||||
}
|
||||
|
||||
static int do_ahash_op(int (*op)(struct ahash_request *req),
|
||||
struct ahash_request *req,
|
||||
struct crypto_wait *wait, bool nosimd)
|
||||
@@ -1049,31 +1248,32 @@ static int do_ahash_op(int (*op)(struct ahash_request *req),
|
||||
return crypto_wait_req(err, wait);
|
||||
}
|
||||
|
||||
static int check_nonfinal_hash_op(const char *op, int err,
|
||||
u8 *result, unsigned int digestsize,
|
||||
const char *driver, const char *vec_name,
|
||||
const struct testvec_config *cfg)
|
||||
static int check_nonfinal_ahash_op(const char *op, int err,
|
||||
u8 *result, unsigned int digestsize,
|
||||
const char *driver, const char *vec_name,
|
||||
const struct testvec_config *cfg)
|
||||
{
|
||||
if (err) {
|
||||
pr_err("alg: hash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
driver, op, err, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
if (!testmgr_is_poison(result, digestsize)) {
|
||||
pr_err("alg: hash: %s %s() used result buffer on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s %s() used result buffer on test vector %s, cfg=\"%s\"\n",
|
||||
driver, op, vec_name, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_hash_vec_cfg(const char *driver,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const struct testvec_config *cfg,
|
||||
struct ahash_request *req,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
/* Test one hash test vector in one configuration, using the ahash API */
|
||||
static int test_ahash_vec_cfg(const char *driver,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const struct testvec_config *cfg,
|
||||
struct ahash_request *req,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
||||
const unsigned int alignmask = crypto_ahash_alignmask(tfm);
|
||||
@@ -1082,8 +1282,6 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags;
|
||||
const struct test_sg_division *divs[XBUFSIZE];
|
||||
DECLARE_CRYPTO_WAIT(wait);
|
||||
struct kvec _input;
|
||||
struct iov_iter input;
|
||||
unsigned int i;
|
||||
struct scatterlist *pending_sgl;
|
||||
unsigned int pending_len;
|
||||
@@ -1096,26 +1294,22 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
if (err) {
|
||||
if (err == vec->setkey_error)
|
||||
return 0;
|
||||
pr_err("alg: hash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
|
||||
pr_err("alg: ahash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
|
||||
driver, vec_name, 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 %s; expected_error=%d\n",
|
||||
pr_err("alg: ahash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
|
||||
driver, vec_name, vec->setkey_error);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the scatterlist for the source data */
|
||||
_input.iov_base = (void *)vec->plaintext;
|
||||
_input.iov_len = vec->psize;
|
||||
iov_iter_kvec(&input, WRITE, &_input, 1, vec->psize);
|
||||
err = build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize,
|
||||
&input, divs);
|
||||
err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
|
||||
if (err) {
|
||||
pr_err("alg: hash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
@@ -1135,13 +1329,13 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
if (err) {
|
||||
if (err == vec->digest_error)
|
||||
return 0;
|
||||
pr_err("alg: hash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
|
||||
driver, vec_name, vec->digest_error, err,
|
||||
cfg->name);
|
||||
return err;
|
||||
}
|
||||
if (vec->digest_error) {
|
||||
pr_err("alg: hash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
|
||||
driver, vec_name, vec->digest_error, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1153,8 +1347,8 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
ahash_request_set_callback(req, req_flags, crypto_req_done, &wait);
|
||||
ahash_request_set_crypt(req, NULL, result, 0);
|
||||
err = do_ahash_op(crypto_ahash_init, req, &wait, cfg->nosimd);
|
||||
err = check_nonfinal_hash_op("init", err, result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("init", err, result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1170,9 +1364,9 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
pending_len);
|
||||
err = do_ahash_op(crypto_ahash_update, req, &wait,
|
||||
divs[i]->nosimd);
|
||||
err = check_nonfinal_hash_op("update", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("update", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
pending_sgl = NULL;
|
||||
@@ -1183,23 +1377,23 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
testmgr_poison(hashstate + statesize,
|
||||
TESTMGR_POISON_LEN);
|
||||
err = crypto_ahash_export(req, hashstate);
|
||||
err = check_nonfinal_hash_op("export", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("export", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
if (!testmgr_is_poison(hashstate + statesize,
|
||||
TESTMGR_POISON_LEN)) {
|
||||
pr_err("alg: hash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
|
||||
err = crypto_ahash_import(req, hashstate);
|
||||
err = check_nonfinal_hash_op("import", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("import", err,
|
||||
result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1213,13 +1407,13 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) {
|
||||
/* finish with update() and final() */
|
||||
err = do_ahash_op(crypto_ahash_update, req, &wait, cfg->nosimd);
|
||||
err = check_nonfinal_hash_op("update", err, result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
err = check_nonfinal_ahash_op("update", err, result, digestsize,
|
||||
driver, vec_name, cfg);
|
||||
if (err)
|
||||
return err;
|
||||
err = do_ahash_op(crypto_ahash_final, req, &wait, cfg->nosimd);
|
||||
if (err) {
|
||||
pr_err("alg: hash: %s final() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s final() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
driver, err, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
@@ -1227,31 +1421,49 @@ static int test_hash_vec_cfg(const char *driver,
|
||||
/* finish with finup() */
|
||||
err = do_ahash_op(crypto_ahash_finup, req, &wait, cfg->nosimd);
|
||||
if (err) {
|
||||
pr_err("alg: hash: %s finup() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
pr_err("alg: ahash: %s finup() failed with err %d on test vector %s, cfg=\"%s\"\n",
|
||||
driver, err, vec_name, cfg->name);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
result_ready:
|
||||
/* Check that the algorithm produced the correct digest */
|
||||
if (memcmp(result, vec->digest, digestsize) != 0) {
|
||||
pr_err("alg: hash: %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) {
|
||||
pr_err("alg: hash: %s overran result buffer on test vector %s, cfg=\"%s\"\n",
|
||||
driver, vec_name, cfg->name);
|
||||
return -EOVERFLOW;
|
||||
return check_hash_result("ahash", result, digestsize, vec, vec_name,
|
||||
driver, cfg);
|
||||
}
|
||||
|
||||
static int test_hash_vec_cfg(const char *driver,
|
||||
const struct hash_testvec *vec,
|
||||
const char *vec_name,
|
||||
const struct testvec_config *cfg,
|
||||
struct ahash_request *req,
|
||||
struct shash_desc *desc,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
int err;
|
||||
|
||||
/*
|
||||
* For algorithms implemented as "shash", most bugs will be detected by
|
||||
* both the shash and ahash tests. Test the shash API first so that the
|
||||
* failures involve less indirection, so are easier to debug.
|
||||
*/
|
||||
|
||||
if (desc) {
|
||||
err = test_shash_vec_cfg(driver, vec, vec_name, cfg, desc, tsgl,
|
||||
hashstate);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return test_ahash_vec_cfg(driver, vec, vec_name, cfg, req, tsgl,
|
||||
hashstate);
|
||||
}
|
||||
|
||||
static int test_hash_vec(const char *driver, const struct hash_testvec *vec,
|
||||
unsigned int vec_num, struct ahash_request *req,
|
||||
struct test_sglist *tsgl, u8 *hashstate)
|
||||
struct shash_desc *desc, struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
char vec_name[16];
|
||||
unsigned int i;
|
||||
@@ -1262,7 +1474,7 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec,
|
||||
for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) {
|
||||
err = test_hash_vec_cfg(driver, vec, vec_name,
|
||||
&default_hash_testvec_configs[i],
|
||||
req, tsgl, hashstate);
|
||||
req, desc, tsgl, hashstate);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1276,9 +1488,10 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec,
|
||||
generate_random_testvec_config(&cfg, cfgname,
|
||||
sizeof(cfgname));
|
||||
err = test_hash_vec_cfg(driver, vec, vec_name, &cfg,
|
||||
req, tsgl, hashstate);
|
||||
req, desc, tsgl, hashstate);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1290,14 +1503,12 @@ static int test_hash_vec(const char *driver, const struct hash_testvec *vec,
|
||||
* Generate a hash test vector from the given implementation.
|
||||
* Assumes the buffers in 'vec' were already allocated.
|
||||
*/
|
||||
static void generate_random_hash_testvec(struct crypto_shash *tfm,
|
||||
static void generate_random_hash_testvec(struct shash_desc *desc,
|
||||
struct hash_testvec *vec,
|
||||
unsigned int maxkeysize,
|
||||
unsigned int maxdatasize,
|
||||
char *name, size_t max_namelen)
|
||||
{
|
||||
SHASH_DESC_ON_STACK(desc, tfm);
|
||||
|
||||
/* Data */
|
||||
vec->psize = generate_random_length(maxdatasize);
|
||||
generate_random_bytes((u8 *)vec->plaintext, vec->psize);
|
||||
@@ -1314,7 +1525,7 @@ static void generate_random_hash_testvec(struct crypto_shash *tfm,
|
||||
vec->ksize = 1 + (prandom_u32() % maxkeysize);
|
||||
generate_random_bytes((u8 *)vec->key, vec->ksize);
|
||||
|
||||
vec->setkey_error = crypto_shash_setkey(tfm, vec->key,
|
||||
vec->setkey_error = crypto_shash_setkey(desc->tfm, vec->key,
|
||||
vec->ksize);
|
||||
/* If the key couldn't be set, no need to continue to digest. */
|
||||
if (vec->setkey_error)
|
||||
@@ -1322,7 +1533,6 @@ static void generate_random_hash_testvec(struct crypto_shash *tfm,
|
||||
}
|
||||
|
||||
/* Digest */
|
||||
desc->tfm = tfm;
|
||||
vec->digest_error = crypto_shash_digest(desc, vec->plaintext,
|
||||
vec->psize, (u8 *)vec->digest);
|
||||
done:
|
||||
@@ -1338,6 +1548,7 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
const char *generic_driver,
|
||||
unsigned int maxkeysize,
|
||||
struct ahash_request *req,
|
||||
struct shash_desc *desc,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
@@ -1348,10 +1559,11 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
const char *algname = crypto_hash_alg_common(tfm)->base.cra_name;
|
||||
char _generic_driver[CRYPTO_MAX_ALG_NAME];
|
||||
struct crypto_shash *generic_tfm = NULL;
|
||||
struct shash_desc *generic_desc = NULL;
|
||||
unsigned int i;
|
||||
struct hash_testvec vec = { 0 };
|
||||
char vec_name[64];
|
||||
struct testvec_config cfg;
|
||||
struct testvec_config *cfg;
|
||||
char cfgname[TESTVEC_CONFIG_NAMELEN];
|
||||
int err;
|
||||
|
||||
@@ -1381,6 +1593,20 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
return err;
|
||||
}
|
||||
|
||||
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
|
||||
if (!cfg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
generic_desc = kzalloc(sizeof(*desc) +
|
||||
crypto_shash_descsize(generic_tfm), GFP_KERNEL);
|
||||
if (!generic_desc) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
generic_desc->tfm = generic_tfm;
|
||||
|
||||
/* Check the algorithm properties for consistency. */
|
||||
|
||||
if (digestsize != crypto_shash_digestsize(generic_tfm)) {
|
||||
@@ -1412,23 +1638,25 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
}
|
||||
|
||||
for (i = 0; i < fuzz_iterations * 8; i++) {
|
||||
generate_random_hash_testvec(generic_tfm, &vec,
|
||||
generate_random_hash_testvec(generic_desc, &vec,
|
||||
maxkeysize, maxdatasize,
|
||||
vec_name, sizeof(vec_name));
|
||||
generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname));
|
||||
generate_random_testvec_config(cfg, cfgname, sizeof(cfgname));
|
||||
|
||||
err = test_hash_vec_cfg(driver, &vec, vec_name, &cfg,
|
||||
req, tsgl, hashstate);
|
||||
err = test_hash_vec_cfg(driver, &vec, vec_name, cfg,
|
||||
req, desc, tsgl, hashstate);
|
||||
if (err)
|
||||
goto out;
|
||||
cond_resched();
|
||||
}
|
||||
err = 0;
|
||||
out:
|
||||
kfree(cfg);
|
||||
kfree(vec.key);
|
||||
kfree(vec.plaintext);
|
||||
kfree(vec.digest);
|
||||
crypto_free_shash(generic_tfm);
|
||||
kzfree(generic_desc);
|
||||
return err;
|
||||
}
|
||||
#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
|
||||
@@ -1436,6 +1664,7 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
const char *generic_driver,
|
||||
unsigned int maxkeysize,
|
||||
struct ahash_request *req,
|
||||
struct shash_desc *desc,
|
||||
struct test_sglist *tsgl,
|
||||
u8 *hashstate)
|
||||
{
|
||||
@@ -1443,26 +1672,67 @@ static int test_hash_vs_generic_impl(const char *driver,
|
||||
}
|
||||
#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
|
||||
|
||||
static int alloc_shash(const char *driver, u32 type, u32 mask,
|
||||
struct crypto_shash **tfm_ret,
|
||||
struct shash_desc **desc_ret)
|
||||
{
|
||||
struct crypto_shash *tfm;
|
||||
struct shash_desc *desc;
|
||||
|
||||
tfm = crypto_alloc_shash(driver, type, mask);
|
||||
if (IS_ERR(tfm)) {
|
||||
if (PTR_ERR(tfm) == -ENOENT) {
|
||||
/*
|
||||
* This algorithm is only available through the ahash
|
||||
* API, not the shash API, so skip the shash tests.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
pr_err("alg: hash: failed to allocate shash transform for %s: %ld\n",
|
||||
driver, PTR_ERR(tfm));
|
||||
return PTR_ERR(tfm);
|
||||
}
|
||||
|
||||
desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
|
||||
if (!desc) {
|
||||
crypto_free_shash(tfm);
|
||||
return -ENOMEM;
|
||||
}
|
||||
desc->tfm = tfm;
|
||||
|
||||
*tfm_ret = tfm;
|
||||
*desc_ret = desc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __alg_test_hash(const struct hash_testvec *vecs,
|
||||
unsigned int num_vecs, const char *driver,
|
||||
u32 type, u32 mask,
|
||||
const char *generic_driver, unsigned int maxkeysize)
|
||||
{
|
||||
struct crypto_ahash *tfm;
|
||||
struct crypto_ahash *atfm = NULL;
|
||||
struct ahash_request *req = NULL;
|
||||
struct crypto_shash *stfm = NULL;
|
||||
struct shash_desc *desc = NULL;
|
||||
struct test_sglist *tsgl = NULL;
|
||||
u8 *hashstate = NULL;
|
||||
unsigned int statesize;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
tfm = crypto_alloc_ahash(driver, type, mask);
|
||||
if (IS_ERR(tfm)) {
|
||||
/*
|
||||
* Always test the ahash API. This works regardless of whether the
|
||||
* algorithm is implemented as ahash or shash.
|
||||
*/
|
||||
|
||||
atfm = crypto_alloc_ahash(driver, type, mask);
|
||||
if (IS_ERR(atfm)) {
|
||||
pr_err("alg: hash: failed to allocate transform for %s: %ld\n",
|
||||
driver, PTR_ERR(tfm));
|
||||
return PTR_ERR(tfm);
|
||||
driver, PTR_ERR(atfm));
|
||||
return PTR_ERR(atfm);
|
||||
}
|
||||
|
||||
req = ahash_request_alloc(tfm, GFP_KERNEL);
|
||||
req = ahash_request_alloc(atfm, GFP_KERNEL);
|
||||
if (!req) {
|
||||
pr_err("alg: hash: failed to allocate request for %s\n",
|
||||
driver);
|
||||
@@ -1470,6 +1740,14 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If available also test the shash API, to cover corner cases that may
|
||||
* be missed by testing the ahash API only.
|
||||
*/
|
||||
err = alloc_shash(driver, type, mask, &stfm, &desc);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
tsgl = kmalloc(sizeof(*tsgl), GFP_KERNEL);
|
||||
if (!tsgl || init_test_sglist(tsgl) != 0) {
|
||||
pr_err("alg: hash: failed to allocate test buffers for %s\n",
|
||||
@@ -1480,8 +1758,10 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
|
||||
goto out;
|
||||
}
|
||||
|
||||
hashstate = kmalloc(crypto_ahash_statesize(tfm) + TESTMGR_POISON_LEN,
|
||||
GFP_KERNEL);
|
||||
statesize = crypto_ahash_statesize(atfm);
|
||||
if (stfm)
|
||||
statesize = max(statesize, crypto_shash_statesize(stfm));
|
||||
hashstate = kmalloc(statesize + TESTMGR_POISON_LEN, GFP_KERNEL);
|
||||
if (!hashstate) {
|
||||
pr_err("alg: hash: failed to allocate hash state buffer for %s\n",
|
||||
driver);
|
||||
@@ -1490,20 +1770,24 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
|
||||
}
|
||||
|
||||
for (i = 0; i < num_vecs; i++) {
|
||||
err = test_hash_vec(driver, &vecs[i], i, req, tsgl, hashstate);
|
||||
err = test_hash_vec(driver, &vecs[i], i, req, desc, tsgl,
|
||||
hashstate);
|
||||
if (err)
|
||||
goto out;
|
||||
cond_resched();
|
||||
}
|
||||
err = test_hash_vs_generic_impl(driver, generic_driver, maxkeysize, req,
|
||||
tsgl, hashstate);
|
||||
desc, tsgl, hashstate);
|
||||
out:
|
||||
kfree(hashstate);
|
||||
if (tsgl) {
|
||||
destroy_test_sglist(tsgl);
|
||||
kfree(tsgl);
|
||||
}
|
||||
kfree(desc);
|
||||
crypto_free_shash(stfm);
|
||||
ahash_request_free(req);
|
||||
crypto_free_ahash(tfm);
|
||||
crypto_free_ahash(atfm);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1755,6 +2039,7 @@ static int test_aead_vec(const char *driver, int enc,
|
||||
&cfg, req, tsgls);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1864,7 +2149,7 @@ static int test_aead_vs_generic_impl(const char *driver,
|
||||
unsigned int i;
|
||||
struct aead_testvec vec = { 0 };
|
||||
char vec_name[64];
|
||||
struct testvec_config cfg;
|
||||
struct testvec_config *cfg;
|
||||
char cfgname[TESTVEC_CONFIG_NAMELEN];
|
||||
int err;
|
||||
|
||||
@@ -1894,6 +2179,12 @@ 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;
|
||||
@@ -1948,13 +2239,13 @@ static int test_aead_vs_generic_impl(const char *driver,
|
||||
generate_random_aead_testvec(generic_req, &vec,
|
||||
maxkeysize, maxdatasize,
|
||||
vec_name, sizeof(vec_name));
|
||||
generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname));
|
||||
generate_random_testvec_config(cfg, cfgname, sizeof(cfgname));
|
||||
|
||||
err = test_aead_vec_cfg(driver, ENCRYPT, &vec, vec_name, &cfg,
|
||||
err = test_aead_vec_cfg(driver, ENCRYPT, &vec, vec_name, cfg,
|
||||
req, tsgls);
|
||||
if (err)
|
||||
goto out;
|
||||
err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, &cfg,
|
||||
err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, cfg,
|
||||
req, tsgls);
|
||||
if (err)
|
||||
goto out;
|
||||
@@ -1962,6 +2253,7 @@ static int test_aead_vs_generic_impl(const char *driver,
|
||||
}
|
||||
err = 0;
|
||||
out:
|
||||
kfree(cfg);
|
||||
kfree(vec.key);
|
||||
kfree(vec.iv);
|
||||
kfree(vec.assoc);
|
||||
@@ -1994,6 +2286,7 @@ static int test_aead(const char *driver, int enc,
|
||||
tsgls);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2336,6 +2629,7 @@ static int test_skcipher_vec(const char *driver, int enc,
|
||||
&cfg, req, tsgls);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2409,7 +2703,7 @@ static int test_skcipher_vs_generic_impl(const char *driver,
|
||||
unsigned int i;
|
||||
struct cipher_testvec vec = { 0 };
|
||||
char vec_name[64];
|
||||
struct testvec_config cfg;
|
||||
struct testvec_config *cfg;
|
||||
char cfgname[TESTVEC_CONFIG_NAMELEN];
|
||||
int err;
|
||||
|
||||
@@ -2443,6 +2737,12 @@ static int test_skcipher_vs_generic_impl(const char *driver,
|
||||
return err;
|
||||
}
|
||||
|
||||
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
|
||||
if (!cfg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
generic_req = skcipher_request_alloc(generic_tfm, GFP_KERNEL);
|
||||
if (!generic_req) {
|
||||
err = -ENOMEM;
|
||||
@@ -2490,20 +2790,21 @@ static int test_skcipher_vs_generic_impl(const char *driver,
|
||||
for (i = 0; i < fuzz_iterations * 8; i++) {
|
||||
generate_random_cipher_testvec(generic_req, &vec, maxdatasize,
|
||||
vec_name, sizeof(vec_name));
|
||||
generate_random_testvec_config(&cfg, cfgname, sizeof(cfgname));
|
||||
generate_random_testvec_config(cfg, cfgname, sizeof(cfgname));
|
||||
|
||||
err = test_skcipher_vec_cfg(driver, ENCRYPT, &vec, vec_name,
|
||||
&cfg, req, tsgls);
|
||||
cfg, req, tsgls);
|
||||
if (err)
|
||||
goto out;
|
||||
err = test_skcipher_vec_cfg(driver, DECRYPT, &vec, vec_name,
|
||||
&cfg, req, tsgls);
|
||||
cfg, req, tsgls);
|
||||
if (err)
|
||||
goto out;
|
||||
cond_resched();
|
||||
}
|
||||
err = 0;
|
||||
out:
|
||||
kfree(cfg);
|
||||
kfree(vec.key);
|
||||
kfree(vec.iv);
|
||||
kfree(vec.ptext);
|
||||
@@ -2535,6 +2836,7 @@ static int test_skcipher(const char *driver, int enc,
|
||||
tsgls);
|
||||
if (err)
|
||||
return err;
|
||||
cond_resched();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -4125,6 +4427,7 @@ static const struct alg_test_desc alg_test_descs[] = {
|
||||
}
|
||||
}, {
|
||||
.alg = "ecb(arc4)",
|
||||
.generic_driver = "ecb(arc4)-generic",
|
||||
.test = alg_test_skcipher,
|
||||
.suite = {
|
||||
.cipher = __VECS(arc4_tv_template)
|
||||
@@ -4789,6 +5092,13 @@ static const struct alg_test_desc alg_test_descs[] = {
|
||||
.alg = "xts512(paes)",
|
||||
.test = alg_test_null,
|
||||
.fips_allowed = 1,
|
||||
}, {
|
||||
.alg = "xxhash64",
|
||||
.test = alg_test_hash,
|
||||
.fips_allowed = 1,
|
||||
.suite = {
|
||||
.hash = __VECS(xxhash64_tv_template)
|
||||
}
|
||||
}, {
|
||||
.alg = "zlib-deflate",
|
||||
.test = alg_test_comp,
|
||||
|
Reference in New Issue
Block a user