Skip to content

Commit 8b54e6a

Browse files
committed
crypto: testmgr - Add multibuffer hash testing
This is based on a patch by Eric Biggers <[email protected]>. Add limited self-test for multibuffer hash code path. This tests only a single request in chain of a random length. The other requests are either all of the same length as the one being tested, or random lengths between 0 and PAGE_SIZE * 2 * XBUFSIZE. Potential extension include testing all requests rather than just the single one. Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Herbert Xu <[email protected]>
1 parent 108ce62 commit 8b54e6a

File tree

1 file changed

+136
-24
lines changed

1 file changed

+136
-24
lines changed

crypto/testmgr.c

Lines changed: 136 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ module_param(fuzz_iterations, uint, 0644);
5858
MODULE_PARM_DESC(fuzz_iterations, "number of fuzz test iterations");
5959
#endif
6060

61+
/* Multibuffer is unlimited. Set arbitrary limit for testing. */
62+
#define MAX_MB_MSGS 16
63+
6164
#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
6265

6366
/* a perfect nop */
@@ -299,6 +302,13 @@ struct test_sg_division {
299302
* @key_offset_relative_to_alignmask: if true, add the algorithm's alignmask to
300303
* the @key_offset
301304
* @finalization_type: what finalization function to use for hashes
305+
* @multibuffer: test with multibuffer
306+
* @multibuffer_index: random number used to generate the message index to use
307+
* for multibuffer.
308+
* @multibuffer_uneven: test with multibuffer using uneven lengths
309+
* @multibuffer_lens: random lengths to make chained request uneven
310+
* @multibuffer_count: random number used to generate the num_msgs parameter
311+
* for multibuffer
302312
* @nosimd: execute with SIMD disabled? Requires !CRYPTO_TFM_REQ_MAY_SLEEP.
303313
* This applies to the parts of the operation that aren't controlled
304314
* individually by @nosimd_setkey or @src_divs[].nosimd.
@@ -318,6 +328,11 @@ struct testvec_config {
318328
enum finalization_type finalization_type;
319329
bool nosimd;
320330
bool nosimd_setkey;
331+
bool multibuffer;
332+
unsigned int multibuffer_index;
333+
unsigned int multibuffer_count;
334+
bool multibuffer_uneven;
335+
unsigned int multibuffer_lens[MAX_MB_MSGS];
321336
};
322337

323338
#define TESTVEC_CONFIG_NAMELEN 192
@@ -557,6 +572,7 @@ struct test_sglist {
557572
char *bufs[XBUFSIZE];
558573
struct scatterlist sgl[XBUFSIZE];
559574
struct scatterlist sgl_saved[XBUFSIZE];
575+
struct scatterlist full_sgl[XBUFSIZE];
560576
struct scatterlist *sgl_ptr;
561577
unsigned int nents;
562578
};
@@ -670,6 +686,11 @@ static int build_test_sglist(struct test_sglist *tsgl,
670686
sg_mark_end(&tsgl->sgl[tsgl->nents - 1]);
671687
tsgl->sgl_ptr = tsgl->sgl;
672688
memcpy(tsgl->sgl_saved, tsgl->sgl, tsgl->nents * sizeof(tsgl->sgl[0]));
689+
690+
sg_init_table(tsgl->full_sgl, XBUFSIZE);
691+
for (i = 0; i < XBUFSIZE; i++)
692+
sg_set_buf(tsgl->full_sgl, tsgl->bufs[i], PAGE_SIZE * 2);
693+
673694
return 0;
674695
}
675696

@@ -1146,6 +1167,27 @@ static void generate_random_testvec_config(struct rnd_state *rng,
11461167
break;
11471168
}
11481169

1170+
if (prandom_bool(rng)) {
1171+
int i;
1172+
1173+
cfg->multibuffer = true;
1174+
cfg->multibuffer_count = prandom_u32_state(rng);
1175+
cfg->multibuffer_count %= MAX_MB_MSGS;
1176+
if (cfg->multibuffer_count++) {
1177+
cfg->multibuffer_index = prandom_u32_state(rng);
1178+
cfg->multibuffer_index %= cfg->multibuffer_count;
1179+
}
1180+
1181+
cfg->multibuffer_uneven = prandom_bool(rng);
1182+
for (i = 0; i < MAX_MB_MSGS; i++)
1183+
cfg->multibuffer_lens[i] =
1184+
generate_random_length(rng, PAGE_SIZE * 2 * XBUFSIZE);
1185+
1186+
p += scnprintf(p, end - p, " multibuffer(%d/%d%s)",
1187+
cfg->multibuffer_index, cfg->multibuffer_count,
1188+
cfg->multibuffer_uneven ? "/uneven" : "");
1189+
}
1190+
11491191
if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP)) {
11501192
if (prandom_bool(rng)) {
11511193
cfg->nosimd = true;
@@ -1450,6 +1492,7 @@ static int do_ahash_op(int (*op)(struct ahash_request *req),
14501492
struct ahash_request *req,
14511493
struct crypto_wait *wait, bool nosimd)
14521494
{
1495+
struct ahash_request *r2;
14531496
int err;
14541497

14551498
if (nosimd)
@@ -1460,7 +1503,15 @@ static int do_ahash_op(int (*op)(struct ahash_request *req),
14601503
if (nosimd)
14611504
crypto_reenable_simd_for_test();
14621505

1463-
return crypto_wait_req(err, wait);
1506+
err = crypto_wait_req(err, wait);
1507+
if (err)
1508+
return err;
1509+
1510+
list_for_each_entry(r2, &req->base.list, base.list)
1511+
if (r2->base.err)
1512+
return r2->base.err;
1513+
1514+
return 0;
14641515
}
14651516

14661517
static int check_nonfinal_ahash_op(const char *op, int err,
@@ -1481,27 +1532,75 @@ static int check_nonfinal_ahash_op(const char *op, int err,
14811532
return 0;
14821533
}
14831534

1535+
static void setup_ahash_multibuffer(
1536+
struct ahash_request *reqs[MAX_MB_MSGS],
1537+
const struct testvec_config *cfg,
1538+
struct test_sglist *tsgl)
1539+
{
1540+
struct scatterlist *sg = tsgl->full_sgl;
1541+
static u8 trash[HASH_MAX_DIGESTSIZE];
1542+
struct ahash_request *req = reqs[0];
1543+
unsigned int num_msgs;
1544+
unsigned int msg_idx;
1545+
int i;
1546+
1547+
if (!cfg->multibuffer)
1548+
return;
1549+
1550+
num_msgs = cfg->multibuffer_count;
1551+
if (num_msgs == 1)
1552+
return;
1553+
1554+
msg_idx = cfg->multibuffer_index;
1555+
for (i = 1; i < num_msgs; i++) {
1556+
struct ahash_request *r2 = reqs[i];
1557+
unsigned int nbytes = req->nbytes;
1558+
1559+
if (cfg->multibuffer_uneven)
1560+
nbytes = cfg->multibuffer_lens[i];
1561+
1562+
ahash_request_set_callback(r2, req->base.flags, NULL, NULL);
1563+
ahash_request_set_crypt(r2, sg, trash, nbytes);
1564+
ahash_request_chain(r2, req);
1565+
}
1566+
1567+
if (msg_idx) {
1568+
reqs[msg_idx]->src = req->src;
1569+
reqs[msg_idx]->nbytes = req->nbytes;
1570+
reqs[msg_idx]->result = req->result;
1571+
req->src = sg;
1572+
if (cfg->multibuffer_uneven)
1573+
req->nbytes = cfg->multibuffer_lens[0];
1574+
req->result = trash;
1575+
}
1576+
}
1577+
14841578
/* Test one hash test vector in one configuration, using the ahash API */
14851579
static int test_ahash_vec_cfg(const struct hash_testvec *vec,
14861580
const char *vec_name,
14871581
const struct testvec_config *cfg,
1488-
struct ahash_request *req,
1582+
struct ahash_request *reqs[MAX_MB_MSGS],
14891583
struct test_sglist *tsgl,
14901584
u8 *hashstate)
14911585
{
1586+
struct ahash_request *req = reqs[0];
14921587
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
14931588
const unsigned int digestsize = crypto_ahash_digestsize(tfm);
14941589
const unsigned int statesize = crypto_ahash_statesize(tfm);
14951590
const char *driver = crypto_ahash_driver_name(tfm);
14961591
const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags;
14971592
const struct test_sg_division *divs[XBUFSIZE];
1593+
struct ahash_request *reqi = req;
14981594
DECLARE_CRYPTO_WAIT(wait);
14991595
unsigned int i;
15001596
struct scatterlist *pending_sgl;
15011597
unsigned int pending_len;
15021598
u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN];
15031599
int err;
15041600

1601+
if (cfg->multibuffer)
1602+
reqi = reqs[cfg->multibuffer_index];
1603+
15051604
/* Set the key, if specified */
15061605
if (vec->ksize) {
15071606
err = do_setkey(crypto_ahash_setkey, tfm, vec->key, vec->ksize,
@@ -1531,7 +1630,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
15311630

15321631
/* Do the actual hashing */
15331632

1534-
testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
1633+
testmgr_poison(reqi->__ctx, crypto_ahash_reqsize(tfm));
15351634
testmgr_poison(result, digestsize + TESTMGR_POISON_LEN);
15361635

15371636
if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST ||
@@ -1540,6 +1639,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
15401639
ahash_request_set_callback(req, req_flags, crypto_req_done,
15411640
&wait);
15421641
ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize);
1642+
setup_ahash_multibuffer(reqs, cfg, tsgl);
15431643
err = do_ahash_op(crypto_ahash_digest, req, &wait, cfg->nosimd);
15441644
if (err) {
15451645
if (err == vec->digest_error)
@@ -1561,6 +1661,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
15611661

15621662
ahash_request_set_callback(req, req_flags, crypto_req_done, &wait);
15631663
ahash_request_set_crypt(req, NULL, result, 0);
1664+
setup_ahash_multibuffer(reqs, cfg, tsgl);
15641665
err = do_ahash_op(crypto_ahash_init, req, &wait, cfg->nosimd);
15651666
err = check_nonfinal_ahash_op("init", err, result, digestsize,
15661667
driver, vec_name, cfg);
@@ -1577,6 +1678,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
15771678
crypto_req_done, &wait);
15781679
ahash_request_set_crypt(req, pending_sgl, result,
15791680
pending_len);
1681+
setup_ahash_multibuffer(reqs, cfg, tsgl);
15801682
err = do_ahash_op(crypto_ahash_update, req, &wait,
15811683
divs[i]->nosimd);
15821684
err = check_nonfinal_ahash_op("update", err,
@@ -1591,7 +1693,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
15911693
/* Test ->export() and ->import() */
15921694
testmgr_poison(hashstate + statesize,
15931695
TESTMGR_POISON_LEN);
1594-
err = crypto_ahash_export(req, hashstate);
1696+
err = crypto_ahash_export(reqi, hashstate);
15951697
err = check_nonfinal_ahash_op("export", err,
15961698
result, digestsize,
15971699
driver, vec_name, cfg);
@@ -1604,8 +1706,8 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
16041706
return -EOVERFLOW;
16051707
}
16061708

1607-
testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
1608-
err = crypto_ahash_import(req, hashstate);
1709+
testmgr_poison(reqi->__ctx, crypto_ahash_reqsize(tfm));
1710+
err = crypto_ahash_import(reqi, hashstate);
16091711
err = check_nonfinal_ahash_op("import", err,
16101712
result, digestsize,
16111713
driver, vec_name, cfg);
@@ -1619,6 +1721,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
16191721

16201722
ahash_request_set_callback(req, req_flags, crypto_req_done, &wait);
16211723
ahash_request_set_crypt(req, pending_sgl, result, pending_len);
1724+
setup_ahash_multibuffer(reqs, cfg, tsgl);
16221725
if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) {
16231726
/* finish with update() and final() */
16241727
err = do_ahash_op(crypto_ahash_update, req, &wait, cfg->nosimd);
@@ -1650,7 +1753,7 @@ static int test_ahash_vec_cfg(const struct hash_testvec *vec,
16501753
static int test_hash_vec_cfg(const struct hash_testvec *vec,
16511754
const char *vec_name,
16521755
const struct testvec_config *cfg,
1653-
struct ahash_request *req,
1756+
struct ahash_request *reqs[MAX_MB_MSGS],
16541757
struct shash_desc *desc,
16551758
struct test_sglist *tsgl,
16561759
u8 *hashstate)
@@ -1670,11 +1773,12 @@ static int test_hash_vec_cfg(const struct hash_testvec *vec,
16701773
return err;
16711774
}
16721775

1673-
return test_ahash_vec_cfg(vec, vec_name, cfg, req, tsgl, hashstate);
1776+
return test_ahash_vec_cfg(vec, vec_name, cfg, reqs, tsgl, hashstate);
16741777
}
16751778

16761779
static int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num,
1677-
struct ahash_request *req, struct shash_desc *desc,
1780+
struct ahash_request *reqs[MAX_MB_MSGS],
1781+
struct shash_desc *desc,
16781782
struct test_sglist *tsgl, u8 *hashstate)
16791783
{
16801784
char vec_name[16];
@@ -1686,7 +1790,7 @@ static int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num,
16861790
for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) {
16871791
err = test_hash_vec_cfg(vec, vec_name,
16881792
&default_hash_testvec_configs[i],
1689-
req, desc, tsgl, hashstate);
1793+
reqs, desc, tsgl, hashstate);
16901794
if (err)
16911795
return err;
16921796
}
@@ -1703,7 +1807,7 @@ static int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num,
17031807
generate_random_testvec_config(&rng, &cfg, cfgname,
17041808
sizeof(cfgname));
17051809
err = test_hash_vec_cfg(vec, vec_name, &cfg,
1706-
req, desc, tsgl, hashstate);
1810+
reqs, desc, tsgl, hashstate);
17071811
if (err)
17081812
return err;
17091813
cond_resched();
@@ -1762,11 +1866,12 @@ static void generate_random_hash_testvec(struct rnd_state *rng,
17621866
*/
17631867
static int test_hash_vs_generic_impl(const char *generic_driver,
17641868
unsigned int maxkeysize,
1765-
struct ahash_request *req,
1869+
struct ahash_request *reqs[MAX_MB_MSGS],
17661870
struct shash_desc *desc,
17671871
struct test_sglist *tsgl,
17681872
u8 *hashstate)
17691873
{
1874+
struct ahash_request *req = reqs[0];
17701875
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
17711876
const unsigned int digestsize = crypto_ahash_digestsize(tfm);
17721877
const unsigned int blocksize = crypto_ahash_blocksize(tfm);
@@ -1864,7 +1969,7 @@ static int test_hash_vs_generic_impl(const char *generic_driver,
18641969
sizeof(cfgname));
18651970

18661971
err = test_hash_vec_cfg(&vec, vec_name, cfg,
1867-
req, desc, tsgl, hashstate);
1972+
reqs, desc, tsgl, hashstate);
18681973
if (err)
18691974
goto out;
18701975
cond_resched();
@@ -1882,7 +1987,7 @@ static int test_hash_vs_generic_impl(const char *generic_driver,
18821987
#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
18831988
static int test_hash_vs_generic_impl(const char *generic_driver,
18841989
unsigned int maxkeysize,
1885-
struct ahash_request *req,
1990+
struct ahash_request *reqs[MAX_MB_MSGS],
18861991
struct shash_desc *desc,
18871992
struct test_sglist *tsgl,
18881993
u8 *hashstate)
@@ -1929,8 +2034,8 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
19292034
u32 type, u32 mask,
19302035
const char *generic_driver, unsigned int maxkeysize)
19312036
{
2037+
struct ahash_request *reqs[MAX_MB_MSGS] = {};
19322038
struct crypto_ahash *atfm = NULL;
1933-
struct ahash_request *req = NULL;
19342039
struct crypto_shash *stfm = NULL;
19352040
struct shash_desc *desc = NULL;
19362041
struct test_sglist *tsgl = NULL;
@@ -1954,12 +2059,14 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
19542059
}
19552060
driver = crypto_ahash_driver_name(atfm);
19562061

1957-
req = ahash_request_alloc(atfm, GFP_KERNEL);
1958-
if (!req) {
1959-
pr_err("alg: hash: failed to allocate request for %s\n",
1960-
driver);
1961-
err = -ENOMEM;
1962-
goto out;
2062+
for (i = 0; i < MAX_MB_MSGS; i++) {
2063+
reqs[i] = ahash_request_alloc(atfm, GFP_KERNEL);
2064+
if (!reqs[i]) {
2065+
pr_err("alg: hash: failed to allocate request for %s\n",
2066+
driver);
2067+
err = -ENOMEM;
2068+
goto out;
2069+
}
19632070
}
19642071

19652072
/*
@@ -1995,12 +2102,12 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
19952102
if (fips_enabled && vecs[i].fips_skip)
19962103
continue;
19972104

1998-
err = test_hash_vec(&vecs[i], i, req, desc, tsgl, hashstate);
2105+
err = test_hash_vec(&vecs[i], i, reqs, desc, tsgl, hashstate);
19992106
if (err)
20002107
goto out;
20012108
cond_resched();
20022109
}
2003-
err = test_hash_vs_generic_impl(generic_driver, maxkeysize, req,
2110+
err = test_hash_vs_generic_impl(generic_driver, maxkeysize, reqs,
20042111
desc, tsgl, hashstate);
20052112
out:
20062113
kfree(hashstate);
@@ -2010,7 +2117,12 @@ static int __alg_test_hash(const struct hash_testvec *vecs,
20102117
}
20112118
kfree(desc);
20122119
crypto_free_shash(stfm);
2013-
ahash_request_free(req);
2120+
if (reqs[0]) {
2121+
ahash_request_set_callback(reqs[0], 0, NULL, NULL);
2122+
for (i = 1; i < MAX_MB_MSGS && reqs[i]; i++)
2123+
ahash_request_chain(reqs[i], reqs[0]);
2124+
ahash_request_free(reqs[0]);
2125+
}
20142126
crypto_free_ahash(atfm);
20152127
return err;
20162128
}

0 commit comments

Comments
 (0)