From nobody Tue Sep 9 16:53:38 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EAE88C7EE2E for ; Mon, 27 Feb 2023 18:30:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229889AbjB0Sa1 (ORCPT ); Mon, 27 Feb 2023 13:30:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36450 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229668AbjB0SaZ (ORCPT ); Mon, 27 Feb 2023 13:30:25 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6B2721E1DF; Mon, 27 Feb 2023 10:30:22 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id EA6EB60DEA; Mon, 27 Feb 2023 18:30:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 20726C433EF; Mon, 27 Feb 2023 18:30:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1677522621; bh=o1hLWCrKKNqcyxr3stmEtR/IVdP1UE9C4sakqVYmHxQ=; h=From:To:Cc:Subject:Date:From; b=oGXDyGl1CKW4yXYZHtNsNykD09HGfqnxWabSEBtFhaogdGMRGwk8+8G9CbEtRRuzE 0NQG1aimfWx/AMYzDBq6aUWYi7GscWiZRzr0g/z+yRohT0ds0d0DFrQhF4QRle1297 LX6L+s3c93msVaIS8m2HrKNuTyeNzku+dgakX3TLO4+uHAHHJNBIBg8zzV/x84SGsC mmpjI/SDstylZC84+dhQRfz0B4ej084QDpIMKgxHJW5A7ZQXT5sw+jUoYFxBw83Bj/ 0dMqNQ7UxSrCdW1R6zOX/NDJH7QO1IjqrL7AvYi3lQxC9JZhkc8l+wL1qxfIyQFKmZ scwJHxnVWS2eg== From: Eric Biggers To: linux-crypto@vger.kernel.org, Herbert Xu Cc: "Jason A . Donenfeld" , linux-kernel@vger.kernel.org, Yann Droneaud , stable@vger.kernel.org Subject: [PATCH v2] crypto: testmgr - fix RNG performance in fuzz tests Date: Mon, 27 Feb 2023 10:29:47 -0800 Message-Id: <20230227182947.61733-1-ebiggers@kernel.org> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Eric Biggers The performance of the crypto fuzz tests has greatly regressed since v5.18. When booting a kernel on an arm64 dev board with all software crypto algorithms and CONFIG_CRYPTO_MANAGER_EXTRA_TESTS enabled, the fuzz tests now take about 200 seconds to run, or about 325 seconds with lockdep enabled, compared to about 5 seconds before. The root cause is that the random number generation has become much slower due to commit d4150779e60f ("random32: use real rng for non-deterministic randomness"). On my same arm64 dev board, at the time the fuzz tests are run, get_random_u8() is about 345x slower than prandom_u32_state(), or about 469x if lockdep is enabled. Lockdep makes a big difference, but much of the rest comes from the get_random_*() functions taking a *very* slow path when the CRNG is not yet initialized. Since the crypto self-tests run early during boot, even having a hardware RNG driver enabled (CONFIG_CRYPTO_DEV_QCOM_RNG in my case) doesn't prevent this. x86 systems don't have this issue, but they still see a significant regression if lockdep is enabled. Converting the "Fully random bytes" case in generate_random_bytes() to use get_random_bytes() helps significantly, improving the test time to about 27 seconds. But that's still over 5x slower than before. This is all a bit silly, though, since the fuzz tests don't actually need cryptographically secure random numbers. So let's just make them use a non-cryptographically-secure RNG as they did before. The original prandom_u32() is gone now, so let's use prandom_u32_state() instead, with an explicitly managed state, like various other self-tests in the kernel source tree (rbtree_test.c, test_scanf.c, etc.) already do. This also has the benefit that no locking is required anymore, so performance should be even better than the original version that used prandom_u32(). Fixes: d4150779e60f ("random32: use real rng for non-deterministic randomne= ss") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers --- v2: made init_rnd_state() use get_random_u64() crypto/testmgr.c | 266 ++++++++++++++++++++++++++++++----------------- 1 file changed, 169 insertions(+), 97 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index c91e93ece20b..b160eeb12c8e 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -860,12 +860,50 @@ static int prepare_keybuf(const u8 *key, unsigned int= ksize, =20 #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS =20 +/* + * The fuzz tests use prandom instead of the normal Linux RNG since they d= on't + * need cryptographically secure random numbers. This greatly improves the + * performance of these tests, especially if they are run before the Linux= RNG + * has been initialized or if they are run on a lockdep-enabled kernel. + */ + +static inline void init_rnd_state(struct rnd_state *rng) +{ + prandom_seed_state(rng, get_random_u64()); +} + +static inline u8 prandom_u8(struct rnd_state *rng) +{ + return prandom_u32_state(rng); +} + +static inline u32 prandom_u32_below(struct rnd_state *rng, u32 ceil) +{ + /* + * This is slightly biased for non-power-of-2 values of 'ceil', but this + * isn't important here. + */ + return prandom_u32_state(rng) % ceil; +} + +static inline bool prandom_bool(struct rnd_state *rng) +{ + return prandom_u32_below(rng, 2); +} + +static inline u32 prandom_u32_inclusive(struct rnd_state *rng, + u32 floor, u32 ceil) +{ + return floor + prandom_u32_below(rng, ceil - floor + 1); +} + /* Generate a random length in range [0, max_len], but prefer smaller valu= es */ -static unsigned int generate_random_length(unsigned int max_len) +static unsigned int generate_random_length(struct rnd_state *rng, + unsigned int max_len) { - unsigned int len =3D get_random_u32_below(max_len + 1); + unsigned int len =3D prandom_u32_below(rng, max_len + 1); =20 - switch (get_random_u32_below(4)) { + switch (prandom_u32_below(rng, 4)) { case 0: return len % 64; case 1: @@ -878,43 +916,44 @@ static unsigned int generate_random_length(unsigned i= nt max_len) } =20 /* Flip a random bit in the given nonempty data buffer */ -static void flip_random_bit(u8 *buf, size_t size) +static void flip_random_bit(struct rnd_state *rng, u8 *buf, size_t size) { size_t bitpos; =20 - bitpos =3D get_random_u32_below(size * 8); + bitpos =3D prandom_u32_below(rng, size * 8); buf[bitpos / 8] ^=3D 1 << (bitpos % 8); } =20 /* Flip a random byte in the given nonempty data buffer */ -static void flip_random_byte(u8 *buf, size_t size) +static void flip_random_byte(struct rnd_state *rng, u8 *buf, size_t size) { - buf[get_random_u32_below(size)] ^=3D 0xff; + buf[prandom_u32_below(rng, size)] ^=3D 0xff; } =20 /* Sometimes make some random changes to the given nonempty data buffer */ -static void mutate_buffer(u8 *buf, size_t size) +static void mutate_buffer(struct rnd_state *rng, u8 *buf, size_t size) { size_t num_flips; size_t i; =20 /* Sometimes flip some bits */ - if (get_random_u32_below(4) =3D=3D 0) { - num_flips =3D min_t(size_t, 1 << get_random_u32_below(8), size * 8); + if (prandom_u32_below(rng, 4) =3D=3D 0) { + num_flips =3D min_t(size_t, 1 << prandom_u32_below(rng, 8), + size * 8); for (i =3D 0; i < num_flips; i++) - flip_random_bit(buf, size); + flip_random_bit(rng, buf, size); } =20 /* Sometimes flip some bytes */ - if (get_random_u32_below(4) =3D=3D 0) { - num_flips =3D min_t(size_t, 1 << get_random_u32_below(8), size); + if (prandom_u32_below(rng, 4) =3D=3D 0) { + num_flips =3D min_t(size_t, 1 << prandom_u32_below(rng, 8), size); for (i =3D 0; i < num_flips; i++) - flip_random_byte(buf, size); + flip_random_byte(rng, buf, size); } } =20 /* Randomly generate 'count' bytes, but sometimes make them "interesting" = */ -static void generate_random_bytes(u8 *buf, size_t count) +static void generate_random_bytes(struct rnd_state *rng, u8 *buf, size_t c= ount) { u8 b; u8 increment; @@ -923,11 +962,11 @@ static void generate_random_bytes(u8 *buf, size_t cou= nt) if (count =3D=3D 0) return; =20 - switch (get_random_u32_below(8)) { /* Choose a generation strategy */ + switch (prandom_u32_below(rng, 8)) { /* Choose a generation strategy */ case 0: case 1: /* All the same byte, plus optional mutations */ - switch (get_random_u32_below(4)) { + switch (prandom_u32_below(rng, 4)) { case 0: b =3D 0x00; break; @@ -935,28 +974,28 @@ static void generate_random_bytes(u8 *buf, size_t cou= nt) b =3D 0xff; break; default: - b =3D get_random_u8(); + b =3D prandom_u8(rng); break; } memset(buf, b, count); - mutate_buffer(buf, count); + mutate_buffer(rng, buf, count); break; case 2: /* Ascending or descending bytes, plus optional mutations */ - increment =3D get_random_u8(); - b =3D get_random_u8(); + increment =3D prandom_u8(rng); + b =3D prandom_u8(rng); for (i =3D 0; i < count; i++, b +=3D increment) buf[i] =3D b; - mutate_buffer(buf, count); + mutate_buffer(rng, buf, count); break; default: /* Fully random bytes */ - for (i =3D 0; i < count; i++) - buf[i] =3D get_random_u8(); + prandom_bytes_state(rng, buf, count); } } =20 -static char *generate_random_sgl_divisions(struct test_sg_division *divs, +static char *generate_random_sgl_divisions(struct rnd_state *rng, + struct test_sg_division *divs, size_t max_divs, char *p, char *end, bool gen_flushes, u32 req_flags) { @@ -967,24 +1006,26 @@ static char *generate_random_sgl_divisions(struct te= st_sg_division *divs, unsigned int this_len; const char *flushtype_str; =20 - if (div =3D=3D &divs[max_divs - 1] || get_random_u32_below(2) =3D=3D 0) + if (div =3D=3D &divs[max_divs - 1] || prandom_bool(rng)) this_len =3D remaining; else - this_len =3D get_random_u32_inclusive(1, remaining); + this_len =3D prandom_u32_inclusive(rng, 1, remaining); div->proportion_of_total =3D this_len; =20 - if (get_random_u32_below(4) =3D=3D 0) - div->offset =3D get_random_u32_inclusive(PAGE_SIZE - 128, PAGE_SIZE - 1= ); - else if (get_random_u32_below(2) =3D=3D 0) - div->offset =3D get_random_u32_below(32); + if (prandom_u32_below(rng, 4) =3D=3D 0) + div->offset =3D prandom_u32_inclusive(rng, + PAGE_SIZE - 128, + PAGE_SIZE - 1); + else if (prandom_bool(rng)) + div->offset =3D prandom_u32_below(rng, 32); else - div->offset =3D get_random_u32_below(PAGE_SIZE); - if (get_random_u32_below(8) =3D=3D 0) + div->offset =3D prandom_u32_below(rng, PAGE_SIZE); + if (prandom_u32_below(rng, 8) =3D=3D 0) div->offset_relative_to_alignmask =3D true; =20 div->flush_type =3D FLUSH_TYPE_NONE; if (gen_flushes) { - switch (get_random_u32_below(4)) { + switch (prandom_u32_below(rng, 4)) { case 0: div->flush_type =3D FLUSH_TYPE_REIMPORT; break; @@ -996,7 +1037,7 @@ static char *generate_random_sgl_divisions(struct test= _sg_division *divs, =20 if (div->flush_type !=3D FLUSH_TYPE_NONE && !(req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) && - get_random_u32_below(2) =3D=3D 0) + prandom_bool(rng)) div->nosimd =3D true; =20 switch (div->flush_type) { @@ -1031,7 +1072,8 @@ static char *generate_random_sgl_divisions(struct tes= t_sg_division *divs, } =20 /* Generate a random testvec_config for fuzz testing */ -static void generate_random_testvec_config(struct testvec_config *cfg, +static void generate_random_testvec_config(struct rnd_state *rng, + struct testvec_config *cfg, char *name, size_t max_namelen) { char *p =3D name; @@ -1043,7 +1085,7 @@ static void generate_random_testvec_config(struct tes= tvec_config *cfg, =20 p +=3D scnprintf(p, end - p, "random:"); =20 - switch (get_random_u32_below(4)) { + switch (prandom_u32_below(rng, 4)) { case 0: case 1: cfg->inplace_mode =3D OUT_OF_PLACE; @@ -1058,12 +1100,12 @@ static void generate_random_testvec_config(struct t= estvec_config *cfg, break; } =20 - if (get_random_u32_below(2) =3D=3D 0) { + if (prandom_bool(rng)) { cfg->req_flags |=3D CRYPTO_TFM_REQ_MAY_SLEEP; p +=3D scnprintf(p, end - p, " may_sleep"); } =20 - switch (get_random_u32_below(4)) { + switch (prandom_u32_below(rng, 4)) { case 0: cfg->finalization_type =3D FINALIZATION_TYPE_FINAL; p +=3D scnprintf(p, end - p, " use_final"); @@ -1078,36 +1120,37 @@ static void generate_random_testvec_config(struct t= estvec_config *cfg, break; } =20 - if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) && - get_random_u32_below(2) =3D=3D 0) { + if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) && prandom_bool(rng)) { cfg->nosimd =3D true; p +=3D scnprintf(p, end - p, " nosimd"); } =20 p +=3D scnprintf(p, end - p, " src_divs=3D["); - p =3D generate_random_sgl_divisions(cfg->src_divs, + p =3D generate_random_sgl_divisions(rng, cfg->src_divs, ARRAY_SIZE(cfg->src_divs), p, end, (cfg->finalization_type !=3D FINALIZATION_TYPE_DIGEST), cfg->req_flags); p +=3D scnprintf(p, end - p, "]"); =20 - if (cfg->inplace_mode =3D=3D OUT_OF_PLACE && get_random_u32_below(2) =3D= =3D 0) { + if (cfg->inplace_mode =3D=3D OUT_OF_PLACE && prandom_bool(rng)) { p +=3D scnprintf(p, end - p, " dst_divs=3D["); - p =3D generate_random_sgl_divisions(cfg->dst_divs, + p =3D generate_random_sgl_divisions(rng, cfg->dst_divs, ARRAY_SIZE(cfg->dst_divs), p, end, false, cfg->req_flags); p +=3D scnprintf(p, end - p, "]"); } =20 - if (get_random_u32_below(2) =3D=3D 0) { - cfg->iv_offset =3D get_random_u32_inclusive(1, MAX_ALGAPI_ALIGNMASK); + if (prandom_bool(rng)) { + cfg->iv_offset =3D prandom_u32_inclusive(rng, 1, + MAX_ALGAPI_ALIGNMASK); p +=3D scnprintf(p, end - p, " iv_offset=3D%u", cfg->iv_offset); } =20 - if (get_random_u32_below(2) =3D=3D 0) { - cfg->key_offset =3D get_random_u32_inclusive(1, MAX_ALGAPI_ALIGNMASK); + if (prandom_bool(rng)) { + cfg->key_offset =3D prandom_u32_inclusive(rng, 1, + MAX_ALGAPI_ALIGNMASK); p +=3D scnprintf(p, end - p, " key_offset=3D%u", cfg->key_offset); } =20 @@ -1620,11 +1663,14 @@ static int test_hash_vec(const struct hash_testvec = *vec, unsigned int vec_num, =20 #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS if (!noextratests) { + struct rnd_state rng; struct testvec_config cfg; char cfgname[TESTVEC_CONFIG_NAMELEN]; =20 + init_rnd_state(&rng); + for (i =3D 0; i < fuzz_iterations; i++) { - generate_random_testvec_config(&cfg, cfgname, + generate_random_testvec_config(&rng, &cfg, cfgname, sizeof(cfgname)); err =3D test_hash_vec_cfg(vec, vec_name, &cfg, req, desc, tsgl, hashstate); @@ -1642,15 +1688,16 @@ static int test_hash_vec(const struct hash_testvec = *vec, unsigned int vec_num, * Generate a hash test vector from the given implementation. * Assumes the buffers in 'vec' were already allocated. */ -static void generate_random_hash_testvec(struct shash_desc *desc, +static void generate_random_hash_testvec(struct rnd_state *rng, + struct shash_desc *desc, struct hash_testvec *vec, unsigned int maxkeysize, unsigned int maxdatasize, char *name, size_t max_namelen) { /* Data */ - vec->psize =3D generate_random_length(maxdatasize); - generate_random_bytes((u8 *)vec->plaintext, vec->psize); + vec->psize =3D generate_random_length(rng, maxdatasize); + generate_random_bytes(rng, (u8 *)vec->plaintext, vec->psize); =20 /* * Key: length in range [1, maxkeysize], but usually choose maxkeysize. @@ -1660,9 +1707,9 @@ static void generate_random_hash_testvec(struct shash= _desc *desc, vec->ksize =3D 0; if (maxkeysize) { vec->ksize =3D maxkeysize; - if (get_random_u32_below(4) =3D=3D 0) - vec->ksize =3D get_random_u32_inclusive(1, maxkeysize); - generate_random_bytes((u8 *)vec->key, vec->ksize); + if (prandom_u32_below(rng, 4) =3D=3D 0) + vec->ksize =3D prandom_u32_inclusive(rng, 1, maxkeysize); + generate_random_bytes(rng, (u8 *)vec->key, vec->ksize); =20 vec->setkey_error =3D crypto_shash_setkey(desc->tfm, vec->key, vec->ksize); @@ -1696,6 +1743,7 @@ static int test_hash_vs_generic_impl(const char *gene= ric_driver, const unsigned int maxdatasize =3D (2 * PAGE_SIZE) - TESTMGR_POISON_LEN; const char *algname =3D crypto_hash_alg_common(tfm)->base.cra_name; const char *driver =3D crypto_ahash_driver_name(tfm); + struct rnd_state rng; char _generic_driver[CRYPTO_MAX_ALG_NAME]; struct crypto_shash *generic_tfm =3D NULL; struct shash_desc *generic_desc =3D NULL; @@ -1709,6 +1757,8 @@ static int test_hash_vs_generic_impl(const char *gene= ric_driver, if (noextratests) return 0; =20 + init_rnd_state(&rng); + if (!generic_driver) { /* Use default naming convention? */ err =3D build_generic_driver_name(algname, _generic_driver); if (err) @@ -1777,10 +1827,11 @@ static int test_hash_vs_generic_impl(const char *ge= neric_driver, } =20 for (i =3D 0; i < fuzz_iterations * 8; i++) { - generate_random_hash_testvec(generic_desc, &vec, + generate_random_hash_testvec(&rng, generic_desc, &vec, maxkeysize, maxdatasize, vec_name, sizeof(vec_name)); - generate_random_testvec_config(cfg, cfgname, sizeof(cfgname)); + generate_random_testvec_config(&rng, cfg, cfgname, + sizeof(cfgname)); =20 err =3D test_hash_vec_cfg(&vec, vec_name, cfg, req, desc, tsgl, hashstate); @@ -2182,11 +2233,14 @@ static int test_aead_vec(int enc, const struct aead= _testvec *vec, =20 #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS if (!noextratests) { + struct rnd_state rng; struct testvec_config cfg; char cfgname[TESTVEC_CONFIG_NAMELEN]; =20 + init_rnd_state(&rng); + for (i =3D 0; i < fuzz_iterations; i++) { - generate_random_testvec_config(&cfg, cfgname, + generate_random_testvec_config(&rng, &cfg, cfgname, sizeof(cfgname)); err =3D test_aead_vec_cfg(enc, vec, vec_name, &cfg, req, tsgls); @@ -2202,6 +2256,7 @@ static int test_aead_vec(int enc, const struct aead_t= estvec *vec, #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS =20 struct aead_extra_tests_ctx { + struct rnd_state rng; struct aead_request *req; struct crypto_aead *tfm; const struct alg_test_desc *test_desc; @@ -2220,24 +2275,26 @@ struct aead_extra_tests_ctx { * here means the full ciphertext including the authentication tag. The * authentication tag (and hence also the ciphertext) is assumed to be non= empty. */ -static void mutate_aead_message(struct aead_testvec *vec, bool aad_iv, +static void mutate_aead_message(struct rnd_state *rng, + struct aead_testvec *vec, bool aad_iv, unsigned int ivsize) { const unsigned int aad_tail_size =3D aad_iv ? ivsize : 0; const unsigned int authsize =3D vec->clen - vec->plen; =20 - if (get_random_u32_below(2) =3D=3D 0 && vec->alen > aad_tail_size) { + if (prandom_bool(rng) && vec->alen > aad_tail_size) { /* Mutate the AAD */ - flip_random_bit((u8 *)vec->assoc, vec->alen - aad_tail_size); - if (get_random_u32_below(2) =3D=3D 0) + flip_random_bit(rng, (u8 *)vec->assoc, + vec->alen - aad_tail_size); + if (prandom_bool(rng)) return; } - if (get_random_u32_below(2) =3D=3D 0) { + if (prandom_bool(rng)) { /* Mutate auth tag (assuming it's at the end of ciphertext) */ - flip_random_bit((u8 *)vec->ctext + vec->plen, authsize); + flip_random_bit(rng, (u8 *)vec->ctext + vec->plen, authsize); } else { /* Mutate any part of the ciphertext */ - flip_random_bit((u8 *)vec->ctext, vec->clen); + flip_random_bit(rng, (u8 *)vec->ctext, vec->clen); } } =20 @@ -2248,7 +2305,8 @@ static void mutate_aead_message(struct aead_testvec *= vec, bool aad_iv, */ #define MIN_COLLISION_FREE_AUTHSIZE 8 =20 -static void generate_aead_message(struct aead_request *req, +static void generate_aead_message(struct rnd_state *rng, + struct aead_request *req, const struct aead_test_suite *suite, struct aead_testvec *vec, bool prefer_inauthentic) @@ -2257,17 +2315,18 @@ static void generate_aead_message(struct aead_reque= st *req, const unsigned int ivsize =3D crypto_aead_ivsize(tfm); const unsigned int authsize =3D vec->clen - vec->plen; const bool inauthentic =3D (authsize >=3D MIN_COLLISION_FREE_AUTHSIZE) && - (prefer_inauthentic || get_random_u32_below(4) =3D=3D 0); + (prefer_inauthentic || + prandom_u32_below(rng, 4) =3D=3D 0); =20 /* Generate the AAD. */ - generate_random_bytes((u8 *)vec->assoc, vec->alen); + generate_random_bytes(rng, (u8 *)vec->assoc, vec->alen); if (suite->aad_iv && vec->alen >=3D ivsize) /* Avoid implementation-defined behavior. */ memcpy((u8 *)vec->assoc + vec->alen - ivsize, vec->iv, ivsize); =20 - if (inauthentic && get_random_u32_below(2) =3D=3D 0) { + if (inauthentic && prandom_bool(rng)) { /* Generate a random ciphertext. */ - generate_random_bytes((u8 *)vec->ctext, vec->clen); + generate_random_bytes(rng, (u8 *)vec->ctext, vec->clen); } else { int i =3D 0; struct scatterlist src[2], dst; @@ -2279,7 +2338,7 @@ static void generate_aead_message(struct aead_request= *req, if (vec->alen) sg_set_buf(&src[i++], vec->assoc, vec->alen); if (vec->plen) { - generate_random_bytes((u8 *)vec->ptext, vec->plen); + generate_random_bytes(rng, (u8 *)vec->ptext, vec->plen); sg_set_buf(&src[i++], vec->ptext, vec->plen); } sg_init_one(&dst, vec->ctext, vec->alen + vec->clen); @@ -2299,7 +2358,7 @@ static void generate_aead_message(struct aead_request= *req, * Mutate the authentic (ciphertext, AAD) pair to get an * inauthentic one. */ - mutate_aead_message(vec, suite->aad_iv, ivsize); + mutate_aead_message(rng, vec, suite->aad_iv, ivsize); } vec->novrfy =3D 1; if (suite->einval_allowed) @@ -2313,7 +2372,8 @@ static void generate_aead_message(struct aead_request= *req, * If 'prefer_inauthentic' is true, then this function will generate inaut= hentic * test vectors (i.e. vectors with 'vec->novrfy=3D1') more often. */ -static void generate_random_aead_testvec(struct aead_request *req, +static void generate_random_aead_testvec(struct rnd_state *rng, + struct aead_request *req, struct aead_testvec *vec, const struct aead_test_suite *suite, unsigned int maxkeysize, @@ -2329,18 +2389,18 @@ static void generate_random_aead_testvec(struct aea= d_request *req, =20 /* Key: length in [0, maxkeysize], but usually choose maxkeysize */ vec->klen =3D maxkeysize; - if (get_random_u32_below(4) =3D=3D 0) - vec->klen =3D get_random_u32_below(maxkeysize + 1); - generate_random_bytes((u8 *)vec->key, vec->klen); + if (prandom_u32_below(rng, 4) =3D=3D 0) + vec->klen =3D prandom_u32_below(rng, maxkeysize + 1); + generate_random_bytes(rng, (u8 *)vec->key, vec->klen); vec->setkey_error =3D crypto_aead_setkey(tfm, vec->key, vec->klen); =20 /* IV */ - generate_random_bytes((u8 *)vec->iv, ivsize); + generate_random_bytes(rng, (u8 *)vec->iv, ivsize); =20 /* Tag length: in [0, maxauthsize], but usually choose maxauthsize */ authsize =3D maxauthsize; - if (get_random_u32_below(4) =3D=3D 0) - authsize =3D get_random_u32_below(maxauthsize + 1); + if (prandom_u32_below(rng, 4) =3D=3D 0) + authsize =3D prandom_u32_below(rng, maxauthsize + 1); if (prefer_inauthentic && authsize < MIN_COLLISION_FREE_AUTHSIZE) authsize =3D MIN_COLLISION_FREE_AUTHSIZE; if (WARN_ON(authsize > maxdatasize)) @@ -2349,11 +2409,11 @@ static void generate_random_aead_testvec(struct aea= d_request *req, vec->setauthsize_error =3D crypto_aead_setauthsize(tfm, authsize); =20 /* AAD, plaintext, and ciphertext lengths */ - total_len =3D generate_random_length(maxdatasize); - if (get_random_u32_below(4) =3D=3D 0) + total_len =3D generate_random_length(rng, maxdatasize); + if (prandom_u32_below(rng, 4) =3D=3D 0) vec->alen =3D 0; else - vec->alen =3D generate_random_length(total_len); + vec->alen =3D generate_random_length(rng, total_len); vec->plen =3D total_len - vec->alen; vec->clen =3D vec->plen + authsize; =20 @@ -2364,7 +2424,7 @@ static void generate_random_aead_testvec(struct aead_= request *req, vec->novrfy =3D 0; vec->crypt_error =3D 0; if (vec->setkey_error =3D=3D 0 && vec->setauthsize_error =3D=3D 0) - generate_aead_message(req, suite, vec, prefer_inauthentic); + generate_aead_message(rng, req, suite, vec, prefer_inauthentic); snprintf(name, max_namelen, "\"random: alen=3D%u plen=3D%u authsize=3D%u klen=3D%u novrfy=3D%d\"", vec->alen, vec->plen, authsize, vec->klen, vec->novrfy); @@ -2376,7 +2436,7 @@ static void try_to_generate_inauthentic_testvec( int i; =20 for (i =3D 0; i < 10; i++) { - generate_random_aead_testvec(ctx->req, &ctx->vec, + generate_random_aead_testvec(&ctx->rng, ctx->req, &ctx->vec, &ctx->test_desc->suite.aead, ctx->maxkeysize, ctx->maxdatasize, ctx->vec_name, @@ -2407,7 +2467,8 @@ static int test_aead_inauthentic_inputs(struct aead_e= xtra_tests_ctx *ctx) */ try_to_generate_inauthentic_testvec(ctx); if (ctx->vec.novrfy) { - generate_random_testvec_config(&ctx->cfg, ctx->cfgname, + generate_random_testvec_config(&ctx->rng, &ctx->cfg, + ctx->cfgname, sizeof(ctx->cfgname)); err =3D test_aead_vec_cfg(DECRYPT, &ctx->vec, ctx->vec_name, &ctx->cfg, @@ -2497,12 +2558,13 @@ static int test_aead_vs_generic_impl(struct aead_ex= tra_tests_ctx *ctx) * the other implementation against them. */ for (i =3D 0; i < fuzz_iterations * 8; i++) { - generate_random_aead_testvec(generic_req, &ctx->vec, + generate_random_aead_testvec(&ctx->rng, generic_req, &ctx->vec, &ctx->test_desc->suite.aead, ctx->maxkeysize, ctx->maxdatasize, ctx->vec_name, sizeof(ctx->vec_name), false); - generate_random_testvec_config(&ctx->cfg, ctx->cfgname, + generate_random_testvec_config(&ctx->rng, &ctx->cfg, + ctx->cfgname, sizeof(ctx->cfgname)); if (!ctx->vec.novrfy) { err =3D test_aead_vec_cfg(ENCRYPT, &ctx->vec, @@ -2541,6 +2603,7 @@ static int test_aead_extra(const struct alg_test_desc= *test_desc, ctx =3D kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; + init_rnd_state(&ctx->rng); ctx->req =3D req; ctx->tfm =3D crypto_aead_reqtfm(req); ctx->test_desc =3D test_desc; @@ -2930,11 +2993,14 @@ static int test_skcipher_vec(int enc, const struct = cipher_testvec *vec, =20 #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS if (!noextratests) { + struct rnd_state rng; struct testvec_config cfg; char cfgname[TESTVEC_CONFIG_NAMELEN]; =20 + init_rnd_state(&rng); + for (i =3D 0; i < fuzz_iterations; i++) { - generate_random_testvec_config(&cfg, cfgname, + generate_random_testvec_config(&rng, &cfg, cfgname, sizeof(cfgname)); err =3D test_skcipher_vec_cfg(enc, vec, vec_name, &cfg, req, tsgls); @@ -2952,7 +3018,8 @@ static int test_skcipher_vec(int enc, const struct ci= pher_testvec *vec, * Generate a symmetric cipher test vector from the given implementation. * Assumes the buffers in 'vec' were already allocated. */ -static void generate_random_cipher_testvec(struct skcipher_request *req, +static void generate_random_cipher_testvec(struct rnd_state *rng, + struct skcipher_request *req, struct cipher_testvec *vec, unsigned int maxdatasize, char *name, size_t max_namelen) @@ -2966,17 +3033,17 @@ static void generate_random_cipher_testvec(struct s= kcipher_request *req, =20 /* Key: length in [0, maxkeysize], but usually choose maxkeysize */ vec->klen =3D maxkeysize; - if (get_random_u32_below(4) =3D=3D 0) - vec->klen =3D get_random_u32_below(maxkeysize + 1); - generate_random_bytes((u8 *)vec->key, vec->klen); + if (prandom_u32_below(rng, 4) =3D=3D 0) + vec->klen =3D prandom_u32_below(rng, maxkeysize + 1); + generate_random_bytes(rng, (u8 *)vec->key, vec->klen); vec->setkey_error =3D crypto_skcipher_setkey(tfm, vec->key, vec->klen); =20 /* IV */ - generate_random_bytes((u8 *)vec->iv, ivsize); + generate_random_bytes(rng, (u8 *)vec->iv, ivsize); =20 /* Plaintext */ - vec->len =3D generate_random_length(maxdatasize); - generate_random_bytes((u8 *)vec->ptext, vec->len); + vec->len =3D generate_random_length(rng, maxdatasize); + generate_random_bytes(rng, (u8 *)vec->ptext, vec->len); =20 /* If the key couldn't be set, no need to continue to encrypt. */ if (vec->setkey_error) @@ -3018,6 +3085,7 @@ static int test_skcipher_vs_generic_impl(const char *= generic_driver, const unsigned int maxdatasize =3D (2 * PAGE_SIZE) - TESTMGR_POISON_LEN; const char *algname =3D crypto_skcipher_alg(tfm)->base.cra_name; const char *driver =3D crypto_skcipher_driver_name(tfm); + struct rnd_state rng; char _generic_driver[CRYPTO_MAX_ALG_NAME]; struct crypto_skcipher *generic_tfm =3D NULL; struct skcipher_request *generic_req =3D NULL; @@ -3035,6 +3103,8 @@ static int test_skcipher_vs_generic_impl(const char *= generic_driver, if (strncmp(algname, "kw(", 3) =3D=3D 0) return 0; =20 + init_rnd_state(&rng); + if (!generic_driver) { /* Use default naming convention? */ err =3D build_generic_driver_name(algname, _generic_driver); if (err) @@ -3119,9 +3189,11 @@ static int test_skcipher_vs_generic_impl(const char = *generic_driver, } =20 for (i =3D 0; i < fuzz_iterations * 8; i++) { - generate_random_cipher_testvec(generic_req, &vec, maxdatasize, + generate_random_cipher_testvec(&rng, generic_req, &vec, + maxdatasize, vec_name, sizeof(vec_name)); - generate_random_testvec_config(cfg, cfgname, sizeof(cfgname)); + generate_random_testvec_config(&rng, cfg, cfgname, + sizeof(cfgname)); =20 err =3D test_skcipher_vec_cfg(ENCRYPT, &vec, vec_name, cfg, req, tsgls); base-commit: 2fcd07b7ccd5fd10b2120d298363e4e6c53ccf9c --=20 2.39.2