162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Algorithm testing framework and tests.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
662306a36Sopenharmony_ci * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
762306a36Sopenharmony_ci * Copyright (c) 2007 Nokia Siemens Networks
862306a36Sopenharmony_ci * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
962306a36Sopenharmony_ci * Copyright (c) 2019 Google LLC
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Updated RFC4106 AES-GCM testing.
1262306a36Sopenharmony_ci *    Authors: Aidan O'Mahony (aidan.o.mahony@intel.com)
1362306a36Sopenharmony_ci *             Adrian Hoban <adrian.hoban@intel.com>
1462306a36Sopenharmony_ci *             Gabriele Paoloni <gabriele.paoloni@intel.com>
1562306a36Sopenharmony_ci *             Tadeusz Struk (tadeusz.struk@intel.com)
1662306a36Sopenharmony_ci *    Copyright (c) 2010, Intel Corporation.
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <crypto/aead.h>
2062306a36Sopenharmony_ci#include <crypto/hash.h>
2162306a36Sopenharmony_ci#include <crypto/skcipher.h>
2262306a36Sopenharmony_ci#include <linux/err.h>
2362306a36Sopenharmony_ci#include <linux/fips.h>
2462306a36Sopenharmony_ci#include <linux/module.h>
2562306a36Sopenharmony_ci#include <linux/once.h>
2662306a36Sopenharmony_ci#include <linux/random.h>
2762306a36Sopenharmony_ci#include <linux/scatterlist.h>
2862306a36Sopenharmony_ci#include <linux/slab.h>
2962306a36Sopenharmony_ci#include <linux/string.h>
3062306a36Sopenharmony_ci#include <linux/uio.h>
3162306a36Sopenharmony_ci#include <crypto/rng.h>
3262306a36Sopenharmony_ci#include <crypto/drbg.h>
3362306a36Sopenharmony_ci#include <crypto/akcipher.h>
3462306a36Sopenharmony_ci#include <crypto/kpp.h>
3562306a36Sopenharmony_ci#include <crypto/acompress.h>
3662306a36Sopenharmony_ci#include <crypto/internal/cipher.h>
3762306a36Sopenharmony_ci#include <crypto/internal/simd.h>
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#include "internal.h"
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ciMODULE_IMPORT_NS(CRYPTO_INTERNAL);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic bool notests;
4462306a36Sopenharmony_cimodule_param(notests, bool, 0644);
4562306a36Sopenharmony_ciMODULE_PARM_DESC(notests, "disable crypto self-tests");
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic bool panic_on_fail;
4862306a36Sopenharmony_cimodule_param(panic_on_fail, bool, 0444);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
5162306a36Sopenharmony_cistatic bool noextratests;
5262306a36Sopenharmony_cimodule_param(noextratests, bool, 0644);
5362306a36Sopenharmony_ciMODULE_PARM_DESC(noextratests, "disable expensive crypto self-tests");
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic unsigned int fuzz_iterations = 100;
5662306a36Sopenharmony_cimodule_param(fuzz_iterations, uint, 0644);
5762306a36Sopenharmony_ciMODULE_PARM_DESC(fuzz_iterations, "number of fuzz test iterations");
5862306a36Sopenharmony_ci#endif
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/* a perfect nop */
6362306a36Sopenharmony_ciint alg_test(const char *driver, const char *alg, u32 type, u32 mask)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	return 0;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#else
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#include "testmgr.h"
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/*
7362306a36Sopenharmony_ci * Need slab memory for testing (size in number of pages).
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_ci#define XBUFSIZE	8
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/*
7862306a36Sopenharmony_ci* Used by test_cipher()
7962306a36Sopenharmony_ci*/
8062306a36Sopenharmony_ci#define ENCRYPT 1
8162306a36Sopenharmony_ci#define DECRYPT 0
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistruct aead_test_suite {
8462306a36Sopenharmony_ci	const struct aead_testvec *vecs;
8562306a36Sopenharmony_ci	unsigned int count;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	/*
8862306a36Sopenharmony_ci	 * Set if trying to decrypt an inauthentic ciphertext with this
8962306a36Sopenharmony_ci	 * algorithm might result in EINVAL rather than EBADMSG, due to other
9062306a36Sopenharmony_ci	 * validation the algorithm does on the inputs such as length checks.
9162306a36Sopenharmony_ci	 */
9262306a36Sopenharmony_ci	unsigned int einval_allowed : 1;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	/*
9562306a36Sopenharmony_ci	 * Set if this algorithm requires that the IV be located at the end of
9662306a36Sopenharmony_ci	 * the AAD buffer, in addition to being given in the normal way.  The
9762306a36Sopenharmony_ci	 * behavior when the two IV copies differ is implementation-defined.
9862306a36Sopenharmony_ci	 */
9962306a36Sopenharmony_ci	unsigned int aad_iv : 1;
10062306a36Sopenharmony_ci};
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistruct cipher_test_suite {
10362306a36Sopenharmony_ci	const struct cipher_testvec *vecs;
10462306a36Sopenharmony_ci	unsigned int count;
10562306a36Sopenharmony_ci};
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistruct comp_test_suite {
10862306a36Sopenharmony_ci	struct {
10962306a36Sopenharmony_ci		const struct comp_testvec *vecs;
11062306a36Sopenharmony_ci		unsigned int count;
11162306a36Sopenharmony_ci	} comp, decomp;
11262306a36Sopenharmony_ci};
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistruct hash_test_suite {
11562306a36Sopenharmony_ci	const struct hash_testvec *vecs;
11662306a36Sopenharmony_ci	unsigned int count;
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistruct cprng_test_suite {
12062306a36Sopenharmony_ci	const struct cprng_testvec *vecs;
12162306a36Sopenharmony_ci	unsigned int count;
12262306a36Sopenharmony_ci};
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistruct drbg_test_suite {
12562306a36Sopenharmony_ci	const struct drbg_testvec *vecs;
12662306a36Sopenharmony_ci	unsigned int count;
12762306a36Sopenharmony_ci};
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistruct akcipher_test_suite {
13062306a36Sopenharmony_ci	const struct akcipher_testvec *vecs;
13162306a36Sopenharmony_ci	unsigned int count;
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistruct kpp_test_suite {
13562306a36Sopenharmony_ci	const struct kpp_testvec *vecs;
13662306a36Sopenharmony_ci	unsigned int count;
13762306a36Sopenharmony_ci};
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistruct alg_test_desc {
14062306a36Sopenharmony_ci	const char *alg;
14162306a36Sopenharmony_ci	const char *generic_driver;
14262306a36Sopenharmony_ci	int (*test)(const struct alg_test_desc *desc, const char *driver,
14362306a36Sopenharmony_ci		    u32 type, u32 mask);
14462306a36Sopenharmony_ci	int fips_allowed;	/* set if alg is allowed in fips mode */
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	union {
14762306a36Sopenharmony_ci		struct aead_test_suite aead;
14862306a36Sopenharmony_ci		struct cipher_test_suite cipher;
14962306a36Sopenharmony_ci		struct comp_test_suite comp;
15062306a36Sopenharmony_ci		struct hash_test_suite hash;
15162306a36Sopenharmony_ci		struct cprng_test_suite cprng;
15262306a36Sopenharmony_ci		struct drbg_test_suite drbg;
15362306a36Sopenharmony_ci		struct akcipher_test_suite akcipher;
15462306a36Sopenharmony_ci		struct kpp_test_suite kpp;
15562306a36Sopenharmony_ci	} suite;
15662306a36Sopenharmony_ci};
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistatic void hexdump(unsigned char *buf, unsigned int len)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
16162306a36Sopenharmony_ci			16, 1,
16262306a36Sopenharmony_ci			buf, len, false);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic int __testmgr_alloc_buf(char *buf[XBUFSIZE], int order)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	int i;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	for (i = 0; i < XBUFSIZE; i++) {
17062306a36Sopenharmony_ci		buf[i] = (char *)__get_free_pages(GFP_KERNEL, order);
17162306a36Sopenharmony_ci		if (!buf[i])
17262306a36Sopenharmony_ci			goto err_free_buf;
17362306a36Sopenharmony_ci	}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	return 0;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cierr_free_buf:
17862306a36Sopenharmony_ci	while (i-- > 0)
17962306a36Sopenharmony_ci		free_pages((unsigned long)buf[i], order);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	return -ENOMEM;
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic int testmgr_alloc_buf(char *buf[XBUFSIZE])
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	return __testmgr_alloc_buf(buf, 0);
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistatic void __testmgr_free_buf(char *buf[XBUFSIZE], int order)
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci	int i;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	for (i = 0; i < XBUFSIZE; i++)
19462306a36Sopenharmony_ci		free_pages((unsigned long)buf[i], order);
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic void testmgr_free_buf(char *buf[XBUFSIZE])
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	__testmgr_free_buf(buf, 0);
20062306a36Sopenharmony_ci}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci#define TESTMGR_POISON_BYTE	0xfe
20362306a36Sopenharmony_ci#define TESTMGR_POISON_LEN	16
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistatic inline void testmgr_poison(void *addr, size_t len)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	memset(addr, TESTMGR_POISON_BYTE, len);
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci/* Is the memory region still fully poisoned? */
21162306a36Sopenharmony_cistatic inline bool testmgr_is_poison(const void *addr, size_t len)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	return memchr_inv(addr, TESTMGR_POISON_BYTE, len) == NULL;
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci/* flush type for hash algorithms */
21762306a36Sopenharmony_cienum flush_type {
21862306a36Sopenharmony_ci	/* merge with update of previous buffer(s) */
21962306a36Sopenharmony_ci	FLUSH_TYPE_NONE = 0,
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	/* update with previous buffer(s) before doing this one */
22262306a36Sopenharmony_ci	FLUSH_TYPE_FLUSH,
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	/* likewise, but also export and re-import the intermediate state */
22562306a36Sopenharmony_ci	FLUSH_TYPE_REIMPORT,
22662306a36Sopenharmony_ci};
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci/* finalization function for hash algorithms */
22962306a36Sopenharmony_cienum finalization_type {
23062306a36Sopenharmony_ci	FINALIZATION_TYPE_FINAL,	/* use final() */
23162306a36Sopenharmony_ci	FINALIZATION_TYPE_FINUP,	/* use finup() */
23262306a36Sopenharmony_ci	FINALIZATION_TYPE_DIGEST,	/* use digest() */
23362306a36Sopenharmony_ci};
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci/*
23662306a36Sopenharmony_ci * Whether the crypto operation will occur in-place, and if so whether the
23762306a36Sopenharmony_ci * source and destination scatterlist pointers will coincide (req->src ==
23862306a36Sopenharmony_ci * req->dst), or whether they'll merely point to two separate scatterlists
23962306a36Sopenharmony_ci * (req->src != req->dst) that reference the same underlying memory.
24062306a36Sopenharmony_ci *
24162306a36Sopenharmony_ci * This is only relevant for algorithm types that support in-place operation.
24262306a36Sopenharmony_ci */
24362306a36Sopenharmony_cienum inplace_mode {
24462306a36Sopenharmony_ci	OUT_OF_PLACE,
24562306a36Sopenharmony_ci	INPLACE_ONE_SGLIST,
24662306a36Sopenharmony_ci	INPLACE_TWO_SGLISTS,
24762306a36Sopenharmony_ci};
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci#define TEST_SG_TOTAL	10000
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci/**
25262306a36Sopenharmony_ci * struct test_sg_division - description of a scatterlist entry
25362306a36Sopenharmony_ci *
25462306a36Sopenharmony_ci * This struct describes one entry of a scatterlist being constructed to check a
25562306a36Sopenharmony_ci * crypto test vector.
25662306a36Sopenharmony_ci *
25762306a36Sopenharmony_ci * @proportion_of_total: length of this chunk relative to the total length,
25862306a36Sopenharmony_ci *			 given as a proportion out of TEST_SG_TOTAL so that it
25962306a36Sopenharmony_ci *			 scales to fit any test vector
26062306a36Sopenharmony_ci * @offset: byte offset into a 2-page buffer at which this chunk will start
26162306a36Sopenharmony_ci * @offset_relative_to_alignmask: if true, add the algorithm's alignmask to the
26262306a36Sopenharmony_ci *				  @offset
26362306a36Sopenharmony_ci * @flush_type: for hashes, whether an update() should be done now vs.
26462306a36Sopenharmony_ci *		continuing to accumulate data
26562306a36Sopenharmony_ci * @nosimd: if doing the pending update(), do it with SIMD disabled?
26662306a36Sopenharmony_ci */
26762306a36Sopenharmony_cistruct test_sg_division {
26862306a36Sopenharmony_ci	unsigned int proportion_of_total;
26962306a36Sopenharmony_ci	unsigned int offset;
27062306a36Sopenharmony_ci	bool offset_relative_to_alignmask;
27162306a36Sopenharmony_ci	enum flush_type flush_type;
27262306a36Sopenharmony_ci	bool nosimd;
27362306a36Sopenharmony_ci};
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/**
27662306a36Sopenharmony_ci * struct testvec_config - configuration for testing a crypto test vector
27762306a36Sopenharmony_ci *
27862306a36Sopenharmony_ci * This struct describes the data layout and other parameters with which each
27962306a36Sopenharmony_ci * crypto test vector can be tested.
28062306a36Sopenharmony_ci *
28162306a36Sopenharmony_ci * @name: name of this config, logged for debugging purposes if a test fails
28262306a36Sopenharmony_ci * @inplace_mode: whether and how to operate on the data in-place, if applicable
28362306a36Sopenharmony_ci * @req_flags: extra request_flags, e.g. CRYPTO_TFM_REQ_MAY_SLEEP
28462306a36Sopenharmony_ci * @src_divs: description of how to arrange the source scatterlist
28562306a36Sopenharmony_ci * @dst_divs: description of how to arrange the dst scatterlist, if applicable
28662306a36Sopenharmony_ci *	      for the algorithm type.  Defaults to @src_divs if unset.
28762306a36Sopenharmony_ci * @iv_offset: misalignment of the IV in the range [0..MAX_ALGAPI_ALIGNMASK+1],
28862306a36Sopenharmony_ci *	       where 0 is aligned to a 2*(MAX_ALGAPI_ALIGNMASK+1) byte boundary
28962306a36Sopenharmony_ci * @iv_offset_relative_to_alignmask: if true, add the algorithm's alignmask to
29062306a36Sopenharmony_ci *				     the @iv_offset
29162306a36Sopenharmony_ci * @key_offset: misalignment of the key, where 0 is default alignment
29262306a36Sopenharmony_ci * @key_offset_relative_to_alignmask: if true, add the algorithm's alignmask to
29362306a36Sopenharmony_ci *				      the @key_offset
29462306a36Sopenharmony_ci * @finalization_type: what finalization function to use for hashes
29562306a36Sopenharmony_ci * @nosimd: execute with SIMD disabled?  Requires !CRYPTO_TFM_REQ_MAY_SLEEP.
29662306a36Sopenharmony_ci */
29762306a36Sopenharmony_cistruct testvec_config {
29862306a36Sopenharmony_ci	const char *name;
29962306a36Sopenharmony_ci	enum inplace_mode inplace_mode;
30062306a36Sopenharmony_ci	u32 req_flags;
30162306a36Sopenharmony_ci	struct test_sg_division src_divs[XBUFSIZE];
30262306a36Sopenharmony_ci	struct test_sg_division dst_divs[XBUFSIZE];
30362306a36Sopenharmony_ci	unsigned int iv_offset;
30462306a36Sopenharmony_ci	unsigned int key_offset;
30562306a36Sopenharmony_ci	bool iv_offset_relative_to_alignmask;
30662306a36Sopenharmony_ci	bool key_offset_relative_to_alignmask;
30762306a36Sopenharmony_ci	enum finalization_type finalization_type;
30862306a36Sopenharmony_ci	bool nosimd;
30962306a36Sopenharmony_ci};
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci#define TESTVEC_CONFIG_NAMELEN	192
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci/*
31462306a36Sopenharmony_ci * The following are the lists of testvec_configs to test for each algorithm
31562306a36Sopenharmony_ci * type when the basic crypto self-tests are enabled, i.e. when
31662306a36Sopenharmony_ci * CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is unset.  They aim to provide good test
31762306a36Sopenharmony_ci * coverage, while keeping the test time much shorter than the full fuzz tests
31862306a36Sopenharmony_ci * so that the basic tests can be enabled in a wider range of circumstances.
31962306a36Sopenharmony_ci */
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci/* Configs for skciphers and aeads */
32262306a36Sopenharmony_cistatic const struct testvec_config default_cipher_testvec_configs[] = {
32362306a36Sopenharmony_ci	{
32462306a36Sopenharmony_ci		.name = "in-place (one sglist)",
32562306a36Sopenharmony_ci		.inplace_mode = INPLACE_ONE_SGLIST,
32662306a36Sopenharmony_ci		.src_divs = { { .proportion_of_total = 10000 } },
32762306a36Sopenharmony_ci	}, {
32862306a36Sopenharmony_ci		.name = "in-place (two sglists)",
32962306a36Sopenharmony_ci		.inplace_mode = INPLACE_TWO_SGLISTS,
33062306a36Sopenharmony_ci		.src_divs = { { .proportion_of_total = 10000 } },
33162306a36Sopenharmony_ci	}, {
33262306a36Sopenharmony_ci		.name = "out-of-place",
33362306a36Sopenharmony_ci		.inplace_mode = OUT_OF_PLACE,
33462306a36Sopenharmony_ci		.src_divs = { { .proportion_of_total = 10000 } },
33562306a36Sopenharmony_ci	}, {
33662306a36Sopenharmony_ci		.name = "unaligned buffer, offset=1",
33762306a36Sopenharmony_ci		.src_divs = { { .proportion_of_total = 10000, .offset = 1 } },
33862306a36Sopenharmony_ci		.iv_offset = 1,
33962306a36Sopenharmony_ci		.key_offset = 1,
34062306a36Sopenharmony_ci	}, {
34162306a36Sopenharmony_ci		.name = "buffer aligned only to alignmask",
34262306a36Sopenharmony_ci		.src_divs = {
34362306a36Sopenharmony_ci			{
34462306a36Sopenharmony_ci				.proportion_of_total = 10000,
34562306a36Sopenharmony_ci				.offset = 1,
34662306a36Sopenharmony_ci				.offset_relative_to_alignmask = true,
34762306a36Sopenharmony_ci			},
34862306a36Sopenharmony_ci		},
34962306a36Sopenharmony_ci		.iv_offset = 1,
35062306a36Sopenharmony_ci		.iv_offset_relative_to_alignmask = true,
35162306a36Sopenharmony_ci		.key_offset = 1,
35262306a36Sopenharmony_ci		.key_offset_relative_to_alignmask = true,
35362306a36Sopenharmony_ci	}, {
35462306a36Sopenharmony_ci		.name = "two even aligned splits",
35562306a36Sopenharmony_ci		.src_divs = {
35662306a36Sopenharmony_ci			{ .proportion_of_total = 5000 },
35762306a36Sopenharmony_ci			{ .proportion_of_total = 5000 },
35862306a36Sopenharmony_ci		},
35962306a36Sopenharmony_ci	}, {
36062306a36Sopenharmony_ci		.name = "one src, two even splits dst",
36162306a36Sopenharmony_ci		.inplace_mode = OUT_OF_PLACE,
36262306a36Sopenharmony_ci		.src_divs = { { .proportion_of_total = 10000 } },
36362306a36Sopenharmony_ci		.dst_divs = {
36462306a36Sopenharmony_ci			{ .proportion_of_total = 5000 },
36562306a36Sopenharmony_ci			{ .proportion_of_total = 5000 },
36662306a36Sopenharmony_ci		 },
36762306a36Sopenharmony_ci	}, {
36862306a36Sopenharmony_ci		.name = "uneven misaligned splits, may sleep",
36962306a36Sopenharmony_ci		.req_flags = CRYPTO_TFM_REQ_MAY_SLEEP,
37062306a36Sopenharmony_ci		.src_divs = {
37162306a36Sopenharmony_ci			{ .proportion_of_total = 1900, .offset = 33 },
37262306a36Sopenharmony_ci			{ .proportion_of_total = 3300, .offset = 7  },
37362306a36Sopenharmony_ci			{ .proportion_of_total = 4800, .offset = 18 },
37462306a36Sopenharmony_ci		},
37562306a36Sopenharmony_ci		.iv_offset = 3,
37662306a36Sopenharmony_ci		.key_offset = 3,
37762306a36Sopenharmony_ci	}, {
37862306a36Sopenharmony_ci		.name = "misaligned splits crossing pages, inplace",
37962306a36Sopenharmony_ci		.inplace_mode = INPLACE_ONE_SGLIST,
38062306a36Sopenharmony_ci		.src_divs = {
38162306a36Sopenharmony_ci			{
38262306a36Sopenharmony_ci				.proportion_of_total = 7500,
38362306a36Sopenharmony_ci				.offset = PAGE_SIZE - 32
38462306a36Sopenharmony_ci			}, {
38562306a36Sopenharmony_ci				.proportion_of_total = 2500,
38662306a36Sopenharmony_ci				.offset = PAGE_SIZE - 7
38762306a36Sopenharmony_ci			},
38862306a36Sopenharmony_ci		},
38962306a36Sopenharmony_ci	}
39062306a36Sopenharmony_ci};
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_cistatic const struct testvec_config default_hash_testvec_configs[] = {
39362306a36Sopenharmony_ci	{
39462306a36Sopenharmony_ci		.name = "init+update+final aligned buffer",
39562306a36Sopenharmony_ci		.src_divs = { { .proportion_of_total = 10000 } },
39662306a36Sopenharmony_ci		.finalization_type = FINALIZATION_TYPE_FINAL,
39762306a36Sopenharmony_ci	}, {
39862306a36Sopenharmony_ci		.name = "init+finup aligned buffer",
39962306a36Sopenharmony_ci		.src_divs = { { .proportion_of_total = 10000 } },
40062306a36Sopenharmony_ci		.finalization_type = FINALIZATION_TYPE_FINUP,
40162306a36Sopenharmony_ci	}, {
40262306a36Sopenharmony_ci		.name = "digest aligned buffer",
40362306a36Sopenharmony_ci		.src_divs = { { .proportion_of_total = 10000 } },
40462306a36Sopenharmony_ci		.finalization_type = FINALIZATION_TYPE_DIGEST,
40562306a36Sopenharmony_ci	}, {
40662306a36Sopenharmony_ci		.name = "init+update+final misaligned buffer",
40762306a36Sopenharmony_ci		.src_divs = { { .proportion_of_total = 10000, .offset = 1 } },
40862306a36Sopenharmony_ci		.finalization_type = FINALIZATION_TYPE_FINAL,
40962306a36Sopenharmony_ci		.key_offset = 1,
41062306a36Sopenharmony_ci	}, {
41162306a36Sopenharmony_ci		.name = "digest buffer aligned only to alignmask",
41262306a36Sopenharmony_ci		.src_divs = {
41362306a36Sopenharmony_ci			{
41462306a36Sopenharmony_ci				.proportion_of_total = 10000,
41562306a36Sopenharmony_ci				.offset = 1,
41662306a36Sopenharmony_ci				.offset_relative_to_alignmask = true,
41762306a36Sopenharmony_ci			},
41862306a36Sopenharmony_ci		},
41962306a36Sopenharmony_ci		.finalization_type = FINALIZATION_TYPE_DIGEST,
42062306a36Sopenharmony_ci		.key_offset = 1,
42162306a36Sopenharmony_ci		.key_offset_relative_to_alignmask = true,
42262306a36Sopenharmony_ci	}, {
42362306a36Sopenharmony_ci		.name = "init+update+update+final two even splits",
42462306a36Sopenharmony_ci		.src_divs = {
42562306a36Sopenharmony_ci			{ .proportion_of_total = 5000 },
42662306a36Sopenharmony_ci			{
42762306a36Sopenharmony_ci				.proportion_of_total = 5000,
42862306a36Sopenharmony_ci				.flush_type = FLUSH_TYPE_FLUSH,
42962306a36Sopenharmony_ci			},
43062306a36Sopenharmony_ci		},
43162306a36Sopenharmony_ci		.finalization_type = FINALIZATION_TYPE_FINAL,
43262306a36Sopenharmony_ci	}, {
43362306a36Sopenharmony_ci		.name = "digest uneven misaligned splits, may sleep",
43462306a36Sopenharmony_ci		.req_flags = CRYPTO_TFM_REQ_MAY_SLEEP,
43562306a36Sopenharmony_ci		.src_divs = {
43662306a36Sopenharmony_ci			{ .proportion_of_total = 1900, .offset = 33 },
43762306a36Sopenharmony_ci			{ .proportion_of_total = 3300, .offset = 7  },
43862306a36Sopenharmony_ci			{ .proportion_of_total = 4800, .offset = 18 },
43962306a36Sopenharmony_ci		},
44062306a36Sopenharmony_ci		.finalization_type = FINALIZATION_TYPE_DIGEST,
44162306a36Sopenharmony_ci	}, {
44262306a36Sopenharmony_ci		.name = "digest misaligned splits crossing pages",
44362306a36Sopenharmony_ci		.src_divs = {
44462306a36Sopenharmony_ci			{
44562306a36Sopenharmony_ci				.proportion_of_total = 7500,
44662306a36Sopenharmony_ci				.offset = PAGE_SIZE - 32,
44762306a36Sopenharmony_ci			}, {
44862306a36Sopenharmony_ci				.proportion_of_total = 2500,
44962306a36Sopenharmony_ci				.offset = PAGE_SIZE - 7,
45062306a36Sopenharmony_ci			},
45162306a36Sopenharmony_ci		},
45262306a36Sopenharmony_ci		.finalization_type = FINALIZATION_TYPE_DIGEST,
45362306a36Sopenharmony_ci	}, {
45462306a36Sopenharmony_ci		.name = "import/export",
45562306a36Sopenharmony_ci		.src_divs = {
45662306a36Sopenharmony_ci			{
45762306a36Sopenharmony_ci				.proportion_of_total = 6500,
45862306a36Sopenharmony_ci				.flush_type = FLUSH_TYPE_REIMPORT,
45962306a36Sopenharmony_ci			}, {
46062306a36Sopenharmony_ci				.proportion_of_total = 3500,
46162306a36Sopenharmony_ci				.flush_type = FLUSH_TYPE_REIMPORT,
46262306a36Sopenharmony_ci			},
46362306a36Sopenharmony_ci		},
46462306a36Sopenharmony_ci		.finalization_type = FINALIZATION_TYPE_FINAL,
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci};
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_cistatic unsigned int count_test_sg_divisions(const struct test_sg_division *divs)
46962306a36Sopenharmony_ci{
47062306a36Sopenharmony_ci	unsigned int remaining = TEST_SG_TOTAL;
47162306a36Sopenharmony_ci	unsigned int ndivs = 0;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	do {
47462306a36Sopenharmony_ci		remaining -= divs[ndivs++].proportion_of_total;
47562306a36Sopenharmony_ci	} while (remaining);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	return ndivs;
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci#define SGDIVS_HAVE_FLUSHES	BIT(0)
48162306a36Sopenharmony_ci#define SGDIVS_HAVE_NOSIMD	BIT(1)
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic bool valid_sg_divisions(const struct test_sg_division *divs,
48462306a36Sopenharmony_ci			       unsigned int count, int *flags_ret)
48562306a36Sopenharmony_ci{
48662306a36Sopenharmony_ci	unsigned int total = 0;
48762306a36Sopenharmony_ci	unsigned int i;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	for (i = 0; i < count && total != TEST_SG_TOTAL; i++) {
49062306a36Sopenharmony_ci		if (divs[i].proportion_of_total <= 0 ||
49162306a36Sopenharmony_ci		    divs[i].proportion_of_total > TEST_SG_TOTAL - total)
49262306a36Sopenharmony_ci			return false;
49362306a36Sopenharmony_ci		total += divs[i].proportion_of_total;
49462306a36Sopenharmony_ci		if (divs[i].flush_type != FLUSH_TYPE_NONE)
49562306a36Sopenharmony_ci			*flags_ret |= SGDIVS_HAVE_FLUSHES;
49662306a36Sopenharmony_ci		if (divs[i].nosimd)
49762306a36Sopenharmony_ci			*flags_ret |= SGDIVS_HAVE_NOSIMD;
49862306a36Sopenharmony_ci	}
49962306a36Sopenharmony_ci	return total == TEST_SG_TOTAL &&
50062306a36Sopenharmony_ci		memchr_inv(&divs[i], 0, (count - i) * sizeof(divs[0])) == NULL;
50162306a36Sopenharmony_ci}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci/*
50462306a36Sopenharmony_ci * Check whether the given testvec_config is valid.  This isn't strictly needed
50562306a36Sopenharmony_ci * since every testvec_config should be valid, but check anyway so that people
50662306a36Sopenharmony_ci * don't unknowingly add broken configs that don't do what they wanted.
50762306a36Sopenharmony_ci */
50862306a36Sopenharmony_cistatic bool valid_testvec_config(const struct testvec_config *cfg)
50962306a36Sopenharmony_ci{
51062306a36Sopenharmony_ci	int flags = 0;
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	if (cfg->name == NULL)
51362306a36Sopenharmony_ci		return false;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	if (!valid_sg_divisions(cfg->src_divs, ARRAY_SIZE(cfg->src_divs),
51662306a36Sopenharmony_ci				&flags))
51762306a36Sopenharmony_ci		return false;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	if (cfg->dst_divs[0].proportion_of_total) {
52062306a36Sopenharmony_ci		if (!valid_sg_divisions(cfg->dst_divs,
52162306a36Sopenharmony_ci					ARRAY_SIZE(cfg->dst_divs), &flags))
52262306a36Sopenharmony_ci			return false;
52362306a36Sopenharmony_ci	} else {
52462306a36Sopenharmony_ci		if (memchr_inv(cfg->dst_divs, 0, sizeof(cfg->dst_divs)))
52562306a36Sopenharmony_ci			return false;
52662306a36Sopenharmony_ci		/* defaults to dst_divs=src_divs */
52762306a36Sopenharmony_ci	}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	if (cfg->iv_offset +
53062306a36Sopenharmony_ci	    (cfg->iv_offset_relative_to_alignmask ? MAX_ALGAPI_ALIGNMASK : 0) >
53162306a36Sopenharmony_ci	    MAX_ALGAPI_ALIGNMASK + 1)
53262306a36Sopenharmony_ci		return false;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	if ((flags & (SGDIVS_HAVE_FLUSHES | SGDIVS_HAVE_NOSIMD)) &&
53562306a36Sopenharmony_ci	    cfg->finalization_type == FINALIZATION_TYPE_DIGEST)
53662306a36Sopenharmony_ci		return false;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	if ((cfg->nosimd || (flags & SGDIVS_HAVE_NOSIMD)) &&
53962306a36Sopenharmony_ci	    (cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP))
54062306a36Sopenharmony_ci		return false;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	return true;
54362306a36Sopenharmony_ci}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_cistruct test_sglist {
54662306a36Sopenharmony_ci	char *bufs[XBUFSIZE];
54762306a36Sopenharmony_ci	struct scatterlist sgl[XBUFSIZE];
54862306a36Sopenharmony_ci	struct scatterlist sgl_saved[XBUFSIZE];
54962306a36Sopenharmony_ci	struct scatterlist *sgl_ptr;
55062306a36Sopenharmony_ci	unsigned int nents;
55162306a36Sopenharmony_ci};
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_cistatic int init_test_sglist(struct test_sglist *tsgl)
55462306a36Sopenharmony_ci{
55562306a36Sopenharmony_ci	return __testmgr_alloc_buf(tsgl->bufs, 1 /* two pages per buffer */);
55662306a36Sopenharmony_ci}
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_cistatic void destroy_test_sglist(struct test_sglist *tsgl)
55962306a36Sopenharmony_ci{
56062306a36Sopenharmony_ci	return __testmgr_free_buf(tsgl->bufs, 1 /* two pages per buffer */);
56162306a36Sopenharmony_ci}
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci/**
56462306a36Sopenharmony_ci * build_test_sglist() - build a scatterlist for a crypto test
56562306a36Sopenharmony_ci *
56662306a36Sopenharmony_ci * @tsgl: the scatterlist to build.  @tsgl->bufs[] contains an array of 2-page
56762306a36Sopenharmony_ci *	  buffers which the scatterlist @tsgl->sgl[] will be made to point into.
56862306a36Sopenharmony_ci * @divs: the layout specification on which the scatterlist will be based
56962306a36Sopenharmony_ci * @alignmask: the algorithm's alignmask
57062306a36Sopenharmony_ci * @total_len: the total length of the scatterlist to build in bytes
57162306a36Sopenharmony_ci * @data: if non-NULL, the buffers will be filled with this data until it ends.
57262306a36Sopenharmony_ci *	  Otherwise the buffers will be poisoned.  In both cases, some bytes
57362306a36Sopenharmony_ci *	  past the end of each buffer will be poisoned to help detect overruns.
57462306a36Sopenharmony_ci * @out_divs: if non-NULL, the test_sg_division to which each scatterlist entry
57562306a36Sopenharmony_ci *	      corresponds will be returned here.  This will match @divs except
57662306a36Sopenharmony_ci *	      that divisions resolving to a length of 0 are omitted as they are
57762306a36Sopenharmony_ci *	      not included in the scatterlist.
57862306a36Sopenharmony_ci *
57962306a36Sopenharmony_ci * Return: 0 or a -errno value
58062306a36Sopenharmony_ci */
58162306a36Sopenharmony_cistatic int build_test_sglist(struct test_sglist *tsgl,
58262306a36Sopenharmony_ci			     const struct test_sg_division *divs,
58362306a36Sopenharmony_ci			     const unsigned int alignmask,
58462306a36Sopenharmony_ci			     const unsigned int total_len,
58562306a36Sopenharmony_ci			     struct iov_iter *data,
58662306a36Sopenharmony_ci			     const struct test_sg_division *out_divs[XBUFSIZE])
58762306a36Sopenharmony_ci{
58862306a36Sopenharmony_ci	struct {
58962306a36Sopenharmony_ci		const struct test_sg_division *div;
59062306a36Sopenharmony_ci		size_t length;
59162306a36Sopenharmony_ci	} partitions[XBUFSIZE];
59262306a36Sopenharmony_ci	const unsigned int ndivs = count_test_sg_divisions(divs);
59362306a36Sopenharmony_ci	unsigned int len_remaining = total_len;
59462306a36Sopenharmony_ci	unsigned int i;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	BUILD_BUG_ON(ARRAY_SIZE(partitions) != ARRAY_SIZE(tsgl->sgl));
59762306a36Sopenharmony_ci	if (WARN_ON(ndivs > ARRAY_SIZE(partitions)))
59862306a36Sopenharmony_ci		return -EINVAL;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	/* Calculate the (div, length) pairs */
60162306a36Sopenharmony_ci	tsgl->nents = 0;
60262306a36Sopenharmony_ci	for (i = 0; i < ndivs; i++) {
60362306a36Sopenharmony_ci		unsigned int len_this_sg =
60462306a36Sopenharmony_ci			min(len_remaining,
60562306a36Sopenharmony_ci			    (total_len * divs[i].proportion_of_total +
60662306a36Sopenharmony_ci			     TEST_SG_TOTAL / 2) / TEST_SG_TOTAL);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci		if (len_this_sg != 0) {
60962306a36Sopenharmony_ci			partitions[tsgl->nents].div = &divs[i];
61062306a36Sopenharmony_ci			partitions[tsgl->nents].length = len_this_sg;
61162306a36Sopenharmony_ci			tsgl->nents++;
61262306a36Sopenharmony_ci			len_remaining -= len_this_sg;
61362306a36Sopenharmony_ci		}
61462306a36Sopenharmony_ci	}
61562306a36Sopenharmony_ci	if (tsgl->nents == 0) {
61662306a36Sopenharmony_ci		partitions[tsgl->nents].div = &divs[0];
61762306a36Sopenharmony_ci		partitions[tsgl->nents].length = 0;
61862306a36Sopenharmony_ci		tsgl->nents++;
61962306a36Sopenharmony_ci	}
62062306a36Sopenharmony_ci	partitions[tsgl->nents - 1].length += len_remaining;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	/* Set up the sgl entries and fill the data or poison */
62362306a36Sopenharmony_ci	sg_init_table(tsgl->sgl, tsgl->nents);
62462306a36Sopenharmony_ci	for (i = 0; i < tsgl->nents; i++) {
62562306a36Sopenharmony_ci		unsigned int offset = partitions[i].div->offset;
62662306a36Sopenharmony_ci		void *addr;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci		if (partitions[i].div->offset_relative_to_alignmask)
62962306a36Sopenharmony_ci			offset += alignmask;
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci		while (offset + partitions[i].length + TESTMGR_POISON_LEN >
63262306a36Sopenharmony_ci		       2 * PAGE_SIZE) {
63362306a36Sopenharmony_ci			if (WARN_ON(offset <= 0))
63462306a36Sopenharmony_ci				return -EINVAL;
63562306a36Sopenharmony_ci			offset /= 2;
63662306a36Sopenharmony_ci		}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci		addr = &tsgl->bufs[i][offset];
63962306a36Sopenharmony_ci		sg_set_buf(&tsgl->sgl[i], addr, partitions[i].length);
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci		if (out_divs)
64262306a36Sopenharmony_ci			out_divs[i] = partitions[i].div;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci		if (data) {
64562306a36Sopenharmony_ci			size_t copy_len, copied;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci			copy_len = min(partitions[i].length, data->count);
64862306a36Sopenharmony_ci			copied = copy_from_iter(addr, copy_len, data);
64962306a36Sopenharmony_ci			if (WARN_ON(copied != copy_len))
65062306a36Sopenharmony_ci				return -EINVAL;
65162306a36Sopenharmony_ci			testmgr_poison(addr + copy_len, partitions[i].length +
65262306a36Sopenharmony_ci				       TESTMGR_POISON_LEN - copy_len);
65362306a36Sopenharmony_ci		} else {
65462306a36Sopenharmony_ci			testmgr_poison(addr, partitions[i].length +
65562306a36Sopenharmony_ci				       TESTMGR_POISON_LEN);
65662306a36Sopenharmony_ci		}
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	sg_mark_end(&tsgl->sgl[tsgl->nents - 1]);
66062306a36Sopenharmony_ci	tsgl->sgl_ptr = tsgl->sgl;
66162306a36Sopenharmony_ci	memcpy(tsgl->sgl_saved, tsgl->sgl, tsgl->nents * sizeof(tsgl->sgl[0]));
66262306a36Sopenharmony_ci	return 0;
66362306a36Sopenharmony_ci}
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci/*
66662306a36Sopenharmony_ci * Verify that a scatterlist crypto operation produced the correct output.
66762306a36Sopenharmony_ci *
66862306a36Sopenharmony_ci * @tsgl: scatterlist containing the actual output
66962306a36Sopenharmony_ci * @expected_output: buffer containing the expected output
67062306a36Sopenharmony_ci * @len_to_check: length of @expected_output in bytes
67162306a36Sopenharmony_ci * @unchecked_prefix_len: number of ignored bytes in @tsgl prior to real result
67262306a36Sopenharmony_ci * @check_poison: verify that the poison bytes after each chunk are intact?
67362306a36Sopenharmony_ci *
67462306a36Sopenharmony_ci * Return: 0 if correct, -EINVAL if incorrect, -EOVERFLOW if buffer overrun.
67562306a36Sopenharmony_ci */
67662306a36Sopenharmony_cistatic int verify_correct_output(const struct test_sglist *tsgl,
67762306a36Sopenharmony_ci				 const char *expected_output,
67862306a36Sopenharmony_ci				 unsigned int len_to_check,
67962306a36Sopenharmony_ci				 unsigned int unchecked_prefix_len,
68062306a36Sopenharmony_ci				 bool check_poison)
68162306a36Sopenharmony_ci{
68262306a36Sopenharmony_ci	unsigned int i;
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	for (i = 0; i < tsgl->nents; i++) {
68562306a36Sopenharmony_ci		struct scatterlist *sg = &tsgl->sgl_ptr[i];
68662306a36Sopenharmony_ci		unsigned int len = sg->length;
68762306a36Sopenharmony_ci		unsigned int offset = sg->offset;
68862306a36Sopenharmony_ci		const char *actual_output;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci		if (unchecked_prefix_len) {
69162306a36Sopenharmony_ci			if (unchecked_prefix_len >= len) {
69262306a36Sopenharmony_ci				unchecked_prefix_len -= len;
69362306a36Sopenharmony_ci				continue;
69462306a36Sopenharmony_ci			}
69562306a36Sopenharmony_ci			offset += unchecked_prefix_len;
69662306a36Sopenharmony_ci			len -= unchecked_prefix_len;
69762306a36Sopenharmony_ci			unchecked_prefix_len = 0;
69862306a36Sopenharmony_ci		}
69962306a36Sopenharmony_ci		len = min(len, len_to_check);
70062306a36Sopenharmony_ci		actual_output = page_address(sg_page(sg)) + offset;
70162306a36Sopenharmony_ci		if (memcmp(expected_output, actual_output, len) != 0)
70262306a36Sopenharmony_ci			return -EINVAL;
70362306a36Sopenharmony_ci		if (check_poison &&
70462306a36Sopenharmony_ci		    !testmgr_is_poison(actual_output + len, TESTMGR_POISON_LEN))
70562306a36Sopenharmony_ci			return -EOVERFLOW;
70662306a36Sopenharmony_ci		len_to_check -= len;
70762306a36Sopenharmony_ci		expected_output += len;
70862306a36Sopenharmony_ci	}
70962306a36Sopenharmony_ci	if (WARN_ON(len_to_check != 0))
71062306a36Sopenharmony_ci		return -EINVAL;
71162306a36Sopenharmony_ci	return 0;
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cistatic bool is_test_sglist_corrupted(const struct test_sglist *tsgl)
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	unsigned int i;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	for (i = 0; i < tsgl->nents; i++) {
71962306a36Sopenharmony_ci		if (tsgl->sgl[i].page_link != tsgl->sgl_saved[i].page_link)
72062306a36Sopenharmony_ci			return true;
72162306a36Sopenharmony_ci		if (tsgl->sgl[i].offset != tsgl->sgl_saved[i].offset)
72262306a36Sopenharmony_ci			return true;
72362306a36Sopenharmony_ci		if (tsgl->sgl[i].length != tsgl->sgl_saved[i].length)
72462306a36Sopenharmony_ci			return true;
72562306a36Sopenharmony_ci	}
72662306a36Sopenharmony_ci	return false;
72762306a36Sopenharmony_ci}
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_cistruct cipher_test_sglists {
73062306a36Sopenharmony_ci	struct test_sglist src;
73162306a36Sopenharmony_ci	struct test_sglist dst;
73262306a36Sopenharmony_ci};
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_cistatic struct cipher_test_sglists *alloc_cipher_test_sglists(void)
73562306a36Sopenharmony_ci{
73662306a36Sopenharmony_ci	struct cipher_test_sglists *tsgls;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	tsgls = kmalloc(sizeof(*tsgls), GFP_KERNEL);
73962306a36Sopenharmony_ci	if (!tsgls)
74062306a36Sopenharmony_ci		return NULL;
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	if (init_test_sglist(&tsgls->src) != 0)
74362306a36Sopenharmony_ci		goto fail_kfree;
74462306a36Sopenharmony_ci	if (init_test_sglist(&tsgls->dst) != 0)
74562306a36Sopenharmony_ci		goto fail_destroy_src;
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	return tsgls;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_cifail_destroy_src:
75062306a36Sopenharmony_ci	destroy_test_sglist(&tsgls->src);
75162306a36Sopenharmony_cifail_kfree:
75262306a36Sopenharmony_ci	kfree(tsgls);
75362306a36Sopenharmony_ci	return NULL;
75462306a36Sopenharmony_ci}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_cistatic void free_cipher_test_sglists(struct cipher_test_sglists *tsgls)
75762306a36Sopenharmony_ci{
75862306a36Sopenharmony_ci	if (tsgls) {
75962306a36Sopenharmony_ci		destroy_test_sglist(&tsgls->src);
76062306a36Sopenharmony_ci		destroy_test_sglist(&tsgls->dst);
76162306a36Sopenharmony_ci		kfree(tsgls);
76262306a36Sopenharmony_ci	}
76362306a36Sopenharmony_ci}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci/* Build the src and dst scatterlists for an skcipher or AEAD test */
76662306a36Sopenharmony_cistatic int build_cipher_test_sglists(struct cipher_test_sglists *tsgls,
76762306a36Sopenharmony_ci				     const struct testvec_config *cfg,
76862306a36Sopenharmony_ci				     unsigned int alignmask,
76962306a36Sopenharmony_ci				     unsigned int src_total_len,
77062306a36Sopenharmony_ci				     unsigned int dst_total_len,
77162306a36Sopenharmony_ci				     const struct kvec *inputs,
77262306a36Sopenharmony_ci				     unsigned int nr_inputs)
77362306a36Sopenharmony_ci{
77462306a36Sopenharmony_ci	struct iov_iter input;
77562306a36Sopenharmony_ci	int err;
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	iov_iter_kvec(&input, ITER_SOURCE, inputs, nr_inputs, src_total_len);
77862306a36Sopenharmony_ci	err = build_test_sglist(&tsgls->src, cfg->src_divs, alignmask,
77962306a36Sopenharmony_ci				cfg->inplace_mode != OUT_OF_PLACE ?
78062306a36Sopenharmony_ci					max(dst_total_len, src_total_len) :
78162306a36Sopenharmony_ci					src_total_len,
78262306a36Sopenharmony_ci				&input, NULL);
78362306a36Sopenharmony_ci	if (err)
78462306a36Sopenharmony_ci		return err;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	/*
78762306a36Sopenharmony_ci	 * In-place crypto operations can use the same scatterlist for both the
78862306a36Sopenharmony_ci	 * source and destination (req->src == req->dst), or can use separate
78962306a36Sopenharmony_ci	 * scatterlists (req->src != req->dst) which point to the same
79062306a36Sopenharmony_ci	 * underlying memory.  Make sure to test both cases.
79162306a36Sopenharmony_ci	 */
79262306a36Sopenharmony_ci	if (cfg->inplace_mode == INPLACE_ONE_SGLIST) {
79362306a36Sopenharmony_ci		tsgls->dst.sgl_ptr = tsgls->src.sgl;
79462306a36Sopenharmony_ci		tsgls->dst.nents = tsgls->src.nents;
79562306a36Sopenharmony_ci		return 0;
79662306a36Sopenharmony_ci	}
79762306a36Sopenharmony_ci	if (cfg->inplace_mode == INPLACE_TWO_SGLISTS) {
79862306a36Sopenharmony_ci		/*
79962306a36Sopenharmony_ci		 * For now we keep it simple and only test the case where the
80062306a36Sopenharmony_ci		 * two scatterlists have identical entries, rather than
80162306a36Sopenharmony_ci		 * different entries that split up the same memory differently.
80262306a36Sopenharmony_ci		 */
80362306a36Sopenharmony_ci		memcpy(tsgls->dst.sgl, tsgls->src.sgl,
80462306a36Sopenharmony_ci		       tsgls->src.nents * sizeof(tsgls->src.sgl[0]));
80562306a36Sopenharmony_ci		memcpy(tsgls->dst.sgl_saved, tsgls->src.sgl,
80662306a36Sopenharmony_ci		       tsgls->src.nents * sizeof(tsgls->src.sgl[0]));
80762306a36Sopenharmony_ci		tsgls->dst.sgl_ptr = tsgls->dst.sgl;
80862306a36Sopenharmony_ci		tsgls->dst.nents = tsgls->src.nents;
80962306a36Sopenharmony_ci		return 0;
81062306a36Sopenharmony_ci	}
81162306a36Sopenharmony_ci	/* Out of place */
81262306a36Sopenharmony_ci	return build_test_sglist(&tsgls->dst,
81362306a36Sopenharmony_ci				 cfg->dst_divs[0].proportion_of_total ?
81462306a36Sopenharmony_ci					cfg->dst_divs : cfg->src_divs,
81562306a36Sopenharmony_ci				 alignmask, dst_total_len, NULL, NULL);
81662306a36Sopenharmony_ci}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci/*
81962306a36Sopenharmony_ci * Support for testing passing a misaligned key to setkey():
82062306a36Sopenharmony_ci *
82162306a36Sopenharmony_ci * If cfg->key_offset is set, copy the key into a new buffer at that offset,
82262306a36Sopenharmony_ci * optionally adding alignmask.  Else, just use the key directly.
82362306a36Sopenharmony_ci */
82462306a36Sopenharmony_cistatic int prepare_keybuf(const u8 *key, unsigned int ksize,
82562306a36Sopenharmony_ci			  const struct testvec_config *cfg,
82662306a36Sopenharmony_ci			  unsigned int alignmask,
82762306a36Sopenharmony_ci			  const u8 **keybuf_ret, const u8 **keyptr_ret)
82862306a36Sopenharmony_ci{
82962306a36Sopenharmony_ci	unsigned int key_offset = cfg->key_offset;
83062306a36Sopenharmony_ci	u8 *keybuf = NULL, *keyptr = (u8 *)key;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	if (key_offset != 0) {
83362306a36Sopenharmony_ci		if (cfg->key_offset_relative_to_alignmask)
83462306a36Sopenharmony_ci			key_offset += alignmask;
83562306a36Sopenharmony_ci		keybuf = kmalloc(key_offset + ksize, GFP_KERNEL);
83662306a36Sopenharmony_ci		if (!keybuf)
83762306a36Sopenharmony_ci			return -ENOMEM;
83862306a36Sopenharmony_ci		keyptr = keybuf + key_offset;
83962306a36Sopenharmony_ci		memcpy(keyptr, key, ksize);
84062306a36Sopenharmony_ci	}
84162306a36Sopenharmony_ci	*keybuf_ret = keybuf;
84262306a36Sopenharmony_ci	*keyptr_ret = keyptr;
84362306a36Sopenharmony_ci	return 0;
84462306a36Sopenharmony_ci}
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci/* Like setkey_f(tfm, key, ksize), but sometimes misalign the key */
84762306a36Sopenharmony_ci#define do_setkey(setkey_f, tfm, key, ksize, cfg, alignmask)		\
84862306a36Sopenharmony_ci({									\
84962306a36Sopenharmony_ci	const u8 *keybuf, *keyptr;					\
85062306a36Sopenharmony_ci	int err;							\
85162306a36Sopenharmony_ci									\
85262306a36Sopenharmony_ci	err = prepare_keybuf((key), (ksize), (cfg), (alignmask),	\
85362306a36Sopenharmony_ci			     &keybuf, &keyptr);				\
85462306a36Sopenharmony_ci	if (err == 0) {							\
85562306a36Sopenharmony_ci		err = setkey_f((tfm), keyptr, (ksize));			\
85662306a36Sopenharmony_ci		kfree(keybuf);						\
85762306a36Sopenharmony_ci	}								\
85862306a36Sopenharmony_ci	err;								\
85962306a36Sopenharmony_ci})
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci/*
86462306a36Sopenharmony_ci * The fuzz tests use prandom instead of the normal Linux RNG since they don't
86562306a36Sopenharmony_ci * need cryptographically secure random numbers.  This greatly improves the
86662306a36Sopenharmony_ci * performance of these tests, especially if they are run before the Linux RNG
86762306a36Sopenharmony_ci * has been initialized or if they are run on a lockdep-enabled kernel.
86862306a36Sopenharmony_ci */
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_cistatic inline void init_rnd_state(struct rnd_state *rng)
87162306a36Sopenharmony_ci{
87262306a36Sopenharmony_ci	prandom_seed_state(rng, get_random_u64());
87362306a36Sopenharmony_ci}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_cistatic inline u8 prandom_u8(struct rnd_state *rng)
87662306a36Sopenharmony_ci{
87762306a36Sopenharmony_ci	return prandom_u32_state(rng);
87862306a36Sopenharmony_ci}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_cistatic inline u32 prandom_u32_below(struct rnd_state *rng, u32 ceil)
88162306a36Sopenharmony_ci{
88262306a36Sopenharmony_ci	/*
88362306a36Sopenharmony_ci	 * This is slightly biased for non-power-of-2 values of 'ceil', but this
88462306a36Sopenharmony_ci	 * isn't important here.
88562306a36Sopenharmony_ci	 */
88662306a36Sopenharmony_ci	return prandom_u32_state(rng) % ceil;
88762306a36Sopenharmony_ci}
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_cistatic inline bool prandom_bool(struct rnd_state *rng)
89062306a36Sopenharmony_ci{
89162306a36Sopenharmony_ci	return prandom_u32_below(rng, 2);
89262306a36Sopenharmony_ci}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_cistatic inline u32 prandom_u32_inclusive(struct rnd_state *rng,
89562306a36Sopenharmony_ci					u32 floor, u32 ceil)
89662306a36Sopenharmony_ci{
89762306a36Sopenharmony_ci	return floor + prandom_u32_below(rng, ceil - floor + 1);
89862306a36Sopenharmony_ci}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci/* Generate a random length in range [0, max_len], but prefer smaller values */
90162306a36Sopenharmony_cistatic unsigned int generate_random_length(struct rnd_state *rng,
90262306a36Sopenharmony_ci					   unsigned int max_len)
90362306a36Sopenharmony_ci{
90462306a36Sopenharmony_ci	unsigned int len = prandom_u32_below(rng, max_len + 1);
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	switch (prandom_u32_below(rng, 4)) {
90762306a36Sopenharmony_ci	case 0:
90862306a36Sopenharmony_ci		return len % 64;
90962306a36Sopenharmony_ci	case 1:
91062306a36Sopenharmony_ci		return len % 256;
91162306a36Sopenharmony_ci	case 2:
91262306a36Sopenharmony_ci		return len % 1024;
91362306a36Sopenharmony_ci	default:
91462306a36Sopenharmony_ci		return len;
91562306a36Sopenharmony_ci	}
91662306a36Sopenharmony_ci}
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci/* Flip a random bit in the given nonempty data buffer */
91962306a36Sopenharmony_cistatic void flip_random_bit(struct rnd_state *rng, u8 *buf, size_t size)
92062306a36Sopenharmony_ci{
92162306a36Sopenharmony_ci	size_t bitpos;
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci	bitpos = prandom_u32_below(rng, size * 8);
92462306a36Sopenharmony_ci	buf[bitpos / 8] ^= 1 << (bitpos % 8);
92562306a36Sopenharmony_ci}
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci/* Flip a random byte in the given nonempty data buffer */
92862306a36Sopenharmony_cistatic void flip_random_byte(struct rnd_state *rng, u8 *buf, size_t size)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	buf[prandom_u32_below(rng, size)] ^= 0xff;
93162306a36Sopenharmony_ci}
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci/* Sometimes make some random changes to the given nonempty data buffer */
93462306a36Sopenharmony_cistatic void mutate_buffer(struct rnd_state *rng, u8 *buf, size_t size)
93562306a36Sopenharmony_ci{
93662306a36Sopenharmony_ci	size_t num_flips;
93762306a36Sopenharmony_ci	size_t i;
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	/* Sometimes flip some bits */
94062306a36Sopenharmony_ci	if (prandom_u32_below(rng, 4) == 0) {
94162306a36Sopenharmony_ci		num_flips = min_t(size_t, 1 << prandom_u32_below(rng, 8),
94262306a36Sopenharmony_ci				  size * 8);
94362306a36Sopenharmony_ci		for (i = 0; i < num_flips; i++)
94462306a36Sopenharmony_ci			flip_random_bit(rng, buf, size);
94562306a36Sopenharmony_ci	}
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	/* Sometimes flip some bytes */
94862306a36Sopenharmony_ci	if (prandom_u32_below(rng, 4) == 0) {
94962306a36Sopenharmony_ci		num_flips = min_t(size_t, 1 << prandom_u32_below(rng, 8), size);
95062306a36Sopenharmony_ci		for (i = 0; i < num_flips; i++)
95162306a36Sopenharmony_ci			flip_random_byte(rng, buf, size);
95262306a36Sopenharmony_ci	}
95362306a36Sopenharmony_ci}
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci/* Randomly generate 'count' bytes, but sometimes make them "interesting" */
95662306a36Sopenharmony_cistatic void generate_random_bytes(struct rnd_state *rng, u8 *buf, size_t count)
95762306a36Sopenharmony_ci{
95862306a36Sopenharmony_ci	u8 b;
95962306a36Sopenharmony_ci	u8 increment;
96062306a36Sopenharmony_ci	size_t i;
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	if (count == 0)
96362306a36Sopenharmony_ci		return;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	switch (prandom_u32_below(rng, 8)) { /* Choose a generation strategy */
96662306a36Sopenharmony_ci	case 0:
96762306a36Sopenharmony_ci	case 1:
96862306a36Sopenharmony_ci		/* All the same byte, plus optional mutations */
96962306a36Sopenharmony_ci		switch (prandom_u32_below(rng, 4)) {
97062306a36Sopenharmony_ci		case 0:
97162306a36Sopenharmony_ci			b = 0x00;
97262306a36Sopenharmony_ci			break;
97362306a36Sopenharmony_ci		case 1:
97462306a36Sopenharmony_ci			b = 0xff;
97562306a36Sopenharmony_ci			break;
97662306a36Sopenharmony_ci		default:
97762306a36Sopenharmony_ci			b = prandom_u8(rng);
97862306a36Sopenharmony_ci			break;
97962306a36Sopenharmony_ci		}
98062306a36Sopenharmony_ci		memset(buf, b, count);
98162306a36Sopenharmony_ci		mutate_buffer(rng, buf, count);
98262306a36Sopenharmony_ci		break;
98362306a36Sopenharmony_ci	case 2:
98462306a36Sopenharmony_ci		/* Ascending or descending bytes, plus optional mutations */
98562306a36Sopenharmony_ci		increment = prandom_u8(rng);
98662306a36Sopenharmony_ci		b = prandom_u8(rng);
98762306a36Sopenharmony_ci		for (i = 0; i < count; i++, b += increment)
98862306a36Sopenharmony_ci			buf[i] = b;
98962306a36Sopenharmony_ci		mutate_buffer(rng, buf, count);
99062306a36Sopenharmony_ci		break;
99162306a36Sopenharmony_ci	default:
99262306a36Sopenharmony_ci		/* Fully random bytes */
99362306a36Sopenharmony_ci		prandom_bytes_state(rng, buf, count);
99462306a36Sopenharmony_ci	}
99562306a36Sopenharmony_ci}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_cistatic char *generate_random_sgl_divisions(struct rnd_state *rng,
99862306a36Sopenharmony_ci					   struct test_sg_division *divs,
99962306a36Sopenharmony_ci					   size_t max_divs, char *p, char *end,
100062306a36Sopenharmony_ci					   bool gen_flushes, u32 req_flags)
100162306a36Sopenharmony_ci{
100262306a36Sopenharmony_ci	struct test_sg_division *div = divs;
100362306a36Sopenharmony_ci	unsigned int remaining = TEST_SG_TOTAL;
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	do {
100662306a36Sopenharmony_ci		unsigned int this_len;
100762306a36Sopenharmony_ci		const char *flushtype_str;
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci		if (div == &divs[max_divs - 1] || prandom_bool(rng))
101062306a36Sopenharmony_ci			this_len = remaining;
101162306a36Sopenharmony_ci		else
101262306a36Sopenharmony_ci			this_len = prandom_u32_inclusive(rng, 1, remaining);
101362306a36Sopenharmony_ci		div->proportion_of_total = this_len;
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci		if (prandom_u32_below(rng, 4) == 0)
101662306a36Sopenharmony_ci			div->offset = prandom_u32_inclusive(rng,
101762306a36Sopenharmony_ci							    PAGE_SIZE - 128,
101862306a36Sopenharmony_ci							    PAGE_SIZE - 1);
101962306a36Sopenharmony_ci		else if (prandom_bool(rng))
102062306a36Sopenharmony_ci			div->offset = prandom_u32_below(rng, 32);
102162306a36Sopenharmony_ci		else
102262306a36Sopenharmony_ci			div->offset = prandom_u32_below(rng, PAGE_SIZE);
102362306a36Sopenharmony_ci		if (prandom_u32_below(rng, 8) == 0)
102462306a36Sopenharmony_ci			div->offset_relative_to_alignmask = true;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci		div->flush_type = FLUSH_TYPE_NONE;
102762306a36Sopenharmony_ci		if (gen_flushes) {
102862306a36Sopenharmony_ci			switch (prandom_u32_below(rng, 4)) {
102962306a36Sopenharmony_ci			case 0:
103062306a36Sopenharmony_ci				div->flush_type = FLUSH_TYPE_REIMPORT;
103162306a36Sopenharmony_ci				break;
103262306a36Sopenharmony_ci			case 1:
103362306a36Sopenharmony_ci				div->flush_type = FLUSH_TYPE_FLUSH;
103462306a36Sopenharmony_ci				break;
103562306a36Sopenharmony_ci			}
103662306a36Sopenharmony_ci		}
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci		if (div->flush_type != FLUSH_TYPE_NONE &&
103962306a36Sopenharmony_ci		    !(req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) &&
104062306a36Sopenharmony_ci		    prandom_bool(rng))
104162306a36Sopenharmony_ci			div->nosimd = true;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci		switch (div->flush_type) {
104462306a36Sopenharmony_ci		case FLUSH_TYPE_FLUSH:
104562306a36Sopenharmony_ci			if (div->nosimd)
104662306a36Sopenharmony_ci				flushtype_str = "<flush,nosimd>";
104762306a36Sopenharmony_ci			else
104862306a36Sopenharmony_ci				flushtype_str = "<flush>";
104962306a36Sopenharmony_ci			break;
105062306a36Sopenharmony_ci		case FLUSH_TYPE_REIMPORT:
105162306a36Sopenharmony_ci			if (div->nosimd)
105262306a36Sopenharmony_ci				flushtype_str = "<reimport,nosimd>";
105362306a36Sopenharmony_ci			else
105462306a36Sopenharmony_ci				flushtype_str = "<reimport>";
105562306a36Sopenharmony_ci			break;
105662306a36Sopenharmony_ci		default:
105762306a36Sopenharmony_ci			flushtype_str = "";
105862306a36Sopenharmony_ci			break;
105962306a36Sopenharmony_ci		}
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci		BUILD_BUG_ON(TEST_SG_TOTAL != 10000); /* for "%u.%u%%" */
106262306a36Sopenharmony_ci		p += scnprintf(p, end - p, "%s%u.%u%%@%s+%u%s", flushtype_str,
106362306a36Sopenharmony_ci			       this_len / 100, this_len % 100,
106462306a36Sopenharmony_ci			       div->offset_relative_to_alignmask ?
106562306a36Sopenharmony_ci					"alignmask" : "",
106662306a36Sopenharmony_ci			       div->offset, this_len == remaining ? "" : ", ");
106762306a36Sopenharmony_ci		remaining -= this_len;
106862306a36Sopenharmony_ci		div++;
106962306a36Sopenharmony_ci	} while (remaining);
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	return p;
107262306a36Sopenharmony_ci}
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci/* Generate a random testvec_config for fuzz testing */
107562306a36Sopenharmony_cistatic void generate_random_testvec_config(struct rnd_state *rng,
107662306a36Sopenharmony_ci					   struct testvec_config *cfg,
107762306a36Sopenharmony_ci					   char *name, size_t max_namelen)
107862306a36Sopenharmony_ci{
107962306a36Sopenharmony_ci	char *p = name;
108062306a36Sopenharmony_ci	char * const end = name + max_namelen;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	memset(cfg, 0, sizeof(*cfg));
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	cfg->name = name;
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	p += scnprintf(p, end - p, "random:");
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	switch (prandom_u32_below(rng, 4)) {
108962306a36Sopenharmony_ci	case 0:
109062306a36Sopenharmony_ci	case 1:
109162306a36Sopenharmony_ci		cfg->inplace_mode = OUT_OF_PLACE;
109262306a36Sopenharmony_ci		break;
109362306a36Sopenharmony_ci	case 2:
109462306a36Sopenharmony_ci		cfg->inplace_mode = INPLACE_ONE_SGLIST;
109562306a36Sopenharmony_ci		p += scnprintf(p, end - p, " inplace_one_sglist");
109662306a36Sopenharmony_ci		break;
109762306a36Sopenharmony_ci	default:
109862306a36Sopenharmony_ci		cfg->inplace_mode = INPLACE_TWO_SGLISTS;
109962306a36Sopenharmony_ci		p += scnprintf(p, end - p, " inplace_two_sglists");
110062306a36Sopenharmony_ci		break;
110162306a36Sopenharmony_ci	}
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	if (prandom_bool(rng)) {
110462306a36Sopenharmony_ci		cfg->req_flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
110562306a36Sopenharmony_ci		p += scnprintf(p, end - p, " may_sleep");
110662306a36Sopenharmony_ci	}
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	switch (prandom_u32_below(rng, 4)) {
110962306a36Sopenharmony_ci	case 0:
111062306a36Sopenharmony_ci		cfg->finalization_type = FINALIZATION_TYPE_FINAL;
111162306a36Sopenharmony_ci		p += scnprintf(p, end - p, " use_final");
111262306a36Sopenharmony_ci		break;
111362306a36Sopenharmony_ci	case 1:
111462306a36Sopenharmony_ci		cfg->finalization_type = FINALIZATION_TYPE_FINUP;
111562306a36Sopenharmony_ci		p += scnprintf(p, end - p, " use_finup");
111662306a36Sopenharmony_ci		break;
111762306a36Sopenharmony_ci	default:
111862306a36Sopenharmony_ci		cfg->finalization_type = FINALIZATION_TYPE_DIGEST;
111962306a36Sopenharmony_ci		p += scnprintf(p, end - p, " use_digest");
112062306a36Sopenharmony_ci		break;
112162306a36Sopenharmony_ci	}
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci	if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) && prandom_bool(rng)) {
112462306a36Sopenharmony_ci		cfg->nosimd = true;
112562306a36Sopenharmony_ci		p += scnprintf(p, end - p, " nosimd");
112662306a36Sopenharmony_ci	}
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	p += scnprintf(p, end - p, " src_divs=[");
112962306a36Sopenharmony_ci	p = generate_random_sgl_divisions(rng, cfg->src_divs,
113062306a36Sopenharmony_ci					  ARRAY_SIZE(cfg->src_divs), p, end,
113162306a36Sopenharmony_ci					  (cfg->finalization_type !=
113262306a36Sopenharmony_ci					   FINALIZATION_TYPE_DIGEST),
113362306a36Sopenharmony_ci					  cfg->req_flags);
113462306a36Sopenharmony_ci	p += scnprintf(p, end - p, "]");
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	if (cfg->inplace_mode == OUT_OF_PLACE && prandom_bool(rng)) {
113762306a36Sopenharmony_ci		p += scnprintf(p, end - p, " dst_divs=[");
113862306a36Sopenharmony_ci		p = generate_random_sgl_divisions(rng, cfg->dst_divs,
113962306a36Sopenharmony_ci						  ARRAY_SIZE(cfg->dst_divs),
114062306a36Sopenharmony_ci						  p, end, false,
114162306a36Sopenharmony_ci						  cfg->req_flags);
114262306a36Sopenharmony_ci		p += scnprintf(p, end - p, "]");
114362306a36Sopenharmony_ci	}
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	if (prandom_bool(rng)) {
114662306a36Sopenharmony_ci		cfg->iv_offset = prandom_u32_inclusive(rng, 1,
114762306a36Sopenharmony_ci						       MAX_ALGAPI_ALIGNMASK);
114862306a36Sopenharmony_ci		p += scnprintf(p, end - p, " iv_offset=%u", cfg->iv_offset);
114962306a36Sopenharmony_ci	}
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	if (prandom_bool(rng)) {
115262306a36Sopenharmony_ci		cfg->key_offset = prandom_u32_inclusive(rng, 1,
115362306a36Sopenharmony_ci							MAX_ALGAPI_ALIGNMASK);
115462306a36Sopenharmony_ci		p += scnprintf(p, end - p, " key_offset=%u", cfg->key_offset);
115562306a36Sopenharmony_ci	}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	WARN_ON_ONCE(!valid_testvec_config(cfg));
115862306a36Sopenharmony_ci}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_cistatic void crypto_disable_simd_for_test(void)
116162306a36Sopenharmony_ci{
116262306a36Sopenharmony_ci	migrate_disable();
116362306a36Sopenharmony_ci	__this_cpu_write(crypto_simd_disabled_for_test, true);
116462306a36Sopenharmony_ci}
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_cistatic void crypto_reenable_simd_for_test(void)
116762306a36Sopenharmony_ci{
116862306a36Sopenharmony_ci	__this_cpu_write(crypto_simd_disabled_for_test, false);
116962306a36Sopenharmony_ci	migrate_enable();
117062306a36Sopenharmony_ci}
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci/*
117362306a36Sopenharmony_ci * Given an algorithm name, build the name of the generic implementation of that
117462306a36Sopenharmony_ci * algorithm, assuming the usual naming convention.  Specifically, this appends
117562306a36Sopenharmony_ci * "-generic" to every part of the name that is not a template name.  Examples:
117662306a36Sopenharmony_ci *
117762306a36Sopenharmony_ci *	aes => aes-generic
117862306a36Sopenharmony_ci *	cbc(aes) => cbc(aes-generic)
117962306a36Sopenharmony_ci *	cts(cbc(aes)) => cts(cbc(aes-generic))
118062306a36Sopenharmony_ci *	rfc7539(chacha20,poly1305) => rfc7539(chacha20-generic,poly1305-generic)
118162306a36Sopenharmony_ci *
118262306a36Sopenharmony_ci * Return: 0 on success, or -ENAMETOOLONG if the generic name would be too long
118362306a36Sopenharmony_ci */
118462306a36Sopenharmony_cistatic int build_generic_driver_name(const char *algname,
118562306a36Sopenharmony_ci				     char driver_name[CRYPTO_MAX_ALG_NAME])
118662306a36Sopenharmony_ci{
118762306a36Sopenharmony_ci	const char *in = algname;
118862306a36Sopenharmony_ci	char *out = driver_name;
118962306a36Sopenharmony_ci	size_t len = strlen(algname);
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	if (len >= CRYPTO_MAX_ALG_NAME)
119262306a36Sopenharmony_ci		goto too_long;
119362306a36Sopenharmony_ci	do {
119462306a36Sopenharmony_ci		const char *in_saved = in;
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci		while (*in && *in != '(' && *in != ')' && *in != ',')
119762306a36Sopenharmony_ci			*out++ = *in++;
119862306a36Sopenharmony_ci		if (*in != '(' && in > in_saved) {
119962306a36Sopenharmony_ci			len += 8;
120062306a36Sopenharmony_ci			if (len >= CRYPTO_MAX_ALG_NAME)
120162306a36Sopenharmony_ci				goto too_long;
120262306a36Sopenharmony_ci			memcpy(out, "-generic", 8);
120362306a36Sopenharmony_ci			out += 8;
120462306a36Sopenharmony_ci		}
120562306a36Sopenharmony_ci	} while ((*out++ = *in++) != '\0');
120662306a36Sopenharmony_ci	return 0;
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_citoo_long:
120962306a36Sopenharmony_ci	pr_err("alg: generic driver name for \"%s\" would be too long\n",
121062306a36Sopenharmony_ci	       algname);
121162306a36Sopenharmony_ci	return -ENAMETOOLONG;
121262306a36Sopenharmony_ci}
121362306a36Sopenharmony_ci#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
121462306a36Sopenharmony_cistatic void crypto_disable_simd_for_test(void)
121562306a36Sopenharmony_ci{
121662306a36Sopenharmony_ci}
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_cistatic void crypto_reenable_simd_for_test(void)
121962306a36Sopenharmony_ci{
122062306a36Sopenharmony_ci}
122162306a36Sopenharmony_ci#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_cistatic int build_hash_sglist(struct test_sglist *tsgl,
122462306a36Sopenharmony_ci			     const struct hash_testvec *vec,
122562306a36Sopenharmony_ci			     const struct testvec_config *cfg,
122662306a36Sopenharmony_ci			     unsigned int alignmask,
122762306a36Sopenharmony_ci			     const struct test_sg_division *divs[XBUFSIZE])
122862306a36Sopenharmony_ci{
122962306a36Sopenharmony_ci	struct kvec kv;
123062306a36Sopenharmony_ci	struct iov_iter input;
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	kv.iov_base = (void *)vec->plaintext;
123362306a36Sopenharmony_ci	kv.iov_len = vec->psize;
123462306a36Sopenharmony_ci	iov_iter_kvec(&input, ITER_SOURCE, &kv, 1, vec->psize);
123562306a36Sopenharmony_ci	return build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize,
123662306a36Sopenharmony_ci				 &input, divs);
123762306a36Sopenharmony_ci}
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_cistatic int check_hash_result(const char *type,
124062306a36Sopenharmony_ci			     const u8 *result, unsigned int digestsize,
124162306a36Sopenharmony_ci			     const struct hash_testvec *vec,
124262306a36Sopenharmony_ci			     const char *vec_name,
124362306a36Sopenharmony_ci			     const char *driver,
124462306a36Sopenharmony_ci			     const struct testvec_config *cfg)
124562306a36Sopenharmony_ci{
124662306a36Sopenharmony_ci	if (memcmp(result, vec->digest, digestsize) != 0) {
124762306a36Sopenharmony_ci		pr_err("alg: %s: %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
124862306a36Sopenharmony_ci		       type, driver, vec_name, cfg->name);
124962306a36Sopenharmony_ci		return -EINVAL;
125062306a36Sopenharmony_ci	}
125162306a36Sopenharmony_ci	if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) {
125262306a36Sopenharmony_ci		pr_err("alg: %s: %s overran result buffer on test vector %s, cfg=\"%s\"\n",
125362306a36Sopenharmony_ci		       type, driver, vec_name, cfg->name);
125462306a36Sopenharmony_ci		return -EOVERFLOW;
125562306a36Sopenharmony_ci	}
125662306a36Sopenharmony_ci	return 0;
125762306a36Sopenharmony_ci}
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_cistatic inline int check_shash_op(const char *op, int err,
126062306a36Sopenharmony_ci				 const char *driver, const char *vec_name,
126162306a36Sopenharmony_ci				 const struct testvec_config *cfg)
126262306a36Sopenharmony_ci{
126362306a36Sopenharmony_ci	if (err)
126462306a36Sopenharmony_ci		pr_err("alg: shash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
126562306a36Sopenharmony_ci		       driver, op, err, vec_name, cfg->name);
126662306a36Sopenharmony_ci	return err;
126762306a36Sopenharmony_ci}
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci/* Test one hash test vector in one configuration, using the shash API */
127062306a36Sopenharmony_cistatic int test_shash_vec_cfg(const struct hash_testvec *vec,
127162306a36Sopenharmony_ci			      const char *vec_name,
127262306a36Sopenharmony_ci			      const struct testvec_config *cfg,
127362306a36Sopenharmony_ci			      struct shash_desc *desc,
127462306a36Sopenharmony_ci			      struct test_sglist *tsgl,
127562306a36Sopenharmony_ci			      u8 *hashstate)
127662306a36Sopenharmony_ci{
127762306a36Sopenharmony_ci	struct crypto_shash *tfm = desc->tfm;
127862306a36Sopenharmony_ci	const unsigned int alignmask = crypto_shash_alignmask(tfm);
127962306a36Sopenharmony_ci	const unsigned int digestsize = crypto_shash_digestsize(tfm);
128062306a36Sopenharmony_ci	const unsigned int statesize = crypto_shash_statesize(tfm);
128162306a36Sopenharmony_ci	const char *driver = crypto_shash_driver_name(tfm);
128262306a36Sopenharmony_ci	const struct test_sg_division *divs[XBUFSIZE];
128362306a36Sopenharmony_ci	unsigned int i;
128462306a36Sopenharmony_ci	u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN];
128562306a36Sopenharmony_ci	int err;
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	/* Set the key, if specified */
128862306a36Sopenharmony_ci	if (vec->ksize) {
128962306a36Sopenharmony_ci		err = do_setkey(crypto_shash_setkey, tfm, vec->key, vec->ksize,
129062306a36Sopenharmony_ci				cfg, alignmask);
129162306a36Sopenharmony_ci		if (err) {
129262306a36Sopenharmony_ci			if (err == vec->setkey_error)
129362306a36Sopenharmony_ci				return 0;
129462306a36Sopenharmony_ci			pr_err("alg: shash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
129562306a36Sopenharmony_ci			       driver, vec_name, vec->setkey_error, err,
129662306a36Sopenharmony_ci			       crypto_shash_get_flags(tfm));
129762306a36Sopenharmony_ci			return err;
129862306a36Sopenharmony_ci		}
129962306a36Sopenharmony_ci		if (vec->setkey_error) {
130062306a36Sopenharmony_ci			pr_err("alg: shash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
130162306a36Sopenharmony_ci			       driver, vec_name, vec->setkey_error);
130262306a36Sopenharmony_ci			return -EINVAL;
130362306a36Sopenharmony_ci		}
130462306a36Sopenharmony_ci	}
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	/* Build the scatterlist for the source data */
130762306a36Sopenharmony_ci	err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
130862306a36Sopenharmony_ci	if (err) {
130962306a36Sopenharmony_ci		pr_err("alg: shash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
131062306a36Sopenharmony_ci		       driver, vec_name, cfg->name);
131162306a36Sopenharmony_ci		return err;
131262306a36Sopenharmony_ci	}
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	/* Do the actual hashing */
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm));
131762306a36Sopenharmony_ci	testmgr_poison(result, digestsize + TESTMGR_POISON_LEN);
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST ||
132062306a36Sopenharmony_ci	    vec->digest_error) {
132162306a36Sopenharmony_ci		/* Just using digest() */
132262306a36Sopenharmony_ci		if (tsgl->nents != 1)
132362306a36Sopenharmony_ci			return 0;
132462306a36Sopenharmony_ci		if (cfg->nosimd)
132562306a36Sopenharmony_ci			crypto_disable_simd_for_test();
132662306a36Sopenharmony_ci		err = crypto_shash_digest(desc, sg_virt(&tsgl->sgl[0]),
132762306a36Sopenharmony_ci					  tsgl->sgl[0].length, result);
132862306a36Sopenharmony_ci		if (cfg->nosimd)
132962306a36Sopenharmony_ci			crypto_reenable_simd_for_test();
133062306a36Sopenharmony_ci		if (err) {
133162306a36Sopenharmony_ci			if (err == vec->digest_error)
133262306a36Sopenharmony_ci				return 0;
133362306a36Sopenharmony_ci			pr_err("alg: shash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
133462306a36Sopenharmony_ci			       driver, vec_name, vec->digest_error, err,
133562306a36Sopenharmony_ci			       cfg->name);
133662306a36Sopenharmony_ci			return err;
133762306a36Sopenharmony_ci		}
133862306a36Sopenharmony_ci		if (vec->digest_error) {
133962306a36Sopenharmony_ci			pr_err("alg: shash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
134062306a36Sopenharmony_ci			       driver, vec_name, vec->digest_error, cfg->name);
134162306a36Sopenharmony_ci			return -EINVAL;
134262306a36Sopenharmony_ci		}
134362306a36Sopenharmony_ci		goto result_ready;
134462306a36Sopenharmony_ci	}
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	/* Using init(), zero or more update(), then final() or finup() */
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	if (cfg->nosimd)
134962306a36Sopenharmony_ci		crypto_disable_simd_for_test();
135062306a36Sopenharmony_ci	err = crypto_shash_init(desc);
135162306a36Sopenharmony_ci	if (cfg->nosimd)
135262306a36Sopenharmony_ci		crypto_reenable_simd_for_test();
135362306a36Sopenharmony_ci	err = check_shash_op("init", err, driver, vec_name, cfg);
135462306a36Sopenharmony_ci	if (err)
135562306a36Sopenharmony_ci		return err;
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	for (i = 0; i < tsgl->nents; i++) {
135862306a36Sopenharmony_ci		if (i + 1 == tsgl->nents &&
135962306a36Sopenharmony_ci		    cfg->finalization_type == FINALIZATION_TYPE_FINUP) {
136062306a36Sopenharmony_ci			if (divs[i]->nosimd)
136162306a36Sopenharmony_ci				crypto_disable_simd_for_test();
136262306a36Sopenharmony_ci			err = crypto_shash_finup(desc, sg_virt(&tsgl->sgl[i]),
136362306a36Sopenharmony_ci						 tsgl->sgl[i].length, result);
136462306a36Sopenharmony_ci			if (divs[i]->nosimd)
136562306a36Sopenharmony_ci				crypto_reenable_simd_for_test();
136662306a36Sopenharmony_ci			err = check_shash_op("finup", err, driver, vec_name,
136762306a36Sopenharmony_ci					     cfg);
136862306a36Sopenharmony_ci			if (err)
136962306a36Sopenharmony_ci				return err;
137062306a36Sopenharmony_ci			goto result_ready;
137162306a36Sopenharmony_ci		}
137262306a36Sopenharmony_ci		if (divs[i]->nosimd)
137362306a36Sopenharmony_ci			crypto_disable_simd_for_test();
137462306a36Sopenharmony_ci		err = crypto_shash_update(desc, sg_virt(&tsgl->sgl[i]),
137562306a36Sopenharmony_ci					  tsgl->sgl[i].length);
137662306a36Sopenharmony_ci		if (divs[i]->nosimd)
137762306a36Sopenharmony_ci			crypto_reenable_simd_for_test();
137862306a36Sopenharmony_ci		err = check_shash_op("update", err, driver, vec_name, cfg);
137962306a36Sopenharmony_ci		if (err)
138062306a36Sopenharmony_ci			return err;
138162306a36Sopenharmony_ci		if (divs[i]->flush_type == FLUSH_TYPE_REIMPORT) {
138262306a36Sopenharmony_ci			/* Test ->export() and ->import() */
138362306a36Sopenharmony_ci			testmgr_poison(hashstate + statesize,
138462306a36Sopenharmony_ci				       TESTMGR_POISON_LEN);
138562306a36Sopenharmony_ci			err = crypto_shash_export(desc, hashstate);
138662306a36Sopenharmony_ci			err = check_shash_op("export", err, driver, vec_name,
138762306a36Sopenharmony_ci					     cfg);
138862306a36Sopenharmony_ci			if (err)
138962306a36Sopenharmony_ci				return err;
139062306a36Sopenharmony_ci			if (!testmgr_is_poison(hashstate + statesize,
139162306a36Sopenharmony_ci					       TESTMGR_POISON_LEN)) {
139262306a36Sopenharmony_ci				pr_err("alg: shash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
139362306a36Sopenharmony_ci				       driver, vec_name, cfg->name);
139462306a36Sopenharmony_ci				return -EOVERFLOW;
139562306a36Sopenharmony_ci			}
139662306a36Sopenharmony_ci			testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm));
139762306a36Sopenharmony_ci			err = crypto_shash_import(desc, hashstate);
139862306a36Sopenharmony_ci			err = check_shash_op("import", err, driver, vec_name,
139962306a36Sopenharmony_ci					     cfg);
140062306a36Sopenharmony_ci			if (err)
140162306a36Sopenharmony_ci				return err;
140262306a36Sopenharmony_ci		}
140362306a36Sopenharmony_ci	}
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	if (cfg->nosimd)
140662306a36Sopenharmony_ci		crypto_disable_simd_for_test();
140762306a36Sopenharmony_ci	err = crypto_shash_final(desc, result);
140862306a36Sopenharmony_ci	if (cfg->nosimd)
140962306a36Sopenharmony_ci		crypto_reenable_simd_for_test();
141062306a36Sopenharmony_ci	err = check_shash_op("final", err, driver, vec_name, cfg);
141162306a36Sopenharmony_ci	if (err)
141262306a36Sopenharmony_ci		return err;
141362306a36Sopenharmony_ciresult_ready:
141462306a36Sopenharmony_ci	return check_hash_result("shash", result, digestsize, vec, vec_name,
141562306a36Sopenharmony_ci				 driver, cfg);
141662306a36Sopenharmony_ci}
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_cistatic int do_ahash_op(int (*op)(struct ahash_request *req),
141962306a36Sopenharmony_ci		       struct ahash_request *req,
142062306a36Sopenharmony_ci		       struct crypto_wait *wait, bool nosimd)
142162306a36Sopenharmony_ci{
142262306a36Sopenharmony_ci	int err;
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci	if (nosimd)
142562306a36Sopenharmony_ci		crypto_disable_simd_for_test();
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	err = op(req);
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	if (nosimd)
143062306a36Sopenharmony_ci		crypto_reenable_simd_for_test();
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci	return crypto_wait_req(err, wait);
143362306a36Sopenharmony_ci}
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_cistatic int check_nonfinal_ahash_op(const char *op, int err,
143662306a36Sopenharmony_ci				   u8 *result, unsigned int digestsize,
143762306a36Sopenharmony_ci				   const char *driver, const char *vec_name,
143862306a36Sopenharmony_ci				   const struct testvec_config *cfg)
143962306a36Sopenharmony_ci{
144062306a36Sopenharmony_ci	if (err) {
144162306a36Sopenharmony_ci		pr_err("alg: ahash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
144262306a36Sopenharmony_ci		       driver, op, err, vec_name, cfg->name);
144362306a36Sopenharmony_ci		return err;
144462306a36Sopenharmony_ci	}
144562306a36Sopenharmony_ci	if (!testmgr_is_poison(result, digestsize)) {
144662306a36Sopenharmony_ci		pr_err("alg: ahash: %s %s() used result buffer on test vector %s, cfg=\"%s\"\n",
144762306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
144862306a36Sopenharmony_ci		return -EINVAL;
144962306a36Sopenharmony_ci	}
145062306a36Sopenharmony_ci	return 0;
145162306a36Sopenharmony_ci}
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci/* Test one hash test vector in one configuration, using the ahash API */
145462306a36Sopenharmony_cistatic int test_ahash_vec_cfg(const struct hash_testvec *vec,
145562306a36Sopenharmony_ci			      const char *vec_name,
145662306a36Sopenharmony_ci			      const struct testvec_config *cfg,
145762306a36Sopenharmony_ci			      struct ahash_request *req,
145862306a36Sopenharmony_ci			      struct test_sglist *tsgl,
145962306a36Sopenharmony_ci			      u8 *hashstate)
146062306a36Sopenharmony_ci{
146162306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
146262306a36Sopenharmony_ci	const unsigned int alignmask = crypto_ahash_alignmask(tfm);
146362306a36Sopenharmony_ci	const unsigned int digestsize = crypto_ahash_digestsize(tfm);
146462306a36Sopenharmony_ci	const unsigned int statesize = crypto_ahash_statesize(tfm);
146562306a36Sopenharmony_ci	const char *driver = crypto_ahash_driver_name(tfm);
146662306a36Sopenharmony_ci	const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags;
146762306a36Sopenharmony_ci	const struct test_sg_division *divs[XBUFSIZE];
146862306a36Sopenharmony_ci	DECLARE_CRYPTO_WAIT(wait);
146962306a36Sopenharmony_ci	unsigned int i;
147062306a36Sopenharmony_ci	struct scatterlist *pending_sgl;
147162306a36Sopenharmony_ci	unsigned int pending_len;
147262306a36Sopenharmony_ci	u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN];
147362306a36Sopenharmony_ci	int err;
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci	/* Set the key, if specified */
147662306a36Sopenharmony_ci	if (vec->ksize) {
147762306a36Sopenharmony_ci		err = do_setkey(crypto_ahash_setkey, tfm, vec->key, vec->ksize,
147862306a36Sopenharmony_ci				cfg, alignmask);
147962306a36Sopenharmony_ci		if (err) {
148062306a36Sopenharmony_ci			if (err == vec->setkey_error)
148162306a36Sopenharmony_ci				return 0;
148262306a36Sopenharmony_ci			pr_err("alg: ahash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
148362306a36Sopenharmony_ci			       driver, vec_name, vec->setkey_error, err,
148462306a36Sopenharmony_ci			       crypto_ahash_get_flags(tfm));
148562306a36Sopenharmony_ci			return err;
148662306a36Sopenharmony_ci		}
148762306a36Sopenharmony_ci		if (vec->setkey_error) {
148862306a36Sopenharmony_ci			pr_err("alg: ahash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
148962306a36Sopenharmony_ci			       driver, vec_name, vec->setkey_error);
149062306a36Sopenharmony_ci			return -EINVAL;
149162306a36Sopenharmony_ci		}
149262306a36Sopenharmony_ci	}
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	/* Build the scatterlist for the source data */
149562306a36Sopenharmony_ci	err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
149662306a36Sopenharmony_ci	if (err) {
149762306a36Sopenharmony_ci		pr_err("alg: ahash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
149862306a36Sopenharmony_ci		       driver, vec_name, cfg->name);
149962306a36Sopenharmony_ci		return err;
150062306a36Sopenharmony_ci	}
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	/* Do the actual hashing */
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci	testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
150562306a36Sopenharmony_ci	testmgr_poison(result, digestsize + TESTMGR_POISON_LEN);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST ||
150862306a36Sopenharmony_ci	    vec->digest_error) {
150962306a36Sopenharmony_ci		/* Just using digest() */
151062306a36Sopenharmony_ci		ahash_request_set_callback(req, req_flags, crypto_req_done,
151162306a36Sopenharmony_ci					   &wait);
151262306a36Sopenharmony_ci		ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize);
151362306a36Sopenharmony_ci		err = do_ahash_op(crypto_ahash_digest, req, &wait, cfg->nosimd);
151462306a36Sopenharmony_ci		if (err) {
151562306a36Sopenharmony_ci			if (err == vec->digest_error)
151662306a36Sopenharmony_ci				return 0;
151762306a36Sopenharmony_ci			pr_err("alg: ahash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
151862306a36Sopenharmony_ci			       driver, vec_name, vec->digest_error, err,
151962306a36Sopenharmony_ci			       cfg->name);
152062306a36Sopenharmony_ci			return err;
152162306a36Sopenharmony_ci		}
152262306a36Sopenharmony_ci		if (vec->digest_error) {
152362306a36Sopenharmony_ci			pr_err("alg: ahash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
152462306a36Sopenharmony_ci			       driver, vec_name, vec->digest_error, cfg->name);
152562306a36Sopenharmony_ci			return -EINVAL;
152662306a36Sopenharmony_ci		}
152762306a36Sopenharmony_ci		goto result_ready;
152862306a36Sopenharmony_ci	}
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	/* Using init(), zero or more update(), then final() or finup() */
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	ahash_request_set_callback(req, req_flags, crypto_req_done, &wait);
153362306a36Sopenharmony_ci	ahash_request_set_crypt(req, NULL, result, 0);
153462306a36Sopenharmony_ci	err = do_ahash_op(crypto_ahash_init, req, &wait, cfg->nosimd);
153562306a36Sopenharmony_ci	err = check_nonfinal_ahash_op("init", err, result, digestsize,
153662306a36Sopenharmony_ci				      driver, vec_name, cfg);
153762306a36Sopenharmony_ci	if (err)
153862306a36Sopenharmony_ci		return err;
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	pending_sgl = NULL;
154162306a36Sopenharmony_ci	pending_len = 0;
154262306a36Sopenharmony_ci	for (i = 0; i < tsgl->nents; i++) {
154362306a36Sopenharmony_ci		if (divs[i]->flush_type != FLUSH_TYPE_NONE &&
154462306a36Sopenharmony_ci		    pending_sgl != NULL) {
154562306a36Sopenharmony_ci			/* update() with the pending data */
154662306a36Sopenharmony_ci			ahash_request_set_callback(req, req_flags,
154762306a36Sopenharmony_ci						   crypto_req_done, &wait);
154862306a36Sopenharmony_ci			ahash_request_set_crypt(req, pending_sgl, result,
154962306a36Sopenharmony_ci						pending_len);
155062306a36Sopenharmony_ci			err = do_ahash_op(crypto_ahash_update, req, &wait,
155162306a36Sopenharmony_ci					  divs[i]->nosimd);
155262306a36Sopenharmony_ci			err = check_nonfinal_ahash_op("update", err,
155362306a36Sopenharmony_ci						      result, digestsize,
155462306a36Sopenharmony_ci						      driver, vec_name, cfg);
155562306a36Sopenharmony_ci			if (err)
155662306a36Sopenharmony_ci				return err;
155762306a36Sopenharmony_ci			pending_sgl = NULL;
155862306a36Sopenharmony_ci			pending_len = 0;
155962306a36Sopenharmony_ci		}
156062306a36Sopenharmony_ci		if (divs[i]->flush_type == FLUSH_TYPE_REIMPORT) {
156162306a36Sopenharmony_ci			/* Test ->export() and ->import() */
156262306a36Sopenharmony_ci			testmgr_poison(hashstate + statesize,
156362306a36Sopenharmony_ci				       TESTMGR_POISON_LEN);
156462306a36Sopenharmony_ci			err = crypto_ahash_export(req, hashstate);
156562306a36Sopenharmony_ci			err = check_nonfinal_ahash_op("export", err,
156662306a36Sopenharmony_ci						      result, digestsize,
156762306a36Sopenharmony_ci						      driver, vec_name, cfg);
156862306a36Sopenharmony_ci			if (err)
156962306a36Sopenharmony_ci				return err;
157062306a36Sopenharmony_ci			if (!testmgr_is_poison(hashstate + statesize,
157162306a36Sopenharmony_ci					       TESTMGR_POISON_LEN)) {
157262306a36Sopenharmony_ci				pr_err("alg: ahash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
157362306a36Sopenharmony_ci				       driver, vec_name, cfg->name);
157462306a36Sopenharmony_ci				return -EOVERFLOW;
157562306a36Sopenharmony_ci			}
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_ci			testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
157862306a36Sopenharmony_ci			err = crypto_ahash_import(req, hashstate);
157962306a36Sopenharmony_ci			err = check_nonfinal_ahash_op("import", err,
158062306a36Sopenharmony_ci						      result, digestsize,
158162306a36Sopenharmony_ci						      driver, vec_name, cfg);
158262306a36Sopenharmony_ci			if (err)
158362306a36Sopenharmony_ci				return err;
158462306a36Sopenharmony_ci		}
158562306a36Sopenharmony_ci		if (pending_sgl == NULL)
158662306a36Sopenharmony_ci			pending_sgl = &tsgl->sgl[i];
158762306a36Sopenharmony_ci		pending_len += tsgl->sgl[i].length;
158862306a36Sopenharmony_ci	}
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci	ahash_request_set_callback(req, req_flags, crypto_req_done, &wait);
159162306a36Sopenharmony_ci	ahash_request_set_crypt(req, pending_sgl, result, pending_len);
159262306a36Sopenharmony_ci	if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) {
159362306a36Sopenharmony_ci		/* finish with update() and final() */
159462306a36Sopenharmony_ci		err = do_ahash_op(crypto_ahash_update, req, &wait, cfg->nosimd);
159562306a36Sopenharmony_ci		err = check_nonfinal_ahash_op("update", err, result, digestsize,
159662306a36Sopenharmony_ci					      driver, vec_name, cfg);
159762306a36Sopenharmony_ci		if (err)
159862306a36Sopenharmony_ci			return err;
159962306a36Sopenharmony_ci		err = do_ahash_op(crypto_ahash_final, req, &wait, cfg->nosimd);
160062306a36Sopenharmony_ci		if (err) {
160162306a36Sopenharmony_ci			pr_err("alg: ahash: %s final() failed with err %d on test vector %s, cfg=\"%s\"\n",
160262306a36Sopenharmony_ci			       driver, err, vec_name, cfg->name);
160362306a36Sopenharmony_ci			return err;
160462306a36Sopenharmony_ci		}
160562306a36Sopenharmony_ci	} else {
160662306a36Sopenharmony_ci		/* finish with finup() */
160762306a36Sopenharmony_ci		err = do_ahash_op(crypto_ahash_finup, req, &wait, cfg->nosimd);
160862306a36Sopenharmony_ci		if (err) {
160962306a36Sopenharmony_ci			pr_err("alg: ahash: %s finup() failed with err %d on test vector %s, cfg=\"%s\"\n",
161062306a36Sopenharmony_ci			       driver, err, vec_name, cfg->name);
161162306a36Sopenharmony_ci			return err;
161262306a36Sopenharmony_ci		}
161362306a36Sopenharmony_ci	}
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ciresult_ready:
161662306a36Sopenharmony_ci	return check_hash_result("ahash", result, digestsize, vec, vec_name,
161762306a36Sopenharmony_ci				 driver, cfg);
161862306a36Sopenharmony_ci}
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_cistatic int test_hash_vec_cfg(const struct hash_testvec *vec,
162162306a36Sopenharmony_ci			     const char *vec_name,
162262306a36Sopenharmony_ci			     const struct testvec_config *cfg,
162362306a36Sopenharmony_ci			     struct ahash_request *req,
162462306a36Sopenharmony_ci			     struct shash_desc *desc,
162562306a36Sopenharmony_ci			     struct test_sglist *tsgl,
162662306a36Sopenharmony_ci			     u8 *hashstate)
162762306a36Sopenharmony_ci{
162862306a36Sopenharmony_ci	int err;
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci	/*
163162306a36Sopenharmony_ci	 * For algorithms implemented as "shash", most bugs will be detected by
163262306a36Sopenharmony_ci	 * both the shash and ahash tests.  Test the shash API first so that the
163362306a36Sopenharmony_ci	 * failures involve less indirection, so are easier to debug.
163462306a36Sopenharmony_ci	 */
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	if (desc) {
163762306a36Sopenharmony_ci		err = test_shash_vec_cfg(vec, vec_name, cfg, desc, tsgl,
163862306a36Sopenharmony_ci					 hashstate);
163962306a36Sopenharmony_ci		if (err)
164062306a36Sopenharmony_ci			return err;
164162306a36Sopenharmony_ci	}
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	return test_ahash_vec_cfg(vec, vec_name, cfg, req, tsgl, hashstate);
164462306a36Sopenharmony_ci}
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_cistatic int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num,
164762306a36Sopenharmony_ci			 struct ahash_request *req, struct shash_desc *desc,
164862306a36Sopenharmony_ci			 struct test_sglist *tsgl, u8 *hashstate)
164962306a36Sopenharmony_ci{
165062306a36Sopenharmony_ci	char vec_name[16];
165162306a36Sopenharmony_ci	unsigned int i;
165262306a36Sopenharmony_ci	int err;
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	sprintf(vec_name, "%u", vec_num);
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) {
165762306a36Sopenharmony_ci		err = test_hash_vec_cfg(vec, vec_name,
165862306a36Sopenharmony_ci					&default_hash_testvec_configs[i],
165962306a36Sopenharmony_ci					req, desc, tsgl, hashstate);
166062306a36Sopenharmony_ci		if (err)
166162306a36Sopenharmony_ci			return err;
166262306a36Sopenharmony_ci	}
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
166562306a36Sopenharmony_ci	if (!noextratests) {
166662306a36Sopenharmony_ci		struct rnd_state rng;
166762306a36Sopenharmony_ci		struct testvec_config cfg;
166862306a36Sopenharmony_ci		char cfgname[TESTVEC_CONFIG_NAMELEN];
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci		init_rnd_state(&rng);
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci		for (i = 0; i < fuzz_iterations; i++) {
167362306a36Sopenharmony_ci			generate_random_testvec_config(&rng, &cfg, cfgname,
167462306a36Sopenharmony_ci						       sizeof(cfgname));
167562306a36Sopenharmony_ci			err = test_hash_vec_cfg(vec, vec_name, &cfg,
167662306a36Sopenharmony_ci						req, desc, tsgl, hashstate);
167762306a36Sopenharmony_ci			if (err)
167862306a36Sopenharmony_ci				return err;
167962306a36Sopenharmony_ci			cond_resched();
168062306a36Sopenharmony_ci		}
168162306a36Sopenharmony_ci	}
168262306a36Sopenharmony_ci#endif
168362306a36Sopenharmony_ci	return 0;
168462306a36Sopenharmony_ci}
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
168762306a36Sopenharmony_ci/*
168862306a36Sopenharmony_ci * Generate a hash test vector from the given implementation.
168962306a36Sopenharmony_ci * Assumes the buffers in 'vec' were already allocated.
169062306a36Sopenharmony_ci */
169162306a36Sopenharmony_cistatic void generate_random_hash_testvec(struct rnd_state *rng,
169262306a36Sopenharmony_ci					 struct shash_desc *desc,
169362306a36Sopenharmony_ci					 struct hash_testvec *vec,
169462306a36Sopenharmony_ci					 unsigned int maxkeysize,
169562306a36Sopenharmony_ci					 unsigned int maxdatasize,
169662306a36Sopenharmony_ci					 char *name, size_t max_namelen)
169762306a36Sopenharmony_ci{
169862306a36Sopenharmony_ci	/* Data */
169962306a36Sopenharmony_ci	vec->psize = generate_random_length(rng, maxdatasize);
170062306a36Sopenharmony_ci	generate_random_bytes(rng, (u8 *)vec->plaintext, vec->psize);
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci	/*
170362306a36Sopenharmony_ci	 * Key: length in range [1, maxkeysize], but usually choose maxkeysize.
170462306a36Sopenharmony_ci	 * If algorithm is unkeyed, then maxkeysize == 0 and set ksize = 0.
170562306a36Sopenharmony_ci	 */
170662306a36Sopenharmony_ci	vec->setkey_error = 0;
170762306a36Sopenharmony_ci	vec->ksize = 0;
170862306a36Sopenharmony_ci	if (maxkeysize) {
170962306a36Sopenharmony_ci		vec->ksize = maxkeysize;
171062306a36Sopenharmony_ci		if (prandom_u32_below(rng, 4) == 0)
171162306a36Sopenharmony_ci			vec->ksize = prandom_u32_inclusive(rng, 1, maxkeysize);
171262306a36Sopenharmony_ci		generate_random_bytes(rng, (u8 *)vec->key, vec->ksize);
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci		vec->setkey_error = crypto_shash_setkey(desc->tfm, vec->key,
171562306a36Sopenharmony_ci							vec->ksize);
171662306a36Sopenharmony_ci		/* If the key couldn't be set, no need to continue to digest. */
171762306a36Sopenharmony_ci		if (vec->setkey_error)
171862306a36Sopenharmony_ci			goto done;
171962306a36Sopenharmony_ci	}
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	/* Digest */
172262306a36Sopenharmony_ci	vec->digest_error = crypto_shash_digest(desc, vec->plaintext,
172362306a36Sopenharmony_ci						vec->psize, (u8 *)vec->digest);
172462306a36Sopenharmony_cidone:
172562306a36Sopenharmony_ci	snprintf(name, max_namelen, "\"random: psize=%u ksize=%u\"",
172662306a36Sopenharmony_ci		 vec->psize, vec->ksize);
172762306a36Sopenharmony_ci}
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci/*
173062306a36Sopenharmony_ci * Test the hash algorithm represented by @req against the corresponding generic
173162306a36Sopenharmony_ci * implementation, if one is available.
173262306a36Sopenharmony_ci */
173362306a36Sopenharmony_cistatic int test_hash_vs_generic_impl(const char *generic_driver,
173462306a36Sopenharmony_ci				     unsigned int maxkeysize,
173562306a36Sopenharmony_ci				     struct ahash_request *req,
173662306a36Sopenharmony_ci				     struct shash_desc *desc,
173762306a36Sopenharmony_ci				     struct test_sglist *tsgl,
173862306a36Sopenharmony_ci				     u8 *hashstate)
173962306a36Sopenharmony_ci{
174062306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
174162306a36Sopenharmony_ci	const unsigned int digestsize = crypto_ahash_digestsize(tfm);
174262306a36Sopenharmony_ci	const unsigned int blocksize = crypto_ahash_blocksize(tfm);
174362306a36Sopenharmony_ci	const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
174462306a36Sopenharmony_ci	const char *algname = crypto_hash_alg_common(tfm)->base.cra_name;
174562306a36Sopenharmony_ci	const char *driver = crypto_ahash_driver_name(tfm);
174662306a36Sopenharmony_ci	struct rnd_state rng;
174762306a36Sopenharmony_ci	char _generic_driver[CRYPTO_MAX_ALG_NAME];
174862306a36Sopenharmony_ci	struct crypto_shash *generic_tfm = NULL;
174962306a36Sopenharmony_ci	struct shash_desc *generic_desc = NULL;
175062306a36Sopenharmony_ci	unsigned int i;
175162306a36Sopenharmony_ci	struct hash_testvec vec = { 0 };
175262306a36Sopenharmony_ci	char vec_name[64];
175362306a36Sopenharmony_ci	struct testvec_config *cfg;
175462306a36Sopenharmony_ci	char cfgname[TESTVEC_CONFIG_NAMELEN];
175562306a36Sopenharmony_ci	int err;
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	if (noextratests)
175862306a36Sopenharmony_ci		return 0;
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	init_rnd_state(&rng);
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci	if (!generic_driver) { /* Use default naming convention? */
176362306a36Sopenharmony_ci		err = build_generic_driver_name(algname, _generic_driver);
176462306a36Sopenharmony_ci		if (err)
176562306a36Sopenharmony_ci			return err;
176662306a36Sopenharmony_ci		generic_driver = _generic_driver;
176762306a36Sopenharmony_ci	}
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci	if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */
177062306a36Sopenharmony_ci		return 0;
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci	generic_tfm = crypto_alloc_shash(generic_driver, 0, 0);
177362306a36Sopenharmony_ci	if (IS_ERR(generic_tfm)) {
177462306a36Sopenharmony_ci		err = PTR_ERR(generic_tfm);
177562306a36Sopenharmony_ci		if (err == -ENOENT) {
177662306a36Sopenharmony_ci			pr_warn("alg: hash: skipping comparison tests for %s because %s is unavailable\n",
177762306a36Sopenharmony_ci				driver, generic_driver);
177862306a36Sopenharmony_ci			return 0;
177962306a36Sopenharmony_ci		}
178062306a36Sopenharmony_ci		pr_err("alg: hash: error allocating %s (generic impl of %s): %d\n",
178162306a36Sopenharmony_ci		       generic_driver, algname, err);
178262306a36Sopenharmony_ci		return err;
178362306a36Sopenharmony_ci	}
178462306a36Sopenharmony_ci
178562306a36Sopenharmony_ci	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
178662306a36Sopenharmony_ci	if (!cfg) {
178762306a36Sopenharmony_ci		err = -ENOMEM;
178862306a36Sopenharmony_ci		goto out;
178962306a36Sopenharmony_ci	}
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_ci	generic_desc = kzalloc(sizeof(*desc) +
179262306a36Sopenharmony_ci			       crypto_shash_descsize(generic_tfm), GFP_KERNEL);
179362306a36Sopenharmony_ci	if (!generic_desc) {
179462306a36Sopenharmony_ci		err = -ENOMEM;
179562306a36Sopenharmony_ci		goto out;
179662306a36Sopenharmony_ci	}
179762306a36Sopenharmony_ci	generic_desc->tfm = generic_tfm;
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci	/* Check the algorithm properties for consistency. */
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_ci	if (digestsize != crypto_shash_digestsize(generic_tfm)) {
180262306a36Sopenharmony_ci		pr_err("alg: hash: digestsize for %s (%u) doesn't match generic impl (%u)\n",
180362306a36Sopenharmony_ci		       driver, digestsize,
180462306a36Sopenharmony_ci		       crypto_shash_digestsize(generic_tfm));
180562306a36Sopenharmony_ci		err = -EINVAL;
180662306a36Sopenharmony_ci		goto out;
180762306a36Sopenharmony_ci	}
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci	if (blocksize != crypto_shash_blocksize(generic_tfm)) {
181062306a36Sopenharmony_ci		pr_err("alg: hash: blocksize for %s (%u) doesn't match generic impl (%u)\n",
181162306a36Sopenharmony_ci		       driver, blocksize, crypto_shash_blocksize(generic_tfm));
181262306a36Sopenharmony_ci		err = -EINVAL;
181362306a36Sopenharmony_ci		goto out;
181462306a36Sopenharmony_ci	}
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	/*
181762306a36Sopenharmony_ci	 * Now generate test vectors using the generic implementation, and test
181862306a36Sopenharmony_ci	 * the other implementation against them.
181962306a36Sopenharmony_ci	 */
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci	vec.key = kmalloc(maxkeysize, GFP_KERNEL);
182262306a36Sopenharmony_ci	vec.plaintext = kmalloc(maxdatasize, GFP_KERNEL);
182362306a36Sopenharmony_ci	vec.digest = kmalloc(digestsize, GFP_KERNEL);
182462306a36Sopenharmony_ci	if (!vec.key || !vec.plaintext || !vec.digest) {
182562306a36Sopenharmony_ci		err = -ENOMEM;
182662306a36Sopenharmony_ci		goto out;
182762306a36Sopenharmony_ci	}
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci	for (i = 0; i < fuzz_iterations * 8; i++) {
183062306a36Sopenharmony_ci		generate_random_hash_testvec(&rng, generic_desc, &vec,
183162306a36Sopenharmony_ci					     maxkeysize, maxdatasize,
183262306a36Sopenharmony_ci					     vec_name, sizeof(vec_name));
183362306a36Sopenharmony_ci		generate_random_testvec_config(&rng, cfg, cfgname,
183462306a36Sopenharmony_ci					       sizeof(cfgname));
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci		err = test_hash_vec_cfg(&vec, vec_name, cfg,
183762306a36Sopenharmony_ci					req, desc, tsgl, hashstate);
183862306a36Sopenharmony_ci		if (err)
183962306a36Sopenharmony_ci			goto out;
184062306a36Sopenharmony_ci		cond_resched();
184162306a36Sopenharmony_ci	}
184262306a36Sopenharmony_ci	err = 0;
184362306a36Sopenharmony_ciout:
184462306a36Sopenharmony_ci	kfree(cfg);
184562306a36Sopenharmony_ci	kfree(vec.key);
184662306a36Sopenharmony_ci	kfree(vec.plaintext);
184762306a36Sopenharmony_ci	kfree(vec.digest);
184862306a36Sopenharmony_ci	crypto_free_shash(generic_tfm);
184962306a36Sopenharmony_ci	kfree_sensitive(generic_desc);
185062306a36Sopenharmony_ci	return err;
185162306a36Sopenharmony_ci}
185262306a36Sopenharmony_ci#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
185362306a36Sopenharmony_cistatic int test_hash_vs_generic_impl(const char *generic_driver,
185462306a36Sopenharmony_ci				     unsigned int maxkeysize,
185562306a36Sopenharmony_ci				     struct ahash_request *req,
185662306a36Sopenharmony_ci				     struct shash_desc *desc,
185762306a36Sopenharmony_ci				     struct test_sglist *tsgl,
185862306a36Sopenharmony_ci				     u8 *hashstate)
185962306a36Sopenharmony_ci{
186062306a36Sopenharmony_ci	return 0;
186162306a36Sopenharmony_ci}
186262306a36Sopenharmony_ci#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
186362306a36Sopenharmony_ci
186462306a36Sopenharmony_cistatic int alloc_shash(const char *driver, u32 type, u32 mask,
186562306a36Sopenharmony_ci		       struct crypto_shash **tfm_ret,
186662306a36Sopenharmony_ci		       struct shash_desc **desc_ret)
186762306a36Sopenharmony_ci{
186862306a36Sopenharmony_ci	struct crypto_shash *tfm;
186962306a36Sopenharmony_ci	struct shash_desc *desc;
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	tfm = crypto_alloc_shash(driver, type, mask);
187262306a36Sopenharmony_ci	if (IS_ERR(tfm)) {
187362306a36Sopenharmony_ci		if (PTR_ERR(tfm) == -ENOENT) {
187462306a36Sopenharmony_ci			/*
187562306a36Sopenharmony_ci			 * This algorithm is only available through the ahash
187662306a36Sopenharmony_ci			 * API, not the shash API, so skip the shash tests.
187762306a36Sopenharmony_ci			 */
187862306a36Sopenharmony_ci			return 0;
187962306a36Sopenharmony_ci		}
188062306a36Sopenharmony_ci		pr_err("alg: hash: failed to allocate shash transform for %s: %ld\n",
188162306a36Sopenharmony_ci		       driver, PTR_ERR(tfm));
188262306a36Sopenharmony_ci		return PTR_ERR(tfm);
188362306a36Sopenharmony_ci	}
188462306a36Sopenharmony_ci
188562306a36Sopenharmony_ci	desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
188662306a36Sopenharmony_ci	if (!desc) {
188762306a36Sopenharmony_ci		crypto_free_shash(tfm);
188862306a36Sopenharmony_ci		return -ENOMEM;
188962306a36Sopenharmony_ci	}
189062306a36Sopenharmony_ci	desc->tfm = tfm;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	*tfm_ret = tfm;
189362306a36Sopenharmony_ci	*desc_ret = desc;
189462306a36Sopenharmony_ci	return 0;
189562306a36Sopenharmony_ci}
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_cistatic int __alg_test_hash(const struct hash_testvec *vecs,
189862306a36Sopenharmony_ci			   unsigned int num_vecs, const char *driver,
189962306a36Sopenharmony_ci			   u32 type, u32 mask,
190062306a36Sopenharmony_ci			   const char *generic_driver, unsigned int maxkeysize)
190162306a36Sopenharmony_ci{
190262306a36Sopenharmony_ci	struct crypto_ahash *atfm = NULL;
190362306a36Sopenharmony_ci	struct ahash_request *req = NULL;
190462306a36Sopenharmony_ci	struct crypto_shash *stfm = NULL;
190562306a36Sopenharmony_ci	struct shash_desc *desc = NULL;
190662306a36Sopenharmony_ci	struct test_sglist *tsgl = NULL;
190762306a36Sopenharmony_ci	u8 *hashstate = NULL;
190862306a36Sopenharmony_ci	unsigned int statesize;
190962306a36Sopenharmony_ci	unsigned int i;
191062306a36Sopenharmony_ci	int err;
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci	/*
191362306a36Sopenharmony_ci	 * Always test the ahash API.  This works regardless of whether the
191462306a36Sopenharmony_ci	 * algorithm is implemented as ahash or shash.
191562306a36Sopenharmony_ci	 */
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci	atfm = crypto_alloc_ahash(driver, type, mask);
191862306a36Sopenharmony_ci	if (IS_ERR(atfm)) {
191962306a36Sopenharmony_ci		pr_err("alg: hash: failed to allocate transform for %s: %ld\n",
192062306a36Sopenharmony_ci		       driver, PTR_ERR(atfm));
192162306a36Sopenharmony_ci		return PTR_ERR(atfm);
192262306a36Sopenharmony_ci	}
192362306a36Sopenharmony_ci	driver = crypto_ahash_driver_name(atfm);
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_ci	req = ahash_request_alloc(atfm, GFP_KERNEL);
192662306a36Sopenharmony_ci	if (!req) {
192762306a36Sopenharmony_ci		pr_err("alg: hash: failed to allocate request for %s\n",
192862306a36Sopenharmony_ci		       driver);
192962306a36Sopenharmony_ci		err = -ENOMEM;
193062306a36Sopenharmony_ci		goto out;
193162306a36Sopenharmony_ci	}
193262306a36Sopenharmony_ci
193362306a36Sopenharmony_ci	/*
193462306a36Sopenharmony_ci	 * If available also test the shash API, to cover corner cases that may
193562306a36Sopenharmony_ci	 * be missed by testing the ahash API only.
193662306a36Sopenharmony_ci	 */
193762306a36Sopenharmony_ci	err = alloc_shash(driver, type, mask, &stfm, &desc);
193862306a36Sopenharmony_ci	if (err)
193962306a36Sopenharmony_ci		goto out;
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci	tsgl = kmalloc(sizeof(*tsgl), GFP_KERNEL);
194262306a36Sopenharmony_ci	if (!tsgl || init_test_sglist(tsgl) != 0) {
194362306a36Sopenharmony_ci		pr_err("alg: hash: failed to allocate test buffers for %s\n",
194462306a36Sopenharmony_ci		       driver);
194562306a36Sopenharmony_ci		kfree(tsgl);
194662306a36Sopenharmony_ci		tsgl = NULL;
194762306a36Sopenharmony_ci		err = -ENOMEM;
194862306a36Sopenharmony_ci		goto out;
194962306a36Sopenharmony_ci	}
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci	statesize = crypto_ahash_statesize(atfm);
195262306a36Sopenharmony_ci	if (stfm)
195362306a36Sopenharmony_ci		statesize = max(statesize, crypto_shash_statesize(stfm));
195462306a36Sopenharmony_ci	hashstate = kmalloc(statesize + TESTMGR_POISON_LEN, GFP_KERNEL);
195562306a36Sopenharmony_ci	if (!hashstate) {
195662306a36Sopenharmony_ci		pr_err("alg: hash: failed to allocate hash state buffer for %s\n",
195762306a36Sopenharmony_ci		       driver);
195862306a36Sopenharmony_ci		err = -ENOMEM;
195962306a36Sopenharmony_ci		goto out;
196062306a36Sopenharmony_ci	}
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	for (i = 0; i < num_vecs; i++) {
196362306a36Sopenharmony_ci		if (fips_enabled && vecs[i].fips_skip)
196462306a36Sopenharmony_ci			continue;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci		err = test_hash_vec(&vecs[i], i, req, desc, tsgl, hashstate);
196762306a36Sopenharmony_ci		if (err)
196862306a36Sopenharmony_ci			goto out;
196962306a36Sopenharmony_ci		cond_resched();
197062306a36Sopenharmony_ci	}
197162306a36Sopenharmony_ci	err = test_hash_vs_generic_impl(generic_driver, maxkeysize, req,
197262306a36Sopenharmony_ci					desc, tsgl, hashstate);
197362306a36Sopenharmony_ciout:
197462306a36Sopenharmony_ci	kfree(hashstate);
197562306a36Sopenharmony_ci	if (tsgl) {
197662306a36Sopenharmony_ci		destroy_test_sglist(tsgl);
197762306a36Sopenharmony_ci		kfree(tsgl);
197862306a36Sopenharmony_ci	}
197962306a36Sopenharmony_ci	kfree(desc);
198062306a36Sopenharmony_ci	crypto_free_shash(stfm);
198162306a36Sopenharmony_ci	ahash_request_free(req);
198262306a36Sopenharmony_ci	crypto_free_ahash(atfm);
198362306a36Sopenharmony_ci	return err;
198462306a36Sopenharmony_ci}
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_cistatic int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
198762306a36Sopenharmony_ci			 u32 type, u32 mask)
198862306a36Sopenharmony_ci{
198962306a36Sopenharmony_ci	const struct hash_testvec *template = desc->suite.hash.vecs;
199062306a36Sopenharmony_ci	unsigned int tcount = desc->suite.hash.count;
199162306a36Sopenharmony_ci	unsigned int nr_unkeyed, nr_keyed;
199262306a36Sopenharmony_ci	unsigned int maxkeysize = 0;
199362306a36Sopenharmony_ci	int err;
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_ci	/*
199662306a36Sopenharmony_ci	 * For OPTIONAL_KEY algorithms, we have to do all the unkeyed tests
199762306a36Sopenharmony_ci	 * first, before setting a key on the tfm.  To make this easier, we
199862306a36Sopenharmony_ci	 * require that the unkeyed test vectors (if any) are listed first.
199962306a36Sopenharmony_ci	 */
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_ci	for (nr_unkeyed = 0; nr_unkeyed < tcount; nr_unkeyed++) {
200262306a36Sopenharmony_ci		if (template[nr_unkeyed].ksize)
200362306a36Sopenharmony_ci			break;
200462306a36Sopenharmony_ci	}
200562306a36Sopenharmony_ci	for (nr_keyed = 0; nr_unkeyed + nr_keyed < tcount; nr_keyed++) {
200662306a36Sopenharmony_ci		if (!template[nr_unkeyed + nr_keyed].ksize) {
200762306a36Sopenharmony_ci			pr_err("alg: hash: test vectors for %s out of order, "
200862306a36Sopenharmony_ci			       "unkeyed ones must come first\n", desc->alg);
200962306a36Sopenharmony_ci			return -EINVAL;
201062306a36Sopenharmony_ci		}
201162306a36Sopenharmony_ci		maxkeysize = max_t(unsigned int, maxkeysize,
201262306a36Sopenharmony_ci				   template[nr_unkeyed + nr_keyed].ksize);
201362306a36Sopenharmony_ci	}
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	err = 0;
201662306a36Sopenharmony_ci	if (nr_unkeyed) {
201762306a36Sopenharmony_ci		err = __alg_test_hash(template, nr_unkeyed, driver, type, mask,
201862306a36Sopenharmony_ci				      desc->generic_driver, maxkeysize);
201962306a36Sopenharmony_ci		template += nr_unkeyed;
202062306a36Sopenharmony_ci	}
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	if (!err && nr_keyed)
202362306a36Sopenharmony_ci		err = __alg_test_hash(template, nr_keyed, driver, type, mask,
202462306a36Sopenharmony_ci				      desc->generic_driver, maxkeysize);
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_ci	return err;
202762306a36Sopenharmony_ci}
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_cistatic int test_aead_vec_cfg(int enc, const struct aead_testvec *vec,
203062306a36Sopenharmony_ci			     const char *vec_name,
203162306a36Sopenharmony_ci			     const struct testvec_config *cfg,
203262306a36Sopenharmony_ci			     struct aead_request *req,
203362306a36Sopenharmony_ci			     struct cipher_test_sglists *tsgls)
203462306a36Sopenharmony_ci{
203562306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
203662306a36Sopenharmony_ci	const unsigned int alignmask = crypto_aead_alignmask(tfm);
203762306a36Sopenharmony_ci	const unsigned int ivsize = crypto_aead_ivsize(tfm);
203862306a36Sopenharmony_ci	const unsigned int authsize = vec->clen - vec->plen;
203962306a36Sopenharmony_ci	const char *driver = crypto_aead_driver_name(tfm);
204062306a36Sopenharmony_ci	const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags;
204162306a36Sopenharmony_ci	const char *op = enc ? "encryption" : "decryption";
204262306a36Sopenharmony_ci	DECLARE_CRYPTO_WAIT(wait);
204362306a36Sopenharmony_ci	u8 _iv[3 * (MAX_ALGAPI_ALIGNMASK + 1) + MAX_IVLEN];
204462306a36Sopenharmony_ci	u8 *iv = PTR_ALIGN(&_iv[0], 2 * (MAX_ALGAPI_ALIGNMASK + 1)) +
204562306a36Sopenharmony_ci		 cfg->iv_offset +
204662306a36Sopenharmony_ci		 (cfg->iv_offset_relative_to_alignmask ? alignmask : 0);
204762306a36Sopenharmony_ci	struct kvec input[2];
204862306a36Sopenharmony_ci	int err;
204962306a36Sopenharmony_ci
205062306a36Sopenharmony_ci	/* Set the key */
205162306a36Sopenharmony_ci	if (vec->wk)
205262306a36Sopenharmony_ci		crypto_aead_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
205362306a36Sopenharmony_ci	else
205462306a36Sopenharmony_ci		crypto_aead_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_ci	err = do_setkey(crypto_aead_setkey, tfm, vec->key, vec->klen,
205762306a36Sopenharmony_ci			cfg, alignmask);
205862306a36Sopenharmony_ci	if (err && err != vec->setkey_error) {
205962306a36Sopenharmony_ci		pr_err("alg: aead: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
206062306a36Sopenharmony_ci		       driver, vec_name, vec->setkey_error, err,
206162306a36Sopenharmony_ci		       crypto_aead_get_flags(tfm));
206262306a36Sopenharmony_ci		return err;
206362306a36Sopenharmony_ci	}
206462306a36Sopenharmony_ci	if (!err && vec->setkey_error) {
206562306a36Sopenharmony_ci		pr_err("alg: aead: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
206662306a36Sopenharmony_ci		       driver, vec_name, vec->setkey_error);
206762306a36Sopenharmony_ci		return -EINVAL;
206862306a36Sopenharmony_ci	}
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci	/* Set the authentication tag size */
207162306a36Sopenharmony_ci	err = crypto_aead_setauthsize(tfm, authsize);
207262306a36Sopenharmony_ci	if (err && err != vec->setauthsize_error) {
207362306a36Sopenharmony_ci		pr_err("alg: aead: %s setauthsize failed on test vector %s; expected_error=%d, actual_error=%d\n",
207462306a36Sopenharmony_ci		       driver, vec_name, vec->setauthsize_error, err);
207562306a36Sopenharmony_ci		return err;
207662306a36Sopenharmony_ci	}
207762306a36Sopenharmony_ci	if (!err && vec->setauthsize_error) {
207862306a36Sopenharmony_ci		pr_err("alg: aead: %s setauthsize unexpectedly succeeded on test vector %s; expected_error=%d\n",
207962306a36Sopenharmony_ci		       driver, vec_name, vec->setauthsize_error);
208062306a36Sopenharmony_ci		return -EINVAL;
208162306a36Sopenharmony_ci	}
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	if (vec->setkey_error || vec->setauthsize_error)
208462306a36Sopenharmony_ci		return 0;
208562306a36Sopenharmony_ci
208662306a36Sopenharmony_ci	/* The IV must be copied to a buffer, as the algorithm may modify it */
208762306a36Sopenharmony_ci	if (WARN_ON(ivsize > MAX_IVLEN))
208862306a36Sopenharmony_ci		return -EINVAL;
208962306a36Sopenharmony_ci	if (vec->iv)
209062306a36Sopenharmony_ci		memcpy(iv, vec->iv, ivsize);
209162306a36Sopenharmony_ci	else
209262306a36Sopenharmony_ci		memset(iv, 0, ivsize);
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci	/* Build the src/dst scatterlists */
209562306a36Sopenharmony_ci	input[0].iov_base = (void *)vec->assoc;
209662306a36Sopenharmony_ci	input[0].iov_len = vec->alen;
209762306a36Sopenharmony_ci	input[1].iov_base = enc ? (void *)vec->ptext : (void *)vec->ctext;
209862306a36Sopenharmony_ci	input[1].iov_len = enc ? vec->plen : vec->clen;
209962306a36Sopenharmony_ci	err = build_cipher_test_sglists(tsgls, cfg, alignmask,
210062306a36Sopenharmony_ci					vec->alen + (enc ? vec->plen :
210162306a36Sopenharmony_ci						     vec->clen),
210262306a36Sopenharmony_ci					vec->alen + (enc ? vec->clen :
210362306a36Sopenharmony_ci						     vec->plen),
210462306a36Sopenharmony_ci					input, 2);
210562306a36Sopenharmony_ci	if (err) {
210662306a36Sopenharmony_ci		pr_err("alg: aead: %s %s: error preparing scatterlists for test vector %s, cfg=\"%s\"\n",
210762306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
210862306a36Sopenharmony_ci		return err;
210962306a36Sopenharmony_ci	}
211062306a36Sopenharmony_ci
211162306a36Sopenharmony_ci	/* Do the actual encryption or decryption */
211262306a36Sopenharmony_ci	testmgr_poison(req->__ctx, crypto_aead_reqsize(tfm));
211362306a36Sopenharmony_ci	aead_request_set_callback(req, req_flags, crypto_req_done, &wait);
211462306a36Sopenharmony_ci	aead_request_set_crypt(req, tsgls->src.sgl_ptr, tsgls->dst.sgl_ptr,
211562306a36Sopenharmony_ci			       enc ? vec->plen : vec->clen, iv);
211662306a36Sopenharmony_ci	aead_request_set_ad(req, vec->alen);
211762306a36Sopenharmony_ci	if (cfg->nosimd)
211862306a36Sopenharmony_ci		crypto_disable_simd_for_test();
211962306a36Sopenharmony_ci	err = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
212062306a36Sopenharmony_ci	if (cfg->nosimd)
212162306a36Sopenharmony_ci		crypto_reenable_simd_for_test();
212262306a36Sopenharmony_ci	err = crypto_wait_req(err, &wait);
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_ci	/* Check that the algorithm didn't overwrite things it shouldn't have */
212562306a36Sopenharmony_ci	if (req->cryptlen != (enc ? vec->plen : vec->clen) ||
212662306a36Sopenharmony_ci	    req->assoclen != vec->alen ||
212762306a36Sopenharmony_ci	    req->iv != iv ||
212862306a36Sopenharmony_ci	    req->src != tsgls->src.sgl_ptr ||
212962306a36Sopenharmony_ci	    req->dst != tsgls->dst.sgl_ptr ||
213062306a36Sopenharmony_ci	    crypto_aead_reqtfm(req) != tfm ||
213162306a36Sopenharmony_ci	    req->base.complete != crypto_req_done ||
213262306a36Sopenharmony_ci	    req->base.flags != req_flags ||
213362306a36Sopenharmony_ci	    req->base.data != &wait) {
213462306a36Sopenharmony_ci		pr_err("alg: aead: %s %s corrupted request struct on test vector %s, cfg=\"%s\"\n",
213562306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
213662306a36Sopenharmony_ci		if (req->cryptlen != (enc ? vec->plen : vec->clen))
213762306a36Sopenharmony_ci			pr_err("alg: aead: changed 'req->cryptlen'\n");
213862306a36Sopenharmony_ci		if (req->assoclen != vec->alen)
213962306a36Sopenharmony_ci			pr_err("alg: aead: changed 'req->assoclen'\n");
214062306a36Sopenharmony_ci		if (req->iv != iv)
214162306a36Sopenharmony_ci			pr_err("alg: aead: changed 'req->iv'\n");
214262306a36Sopenharmony_ci		if (req->src != tsgls->src.sgl_ptr)
214362306a36Sopenharmony_ci			pr_err("alg: aead: changed 'req->src'\n");
214462306a36Sopenharmony_ci		if (req->dst != tsgls->dst.sgl_ptr)
214562306a36Sopenharmony_ci			pr_err("alg: aead: changed 'req->dst'\n");
214662306a36Sopenharmony_ci		if (crypto_aead_reqtfm(req) != tfm)
214762306a36Sopenharmony_ci			pr_err("alg: aead: changed 'req->base.tfm'\n");
214862306a36Sopenharmony_ci		if (req->base.complete != crypto_req_done)
214962306a36Sopenharmony_ci			pr_err("alg: aead: changed 'req->base.complete'\n");
215062306a36Sopenharmony_ci		if (req->base.flags != req_flags)
215162306a36Sopenharmony_ci			pr_err("alg: aead: changed 'req->base.flags'\n");
215262306a36Sopenharmony_ci		if (req->base.data != &wait)
215362306a36Sopenharmony_ci			pr_err("alg: aead: changed 'req->base.data'\n");
215462306a36Sopenharmony_ci		return -EINVAL;
215562306a36Sopenharmony_ci	}
215662306a36Sopenharmony_ci	if (is_test_sglist_corrupted(&tsgls->src)) {
215762306a36Sopenharmony_ci		pr_err("alg: aead: %s %s corrupted src sgl on test vector %s, cfg=\"%s\"\n",
215862306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
215962306a36Sopenharmony_ci		return -EINVAL;
216062306a36Sopenharmony_ci	}
216162306a36Sopenharmony_ci	if (tsgls->dst.sgl_ptr != tsgls->src.sgl &&
216262306a36Sopenharmony_ci	    is_test_sglist_corrupted(&tsgls->dst)) {
216362306a36Sopenharmony_ci		pr_err("alg: aead: %s %s corrupted dst sgl on test vector %s, cfg=\"%s\"\n",
216462306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
216562306a36Sopenharmony_ci		return -EINVAL;
216662306a36Sopenharmony_ci	}
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci	/* Check for unexpected success or failure, or wrong error code */
216962306a36Sopenharmony_ci	if ((err == 0 && vec->novrfy) ||
217062306a36Sopenharmony_ci	    (err != vec->crypt_error && !(err == -EBADMSG && vec->novrfy))) {
217162306a36Sopenharmony_ci		char expected_error[32];
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_ci		if (vec->novrfy &&
217462306a36Sopenharmony_ci		    vec->crypt_error != 0 && vec->crypt_error != -EBADMSG)
217562306a36Sopenharmony_ci			sprintf(expected_error, "-EBADMSG or %d",
217662306a36Sopenharmony_ci				vec->crypt_error);
217762306a36Sopenharmony_ci		else if (vec->novrfy)
217862306a36Sopenharmony_ci			sprintf(expected_error, "-EBADMSG");
217962306a36Sopenharmony_ci		else
218062306a36Sopenharmony_ci			sprintf(expected_error, "%d", vec->crypt_error);
218162306a36Sopenharmony_ci		if (err) {
218262306a36Sopenharmony_ci			pr_err("alg: aead: %s %s failed on test vector %s; expected_error=%s, actual_error=%d, cfg=\"%s\"\n",
218362306a36Sopenharmony_ci			       driver, op, vec_name, expected_error, err,
218462306a36Sopenharmony_ci			       cfg->name);
218562306a36Sopenharmony_ci			return err;
218662306a36Sopenharmony_ci		}
218762306a36Sopenharmony_ci		pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %s; expected_error=%s, cfg=\"%s\"\n",
218862306a36Sopenharmony_ci		       driver, op, vec_name, expected_error, cfg->name);
218962306a36Sopenharmony_ci		return -EINVAL;
219062306a36Sopenharmony_ci	}
219162306a36Sopenharmony_ci	if (err) /* Expectedly failed. */
219262306a36Sopenharmony_ci		return 0;
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_ci	/* Check for the correct output (ciphertext or plaintext) */
219562306a36Sopenharmony_ci	err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext,
219662306a36Sopenharmony_ci				    enc ? vec->clen : vec->plen,
219762306a36Sopenharmony_ci				    vec->alen,
219862306a36Sopenharmony_ci				    enc || cfg->inplace_mode == OUT_OF_PLACE);
219962306a36Sopenharmony_ci	if (err == -EOVERFLOW) {
220062306a36Sopenharmony_ci		pr_err("alg: aead: %s %s overran dst buffer on test vector %s, cfg=\"%s\"\n",
220162306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
220262306a36Sopenharmony_ci		return err;
220362306a36Sopenharmony_ci	}
220462306a36Sopenharmony_ci	if (err) {
220562306a36Sopenharmony_ci		pr_err("alg: aead: %s %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
220662306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
220762306a36Sopenharmony_ci		return err;
220862306a36Sopenharmony_ci	}
220962306a36Sopenharmony_ci
221062306a36Sopenharmony_ci	return 0;
221162306a36Sopenharmony_ci}
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_cistatic int test_aead_vec(int enc, const struct aead_testvec *vec,
221462306a36Sopenharmony_ci			 unsigned int vec_num, struct aead_request *req,
221562306a36Sopenharmony_ci			 struct cipher_test_sglists *tsgls)
221662306a36Sopenharmony_ci{
221762306a36Sopenharmony_ci	char vec_name[16];
221862306a36Sopenharmony_ci	unsigned int i;
221962306a36Sopenharmony_ci	int err;
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci	if (enc && vec->novrfy)
222262306a36Sopenharmony_ci		return 0;
222362306a36Sopenharmony_ci
222462306a36Sopenharmony_ci	sprintf(vec_name, "%u", vec_num);
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) {
222762306a36Sopenharmony_ci		err = test_aead_vec_cfg(enc, vec, vec_name,
222862306a36Sopenharmony_ci					&default_cipher_testvec_configs[i],
222962306a36Sopenharmony_ci					req, tsgls);
223062306a36Sopenharmony_ci		if (err)
223162306a36Sopenharmony_ci			return err;
223262306a36Sopenharmony_ci	}
223362306a36Sopenharmony_ci
223462306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
223562306a36Sopenharmony_ci	if (!noextratests) {
223662306a36Sopenharmony_ci		struct rnd_state rng;
223762306a36Sopenharmony_ci		struct testvec_config cfg;
223862306a36Sopenharmony_ci		char cfgname[TESTVEC_CONFIG_NAMELEN];
223962306a36Sopenharmony_ci
224062306a36Sopenharmony_ci		init_rnd_state(&rng);
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_ci		for (i = 0; i < fuzz_iterations; i++) {
224362306a36Sopenharmony_ci			generate_random_testvec_config(&rng, &cfg, cfgname,
224462306a36Sopenharmony_ci						       sizeof(cfgname));
224562306a36Sopenharmony_ci			err = test_aead_vec_cfg(enc, vec, vec_name,
224662306a36Sopenharmony_ci						&cfg, req, tsgls);
224762306a36Sopenharmony_ci			if (err)
224862306a36Sopenharmony_ci				return err;
224962306a36Sopenharmony_ci			cond_resched();
225062306a36Sopenharmony_ci		}
225162306a36Sopenharmony_ci	}
225262306a36Sopenharmony_ci#endif
225362306a36Sopenharmony_ci	return 0;
225462306a36Sopenharmony_ci}
225562306a36Sopenharmony_ci
225662306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_cistruct aead_extra_tests_ctx {
225962306a36Sopenharmony_ci	struct rnd_state rng;
226062306a36Sopenharmony_ci	struct aead_request *req;
226162306a36Sopenharmony_ci	struct crypto_aead *tfm;
226262306a36Sopenharmony_ci	const struct alg_test_desc *test_desc;
226362306a36Sopenharmony_ci	struct cipher_test_sglists *tsgls;
226462306a36Sopenharmony_ci	unsigned int maxdatasize;
226562306a36Sopenharmony_ci	unsigned int maxkeysize;
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	struct aead_testvec vec;
226862306a36Sopenharmony_ci	char vec_name[64];
226962306a36Sopenharmony_ci	char cfgname[TESTVEC_CONFIG_NAMELEN];
227062306a36Sopenharmony_ci	struct testvec_config cfg;
227162306a36Sopenharmony_ci};
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci/*
227462306a36Sopenharmony_ci * Make at least one random change to a (ciphertext, AAD) pair.  "Ciphertext"
227562306a36Sopenharmony_ci * here means the full ciphertext including the authentication tag.  The
227662306a36Sopenharmony_ci * authentication tag (and hence also the ciphertext) is assumed to be nonempty.
227762306a36Sopenharmony_ci */
227862306a36Sopenharmony_cistatic void mutate_aead_message(struct rnd_state *rng,
227962306a36Sopenharmony_ci				struct aead_testvec *vec, bool aad_iv,
228062306a36Sopenharmony_ci				unsigned int ivsize)
228162306a36Sopenharmony_ci{
228262306a36Sopenharmony_ci	const unsigned int aad_tail_size = aad_iv ? ivsize : 0;
228362306a36Sopenharmony_ci	const unsigned int authsize = vec->clen - vec->plen;
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	if (prandom_bool(rng) && vec->alen > aad_tail_size) {
228662306a36Sopenharmony_ci		 /* Mutate the AAD */
228762306a36Sopenharmony_ci		flip_random_bit(rng, (u8 *)vec->assoc,
228862306a36Sopenharmony_ci				vec->alen - aad_tail_size);
228962306a36Sopenharmony_ci		if (prandom_bool(rng))
229062306a36Sopenharmony_ci			return;
229162306a36Sopenharmony_ci	}
229262306a36Sopenharmony_ci	if (prandom_bool(rng)) {
229362306a36Sopenharmony_ci		/* Mutate auth tag (assuming it's at the end of ciphertext) */
229462306a36Sopenharmony_ci		flip_random_bit(rng, (u8 *)vec->ctext + vec->plen, authsize);
229562306a36Sopenharmony_ci	} else {
229662306a36Sopenharmony_ci		/* Mutate any part of the ciphertext */
229762306a36Sopenharmony_ci		flip_random_bit(rng, (u8 *)vec->ctext, vec->clen);
229862306a36Sopenharmony_ci	}
229962306a36Sopenharmony_ci}
230062306a36Sopenharmony_ci
230162306a36Sopenharmony_ci/*
230262306a36Sopenharmony_ci * Minimum authentication tag size in bytes at which we assume that we can
230362306a36Sopenharmony_ci * reliably generate inauthentic messages, i.e. not generate an authentic
230462306a36Sopenharmony_ci * message by chance.
230562306a36Sopenharmony_ci */
230662306a36Sopenharmony_ci#define MIN_COLLISION_FREE_AUTHSIZE 8
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_cistatic void generate_aead_message(struct rnd_state *rng,
230962306a36Sopenharmony_ci				  struct aead_request *req,
231062306a36Sopenharmony_ci				  const struct aead_test_suite *suite,
231162306a36Sopenharmony_ci				  struct aead_testvec *vec,
231262306a36Sopenharmony_ci				  bool prefer_inauthentic)
231362306a36Sopenharmony_ci{
231462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
231562306a36Sopenharmony_ci	const unsigned int ivsize = crypto_aead_ivsize(tfm);
231662306a36Sopenharmony_ci	const unsigned int authsize = vec->clen - vec->plen;
231762306a36Sopenharmony_ci	const bool inauthentic = (authsize >= MIN_COLLISION_FREE_AUTHSIZE) &&
231862306a36Sopenharmony_ci				 (prefer_inauthentic ||
231962306a36Sopenharmony_ci				  prandom_u32_below(rng, 4) == 0);
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ci	/* Generate the AAD. */
232262306a36Sopenharmony_ci	generate_random_bytes(rng, (u8 *)vec->assoc, vec->alen);
232362306a36Sopenharmony_ci	if (suite->aad_iv && vec->alen >= ivsize)
232462306a36Sopenharmony_ci		/* Avoid implementation-defined behavior. */
232562306a36Sopenharmony_ci		memcpy((u8 *)vec->assoc + vec->alen - ivsize, vec->iv, ivsize);
232662306a36Sopenharmony_ci
232762306a36Sopenharmony_ci	if (inauthentic && prandom_bool(rng)) {
232862306a36Sopenharmony_ci		/* Generate a random ciphertext. */
232962306a36Sopenharmony_ci		generate_random_bytes(rng, (u8 *)vec->ctext, vec->clen);
233062306a36Sopenharmony_ci	} else {
233162306a36Sopenharmony_ci		int i = 0;
233262306a36Sopenharmony_ci		struct scatterlist src[2], dst;
233362306a36Sopenharmony_ci		u8 iv[MAX_IVLEN];
233462306a36Sopenharmony_ci		DECLARE_CRYPTO_WAIT(wait);
233562306a36Sopenharmony_ci
233662306a36Sopenharmony_ci		/* Generate a random plaintext and encrypt it. */
233762306a36Sopenharmony_ci		sg_init_table(src, 2);
233862306a36Sopenharmony_ci		if (vec->alen)
233962306a36Sopenharmony_ci			sg_set_buf(&src[i++], vec->assoc, vec->alen);
234062306a36Sopenharmony_ci		if (vec->plen) {
234162306a36Sopenharmony_ci			generate_random_bytes(rng, (u8 *)vec->ptext, vec->plen);
234262306a36Sopenharmony_ci			sg_set_buf(&src[i++], vec->ptext, vec->plen);
234362306a36Sopenharmony_ci		}
234462306a36Sopenharmony_ci		sg_init_one(&dst, vec->ctext, vec->alen + vec->clen);
234562306a36Sopenharmony_ci		memcpy(iv, vec->iv, ivsize);
234662306a36Sopenharmony_ci		aead_request_set_callback(req, 0, crypto_req_done, &wait);
234762306a36Sopenharmony_ci		aead_request_set_crypt(req, src, &dst, vec->plen, iv);
234862306a36Sopenharmony_ci		aead_request_set_ad(req, vec->alen);
234962306a36Sopenharmony_ci		vec->crypt_error = crypto_wait_req(crypto_aead_encrypt(req),
235062306a36Sopenharmony_ci						   &wait);
235162306a36Sopenharmony_ci		/* If encryption failed, we're done. */
235262306a36Sopenharmony_ci		if (vec->crypt_error != 0)
235362306a36Sopenharmony_ci			return;
235462306a36Sopenharmony_ci		memmove((u8 *)vec->ctext, vec->ctext + vec->alen, vec->clen);
235562306a36Sopenharmony_ci		if (!inauthentic)
235662306a36Sopenharmony_ci			return;
235762306a36Sopenharmony_ci		/*
235862306a36Sopenharmony_ci		 * Mutate the authentic (ciphertext, AAD) pair to get an
235962306a36Sopenharmony_ci		 * inauthentic one.
236062306a36Sopenharmony_ci		 */
236162306a36Sopenharmony_ci		mutate_aead_message(rng, vec, suite->aad_iv, ivsize);
236262306a36Sopenharmony_ci	}
236362306a36Sopenharmony_ci	vec->novrfy = 1;
236462306a36Sopenharmony_ci	if (suite->einval_allowed)
236562306a36Sopenharmony_ci		vec->crypt_error = -EINVAL;
236662306a36Sopenharmony_ci}
236762306a36Sopenharmony_ci
236862306a36Sopenharmony_ci/*
236962306a36Sopenharmony_ci * Generate an AEAD test vector 'vec' using the implementation specified by
237062306a36Sopenharmony_ci * 'req'.  The buffers in 'vec' must already be allocated.
237162306a36Sopenharmony_ci *
237262306a36Sopenharmony_ci * If 'prefer_inauthentic' is true, then this function will generate inauthentic
237362306a36Sopenharmony_ci * test vectors (i.e. vectors with 'vec->novrfy=1') more often.
237462306a36Sopenharmony_ci */
237562306a36Sopenharmony_cistatic void generate_random_aead_testvec(struct rnd_state *rng,
237662306a36Sopenharmony_ci					 struct aead_request *req,
237762306a36Sopenharmony_ci					 struct aead_testvec *vec,
237862306a36Sopenharmony_ci					 const struct aead_test_suite *suite,
237962306a36Sopenharmony_ci					 unsigned int maxkeysize,
238062306a36Sopenharmony_ci					 unsigned int maxdatasize,
238162306a36Sopenharmony_ci					 char *name, size_t max_namelen,
238262306a36Sopenharmony_ci					 bool prefer_inauthentic)
238362306a36Sopenharmony_ci{
238462306a36Sopenharmony_ci	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
238562306a36Sopenharmony_ci	const unsigned int ivsize = crypto_aead_ivsize(tfm);
238662306a36Sopenharmony_ci	const unsigned int maxauthsize = crypto_aead_maxauthsize(tfm);
238762306a36Sopenharmony_ci	unsigned int authsize;
238862306a36Sopenharmony_ci	unsigned int total_len;
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	/* Key: length in [0, maxkeysize], but usually choose maxkeysize */
239162306a36Sopenharmony_ci	vec->klen = maxkeysize;
239262306a36Sopenharmony_ci	if (prandom_u32_below(rng, 4) == 0)
239362306a36Sopenharmony_ci		vec->klen = prandom_u32_below(rng, maxkeysize + 1);
239462306a36Sopenharmony_ci	generate_random_bytes(rng, (u8 *)vec->key, vec->klen);
239562306a36Sopenharmony_ci	vec->setkey_error = crypto_aead_setkey(tfm, vec->key, vec->klen);
239662306a36Sopenharmony_ci
239762306a36Sopenharmony_ci	/* IV */
239862306a36Sopenharmony_ci	generate_random_bytes(rng, (u8 *)vec->iv, ivsize);
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_ci	/* Tag length: in [0, maxauthsize], but usually choose maxauthsize */
240162306a36Sopenharmony_ci	authsize = maxauthsize;
240262306a36Sopenharmony_ci	if (prandom_u32_below(rng, 4) == 0)
240362306a36Sopenharmony_ci		authsize = prandom_u32_below(rng, maxauthsize + 1);
240462306a36Sopenharmony_ci	if (prefer_inauthentic && authsize < MIN_COLLISION_FREE_AUTHSIZE)
240562306a36Sopenharmony_ci		authsize = MIN_COLLISION_FREE_AUTHSIZE;
240662306a36Sopenharmony_ci	if (WARN_ON(authsize > maxdatasize))
240762306a36Sopenharmony_ci		authsize = maxdatasize;
240862306a36Sopenharmony_ci	maxdatasize -= authsize;
240962306a36Sopenharmony_ci	vec->setauthsize_error = crypto_aead_setauthsize(tfm, authsize);
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci	/* AAD, plaintext, and ciphertext lengths */
241262306a36Sopenharmony_ci	total_len = generate_random_length(rng, maxdatasize);
241362306a36Sopenharmony_ci	if (prandom_u32_below(rng, 4) == 0)
241462306a36Sopenharmony_ci		vec->alen = 0;
241562306a36Sopenharmony_ci	else
241662306a36Sopenharmony_ci		vec->alen = generate_random_length(rng, total_len);
241762306a36Sopenharmony_ci	vec->plen = total_len - vec->alen;
241862306a36Sopenharmony_ci	vec->clen = vec->plen + authsize;
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci	/*
242162306a36Sopenharmony_ci	 * Generate the AAD, plaintext, and ciphertext.  Not applicable if the
242262306a36Sopenharmony_ci	 * key or the authentication tag size couldn't be set.
242362306a36Sopenharmony_ci	 */
242462306a36Sopenharmony_ci	vec->novrfy = 0;
242562306a36Sopenharmony_ci	vec->crypt_error = 0;
242662306a36Sopenharmony_ci	if (vec->setkey_error == 0 && vec->setauthsize_error == 0)
242762306a36Sopenharmony_ci		generate_aead_message(rng, req, suite, vec, prefer_inauthentic);
242862306a36Sopenharmony_ci	snprintf(name, max_namelen,
242962306a36Sopenharmony_ci		 "\"random: alen=%u plen=%u authsize=%u klen=%u novrfy=%d\"",
243062306a36Sopenharmony_ci		 vec->alen, vec->plen, authsize, vec->klen, vec->novrfy);
243162306a36Sopenharmony_ci}
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_cistatic void try_to_generate_inauthentic_testvec(
243462306a36Sopenharmony_ci					struct aead_extra_tests_ctx *ctx)
243562306a36Sopenharmony_ci{
243662306a36Sopenharmony_ci	int i;
243762306a36Sopenharmony_ci
243862306a36Sopenharmony_ci	for (i = 0; i < 10; i++) {
243962306a36Sopenharmony_ci		generate_random_aead_testvec(&ctx->rng, ctx->req, &ctx->vec,
244062306a36Sopenharmony_ci					     &ctx->test_desc->suite.aead,
244162306a36Sopenharmony_ci					     ctx->maxkeysize, ctx->maxdatasize,
244262306a36Sopenharmony_ci					     ctx->vec_name,
244362306a36Sopenharmony_ci					     sizeof(ctx->vec_name), true);
244462306a36Sopenharmony_ci		if (ctx->vec.novrfy)
244562306a36Sopenharmony_ci			return;
244662306a36Sopenharmony_ci	}
244762306a36Sopenharmony_ci}
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_ci/*
245062306a36Sopenharmony_ci * Generate inauthentic test vectors (i.e. ciphertext, AAD pairs that aren't the
245162306a36Sopenharmony_ci * result of an encryption with the key) and verify that decryption fails.
245262306a36Sopenharmony_ci */
245362306a36Sopenharmony_cistatic int test_aead_inauthentic_inputs(struct aead_extra_tests_ctx *ctx)
245462306a36Sopenharmony_ci{
245562306a36Sopenharmony_ci	unsigned int i;
245662306a36Sopenharmony_ci	int err;
245762306a36Sopenharmony_ci
245862306a36Sopenharmony_ci	for (i = 0; i < fuzz_iterations * 8; i++) {
245962306a36Sopenharmony_ci		/*
246062306a36Sopenharmony_ci		 * Since this part of the tests isn't comparing the
246162306a36Sopenharmony_ci		 * implementation to another, there's no point in testing any
246262306a36Sopenharmony_ci		 * test vectors other than inauthentic ones (vec.novrfy=1) here.
246362306a36Sopenharmony_ci		 *
246462306a36Sopenharmony_ci		 * If we're having trouble generating such a test vector, e.g.
246562306a36Sopenharmony_ci		 * if the algorithm keeps rejecting the generated keys, don't
246662306a36Sopenharmony_ci		 * retry forever; just continue on.
246762306a36Sopenharmony_ci		 */
246862306a36Sopenharmony_ci		try_to_generate_inauthentic_testvec(ctx);
246962306a36Sopenharmony_ci		if (ctx->vec.novrfy) {
247062306a36Sopenharmony_ci			generate_random_testvec_config(&ctx->rng, &ctx->cfg,
247162306a36Sopenharmony_ci						       ctx->cfgname,
247262306a36Sopenharmony_ci						       sizeof(ctx->cfgname));
247362306a36Sopenharmony_ci			err = test_aead_vec_cfg(DECRYPT, &ctx->vec,
247462306a36Sopenharmony_ci						ctx->vec_name, &ctx->cfg,
247562306a36Sopenharmony_ci						ctx->req, ctx->tsgls);
247662306a36Sopenharmony_ci			if (err)
247762306a36Sopenharmony_ci				return err;
247862306a36Sopenharmony_ci		}
247962306a36Sopenharmony_ci		cond_resched();
248062306a36Sopenharmony_ci	}
248162306a36Sopenharmony_ci	return 0;
248262306a36Sopenharmony_ci}
248362306a36Sopenharmony_ci
248462306a36Sopenharmony_ci/*
248562306a36Sopenharmony_ci * Test the AEAD algorithm against the corresponding generic implementation, if
248662306a36Sopenharmony_ci * one is available.
248762306a36Sopenharmony_ci */
248862306a36Sopenharmony_cistatic int test_aead_vs_generic_impl(struct aead_extra_tests_ctx *ctx)
248962306a36Sopenharmony_ci{
249062306a36Sopenharmony_ci	struct crypto_aead *tfm = ctx->tfm;
249162306a36Sopenharmony_ci	const char *algname = crypto_aead_alg(tfm)->base.cra_name;
249262306a36Sopenharmony_ci	const char *driver = crypto_aead_driver_name(tfm);
249362306a36Sopenharmony_ci	const char *generic_driver = ctx->test_desc->generic_driver;
249462306a36Sopenharmony_ci	char _generic_driver[CRYPTO_MAX_ALG_NAME];
249562306a36Sopenharmony_ci	struct crypto_aead *generic_tfm = NULL;
249662306a36Sopenharmony_ci	struct aead_request *generic_req = NULL;
249762306a36Sopenharmony_ci	unsigned int i;
249862306a36Sopenharmony_ci	int err;
249962306a36Sopenharmony_ci
250062306a36Sopenharmony_ci	if (!generic_driver) { /* Use default naming convention? */
250162306a36Sopenharmony_ci		err = build_generic_driver_name(algname, _generic_driver);
250262306a36Sopenharmony_ci		if (err)
250362306a36Sopenharmony_ci			return err;
250462306a36Sopenharmony_ci		generic_driver = _generic_driver;
250562306a36Sopenharmony_ci	}
250662306a36Sopenharmony_ci
250762306a36Sopenharmony_ci	if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */
250862306a36Sopenharmony_ci		return 0;
250962306a36Sopenharmony_ci
251062306a36Sopenharmony_ci	generic_tfm = crypto_alloc_aead(generic_driver, 0, 0);
251162306a36Sopenharmony_ci	if (IS_ERR(generic_tfm)) {
251262306a36Sopenharmony_ci		err = PTR_ERR(generic_tfm);
251362306a36Sopenharmony_ci		if (err == -ENOENT) {
251462306a36Sopenharmony_ci			pr_warn("alg: aead: skipping comparison tests for %s because %s is unavailable\n",
251562306a36Sopenharmony_ci				driver, generic_driver);
251662306a36Sopenharmony_ci			return 0;
251762306a36Sopenharmony_ci		}
251862306a36Sopenharmony_ci		pr_err("alg: aead: error allocating %s (generic impl of %s): %d\n",
251962306a36Sopenharmony_ci		       generic_driver, algname, err);
252062306a36Sopenharmony_ci		return err;
252162306a36Sopenharmony_ci	}
252262306a36Sopenharmony_ci
252362306a36Sopenharmony_ci	generic_req = aead_request_alloc(generic_tfm, GFP_KERNEL);
252462306a36Sopenharmony_ci	if (!generic_req) {
252562306a36Sopenharmony_ci		err = -ENOMEM;
252662306a36Sopenharmony_ci		goto out;
252762306a36Sopenharmony_ci	}
252862306a36Sopenharmony_ci
252962306a36Sopenharmony_ci	/* Check the algorithm properties for consistency. */
253062306a36Sopenharmony_ci
253162306a36Sopenharmony_ci	if (crypto_aead_maxauthsize(tfm) !=
253262306a36Sopenharmony_ci	    crypto_aead_maxauthsize(generic_tfm)) {
253362306a36Sopenharmony_ci		pr_err("alg: aead: maxauthsize for %s (%u) doesn't match generic impl (%u)\n",
253462306a36Sopenharmony_ci		       driver, crypto_aead_maxauthsize(tfm),
253562306a36Sopenharmony_ci		       crypto_aead_maxauthsize(generic_tfm));
253662306a36Sopenharmony_ci		err = -EINVAL;
253762306a36Sopenharmony_ci		goto out;
253862306a36Sopenharmony_ci	}
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_ci	if (crypto_aead_ivsize(tfm) != crypto_aead_ivsize(generic_tfm)) {
254162306a36Sopenharmony_ci		pr_err("alg: aead: ivsize for %s (%u) doesn't match generic impl (%u)\n",
254262306a36Sopenharmony_ci		       driver, crypto_aead_ivsize(tfm),
254362306a36Sopenharmony_ci		       crypto_aead_ivsize(generic_tfm));
254462306a36Sopenharmony_ci		err = -EINVAL;
254562306a36Sopenharmony_ci		goto out;
254662306a36Sopenharmony_ci	}
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci	if (crypto_aead_blocksize(tfm) != crypto_aead_blocksize(generic_tfm)) {
254962306a36Sopenharmony_ci		pr_err("alg: aead: blocksize for %s (%u) doesn't match generic impl (%u)\n",
255062306a36Sopenharmony_ci		       driver, crypto_aead_blocksize(tfm),
255162306a36Sopenharmony_ci		       crypto_aead_blocksize(generic_tfm));
255262306a36Sopenharmony_ci		err = -EINVAL;
255362306a36Sopenharmony_ci		goto out;
255462306a36Sopenharmony_ci	}
255562306a36Sopenharmony_ci
255662306a36Sopenharmony_ci	/*
255762306a36Sopenharmony_ci	 * Now generate test vectors using the generic implementation, and test
255862306a36Sopenharmony_ci	 * the other implementation against them.
255962306a36Sopenharmony_ci	 */
256062306a36Sopenharmony_ci	for (i = 0; i < fuzz_iterations * 8; i++) {
256162306a36Sopenharmony_ci		generate_random_aead_testvec(&ctx->rng, generic_req, &ctx->vec,
256262306a36Sopenharmony_ci					     &ctx->test_desc->suite.aead,
256362306a36Sopenharmony_ci					     ctx->maxkeysize, ctx->maxdatasize,
256462306a36Sopenharmony_ci					     ctx->vec_name,
256562306a36Sopenharmony_ci					     sizeof(ctx->vec_name), false);
256662306a36Sopenharmony_ci		generate_random_testvec_config(&ctx->rng, &ctx->cfg,
256762306a36Sopenharmony_ci					       ctx->cfgname,
256862306a36Sopenharmony_ci					       sizeof(ctx->cfgname));
256962306a36Sopenharmony_ci		if (!ctx->vec.novrfy) {
257062306a36Sopenharmony_ci			err = test_aead_vec_cfg(ENCRYPT, &ctx->vec,
257162306a36Sopenharmony_ci						ctx->vec_name, &ctx->cfg,
257262306a36Sopenharmony_ci						ctx->req, ctx->tsgls);
257362306a36Sopenharmony_ci			if (err)
257462306a36Sopenharmony_ci				goto out;
257562306a36Sopenharmony_ci		}
257662306a36Sopenharmony_ci		if (ctx->vec.crypt_error == 0 || ctx->vec.novrfy) {
257762306a36Sopenharmony_ci			err = test_aead_vec_cfg(DECRYPT, &ctx->vec,
257862306a36Sopenharmony_ci						ctx->vec_name, &ctx->cfg,
257962306a36Sopenharmony_ci						ctx->req, ctx->tsgls);
258062306a36Sopenharmony_ci			if (err)
258162306a36Sopenharmony_ci				goto out;
258262306a36Sopenharmony_ci		}
258362306a36Sopenharmony_ci		cond_resched();
258462306a36Sopenharmony_ci	}
258562306a36Sopenharmony_ci	err = 0;
258662306a36Sopenharmony_ciout:
258762306a36Sopenharmony_ci	crypto_free_aead(generic_tfm);
258862306a36Sopenharmony_ci	aead_request_free(generic_req);
258962306a36Sopenharmony_ci	return err;
259062306a36Sopenharmony_ci}
259162306a36Sopenharmony_ci
259262306a36Sopenharmony_cistatic int test_aead_extra(const struct alg_test_desc *test_desc,
259362306a36Sopenharmony_ci			   struct aead_request *req,
259462306a36Sopenharmony_ci			   struct cipher_test_sglists *tsgls)
259562306a36Sopenharmony_ci{
259662306a36Sopenharmony_ci	struct aead_extra_tests_ctx *ctx;
259762306a36Sopenharmony_ci	unsigned int i;
259862306a36Sopenharmony_ci	int err;
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_ci	if (noextratests)
260162306a36Sopenharmony_ci		return 0;
260262306a36Sopenharmony_ci
260362306a36Sopenharmony_ci	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
260462306a36Sopenharmony_ci	if (!ctx)
260562306a36Sopenharmony_ci		return -ENOMEM;
260662306a36Sopenharmony_ci	init_rnd_state(&ctx->rng);
260762306a36Sopenharmony_ci	ctx->req = req;
260862306a36Sopenharmony_ci	ctx->tfm = crypto_aead_reqtfm(req);
260962306a36Sopenharmony_ci	ctx->test_desc = test_desc;
261062306a36Sopenharmony_ci	ctx->tsgls = tsgls;
261162306a36Sopenharmony_ci	ctx->maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
261262306a36Sopenharmony_ci	ctx->maxkeysize = 0;
261362306a36Sopenharmony_ci	for (i = 0; i < test_desc->suite.aead.count; i++)
261462306a36Sopenharmony_ci		ctx->maxkeysize = max_t(unsigned int, ctx->maxkeysize,
261562306a36Sopenharmony_ci					test_desc->suite.aead.vecs[i].klen);
261662306a36Sopenharmony_ci
261762306a36Sopenharmony_ci	ctx->vec.key = kmalloc(ctx->maxkeysize, GFP_KERNEL);
261862306a36Sopenharmony_ci	ctx->vec.iv = kmalloc(crypto_aead_ivsize(ctx->tfm), GFP_KERNEL);
261962306a36Sopenharmony_ci	ctx->vec.assoc = kmalloc(ctx->maxdatasize, GFP_KERNEL);
262062306a36Sopenharmony_ci	ctx->vec.ptext = kmalloc(ctx->maxdatasize, GFP_KERNEL);
262162306a36Sopenharmony_ci	ctx->vec.ctext = kmalloc(ctx->maxdatasize, GFP_KERNEL);
262262306a36Sopenharmony_ci	if (!ctx->vec.key || !ctx->vec.iv || !ctx->vec.assoc ||
262362306a36Sopenharmony_ci	    !ctx->vec.ptext || !ctx->vec.ctext) {
262462306a36Sopenharmony_ci		err = -ENOMEM;
262562306a36Sopenharmony_ci		goto out;
262662306a36Sopenharmony_ci	}
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci	err = test_aead_vs_generic_impl(ctx);
262962306a36Sopenharmony_ci	if (err)
263062306a36Sopenharmony_ci		goto out;
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	err = test_aead_inauthentic_inputs(ctx);
263362306a36Sopenharmony_ciout:
263462306a36Sopenharmony_ci	kfree(ctx->vec.key);
263562306a36Sopenharmony_ci	kfree(ctx->vec.iv);
263662306a36Sopenharmony_ci	kfree(ctx->vec.assoc);
263762306a36Sopenharmony_ci	kfree(ctx->vec.ptext);
263862306a36Sopenharmony_ci	kfree(ctx->vec.ctext);
263962306a36Sopenharmony_ci	kfree(ctx);
264062306a36Sopenharmony_ci	return err;
264162306a36Sopenharmony_ci}
264262306a36Sopenharmony_ci#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
264362306a36Sopenharmony_cistatic int test_aead_extra(const struct alg_test_desc *test_desc,
264462306a36Sopenharmony_ci			   struct aead_request *req,
264562306a36Sopenharmony_ci			   struct cipher_test_sglists *tsgls)
264662306a36Sopenharmony_ci{
264762306a36Sopenharmony_ci	return 0;
264862306a36Sopenharmony_ci}
264962306a36Sopenharmony_ci#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_cistatic int test_aead(int enc, const struct aead_test_suite *suite,
265262306a36Sopenharmony_ci		     struct aead_request *req,
265362306a36Sopenharmony_ci		     struct cipher_test_sglists *tsgls)
265462306a36Sopenharmony_ci{
265562306a36Sopenharmony_ci	unsigned int i;
265662306a36Sopenharmony_ci	int err;
265762306a36Sopenharmony_ci
265862306a36Sopenharmony_ci	for (i = 0; i < suite->count; i++) {
265962306a36Sopenharmony_ci		err = test_aead_vec(enc, &suite->vecs[i], i, req, tsgls);
266062306a36Sopenharmony_ci		if (err)
266162306a36Sopenharmony_ci			return err;
266262306a36Sopenharmony_ci		cond_resched();
266362306a36Sopenharmony_ci	}
266462306a36Sopenharmony_ci	return 0;
266562306a36Sopenharmony_ci}
266662306a36Sopenharmony_ci
266762306a36Sopenharmony_cistatic int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
266862306a36Sopenharmony_ci			 u32 type, u32 mask)
266962306a36Sopenharmony_ci{
267062306a36Sopenharmony_ci	const struct aead_test_suite *suite = &desc->suite.aead;
267162306a36Sopenharmony_ci	struct crypto_aead *tfm;
267262306a36Sopenharmony_ci	struct aead_request *req = NULL;
267362306a36Sopenharmony_ci	struct cipher_test_sglists *tsgls = NULL;
267462306a36Sopenharmony_ci	int err;
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci	if (suite->count <= 0) {
267762306a36Sopenharmony_ci		pr_err("alg: aead: empty test suite for %s\n", driver);
267862306a36Sopenharmony_ci		return -EINVAL;
267962306a36Sopenharmony_ci	}
268062306a36Sopenharmony_ci
268162306a36Sopenharmony_ci	tfm = crypto_alloc_aead(driver, type, mask);
268262306a36Sopenharmony_ci	if (IS_ERR(tfm)) {
268362306a36Sopenharmony_ci		pr_err("alg: aead: failed to allocate transform for %s: %ld\n",
268462306a36Sopenharmony_ci		       driver, PTR_ERR(tfm));
268562306a36Sopenharmony_ci		return PTR_ERR(tfm);
268662306a36Sopenharmony_ci	}
268762306a36Sopenharmony_ci	driver = crypto_aead_driver_name(tfm);
268862306a36Sopenharmony_ci
268962306a36Sopenharmony_ci	req = aead_request_alloc(tfm, GFP_KERNEL);
269062306a36Sopenharmony_ci	if (!req) {
269162306a36Sopenharmony_ci		pr_err("alg: aead: failed to allocate request for %s\n",
269262306a36Sopenharmony_ci		       driver);
269362306a36Sopenharmony_ci		err = -ENOMEM;
269462306a36Sopenharmony_ci		goto out;
269562306a36Sopenharmony_ci	}
269662306a36Sopenharmony_ci
269762306a36Sopenharmony_ci	tsgls = alloc_cipher_test_sglists();
269862306a36Sopenharmony_ci	if (!tsgls) {
269962306a36Sopenharmony_ci		pr_err("alg: aead: failed to allocate test buffers for %s\n",
270062306a36Sopenharmony_ci		       driver);
270162306a36Sopenharmony_ci		err = -ENOMEM;
270262306a36Sopenharmony_ci		goto out;
270362306a36Sopenharmony_ci	}
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_ci	err = test_aead(ENCRYPT, suite, req, tsgls);
270662306a36Sopenharmony_ci	if (err)
270762306a36Sopenharmony_ci		goto out;
270862306a36Sopenharmony_ci
270962306a36Sopenharmony_ci	err = test_aead(DECRYPT, suite, req, tsgls);
271062306a36Sopenharmony_ci	if (err)
271162306a36Sopenharmony_ci		goto out;
271262306a36Sopenharmony_ci
271362306a36Sopenharmony_ci	err = test_aead_extra(desc, req, tsgls);
271462306a36Sopenharmony_ciout:
271562306a36Sopenharmony_ci	free_cipher_test_sglists(tsgls);
271662306a36Sopenharmony_ci	aead_request_free(req);
271762306a36Sopenharmony_ci	crypto_free_aead(tfm);
271862306a36Sopenharmony_ci	return err;
271962306a36Sopenharmony_ci}
272062306a36Sopenharmony_ci
272162306a36Sopenharmony_cistatic int test_cipher(struct crypto_cipher *tfm, int enc,
272262306a36Sopenharmony_ci		       const struct cipher_testvec *template,
272362306a36Sopenharmony_ci		       unsigned int tcount)
272462306a36Sopenharmony_ci{
272562306a36Sopenharmony_ci	const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
272662306a36Sopenharmony_ci	unsigned int i, j, k;
272762306a36Sopenharmony_ci	char *q;
272862306a36Sopenharmony_ci	const char *e;
272962306a36Sopenharmony_ci	const char *input, *result;
273062306a36Sopenharmony_ci	void *data;
273162306a36Sopenharmony_ci	char *xbuf[XBUFSIZE];
273262306a36Sopenharmony_ci	int ret = -ENOMEM;
273362306a36Sopenharmony_ci
273462306a36Sopenharmony_ci	if (testmgr_alloc_buf(xbuf))
273562306a36Sopenharmony_ci		goto out_nobuf;
273662306a36Sopenharmony_ci
273762306a36Sopenharmony_ci	if (enc == ENCRYPT)
273862306a36Sopenharmony_ci	        e = "encryption";
273962306a36Sopenharmony_ci	else
274062306a36Sopenharmony_ci		e = "decryption";
274162306a36Sopenharmony_ci
274262306a36Sopenharmony_ci	j = 0;
274362306a36Sopenharmony_ci	for (i = 0; i < tcount; i++) {
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_ci		if (fips_enabled && template[i].fips_skip)
274662306a36Sopenharmony_ci			continue;
274762306a36Sopenharmony_ci
274862306a36Sopenharmony_ci		input  = enc ? template[i].ptext : template[i].ctext;
274962306a36Sopenharmony_ci		result = enc ? template[i].ctext : template[i].ptext;
275062306a36Sopenharmony_ci		j++;
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci		ret = -EINVAL;
275362306a36Sopenharmony_ci		if (WARN_ON(template[i].len > PAGE_SIZE))
275462306a36Sopenharmony_ci			goto out;
275562306a36Sopenharmony_ci
275662306a36Sopenharmony_ci		data = xbuf[0];
275762306a36Sopenharmony_ci		memcpy(data, input, template[i].len);
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci		crypto_cipher_clear_flags(tfm, ~0);
276062306a36Sopenharmony_ci		if (template[i].wk)
276162306a36Sopenharmony_ci			crypto_cipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
276262306a36Sopenharmony_ci
276362306a36Sopenharmony_ci		ret = crypto_cipher_setkey(tfm, template[i].key,
276462306a36Sopenharmony_ci					   template[i].klen);
276562306a36Sopenharmony_ci		if (ret) {
276662306a36Sopenharmony_ci			if (ret == template[i].setkey_error)
276762306a36Sopenharmony_ci				continue;
276862306a36Sopenharmony_ci			pr_err("alg: cipher: %s setkey failed on test vector %u; expected_error=%d, actual_error=%d, flags=%#x\n",
276962306a36Sopenharmony_ci			       algo, j, template[i].setkey_error, ret,
277062306a36Sopenharmony_ci			       crypto_cipher_get_flags(tfm));
277162306a36Sopenharmony_ci			goto out;
277262306a36Sopenharmony_ci		}
277362306a36Sopenharmony_ci		if (template[i].setkey_error) {
277462306a36Sopenharmony_ci			pr_err("alg: cipher: %s setkey unexpectedly succeeded on test vector %u; expected_error=%d\n",
277562306a36Sopenharmony_ci			       algo, j, template[i].setkey_error);
277662306a36Sopenharmony_ci			ret = -EINVAL;
277762306a36Sopenharmony_ci			goto out;
277862306a36Sopenharmony_ci		}
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci		for (k = 0; k < template[i].len;
278162306a36Sopenharmony_ci		     k += crypto_cipher_blocksize(tfm)) {
278262306a36Sopenharmony_ci			if (enc)
278362306a36Sopenharmony_ci				crypto_cipher_encrypt_one(tfm, data + k,
278462306a36Sopenharmony_ci							  data + k);
278562306a36Sopenharmony_ci			else
278662306a36Sopenharmony_ci				crypto_cipher_decrypt_one(tfm, data + k,
278762306a36Sopenharmony_ci							  data + k);
278862306a36Sopenharmony_ci		}
278962306a36Sopenharmony_ci
279062306a36Sopenharmony_ci		q = data;
279162306a36Sopenharmony_ci		if (memcmp(q, result, template[i].len)) {
279262306a36Sopenharmony_ci			printk(KERN_ERR "alg: cipher: Test %d failed "
279362306a36Sopenharmony_ci			       "on %s for %s\n", j, e, algo);
279462306a36Sopenharmony_ci			hexdump(q, template[i].len);
279562306a36Sopenharmony_ci			ret = -EINVAL;
279662306a36Sopenharmony_ci			goto out;
279762306a36Sopenharmony_ci		}
279862306a36Sopenharmony_ci	}
279962306a36Sopenharmony_ci
280062306a36Sopenharmony_ci	ret = 0;
280162306a36Sopenharmony_ci
280262306a36Sopenharmony_ciout:
280362306a36Sopenharmony_ci	testmgr_free_buf(xbuf);
280462306a36Sopenharmony_ciout_nobuf:
280562306a36Sopenharmony_ci	return ret;
280662306a36Sopenharmony_ci}
280762306a36Sopenharmony_ci
280862306a36Sopenharmony_cistatic int test_skcipher_vec_cfg(int enc, const struct cipher_testvec *vec,
280962306a36Sopenharmony_ci				 const char *vec_name,
281062306a36Sopenharmony_ci				 const struct testvec_config *cfg,
281162306a36Sopenharmony_ci				 struct skcipher_request *req,
281262306a36Sopenharmony_ci				 struct cipher_test_sglists *tsgls)
281362306a36Sopenharmony_ci{
281462306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
281562306a36Sopenharmony_ci	const unsigned int alignmask = crypto_skcipher_alignmask(tfm);
281662306a36Sopenharmony_ci	const unsigned int ivsize = crypto_skcipher_ivsize(tfm);
281762306a36Sopenharmony_ci	const char *driver = crypto_skcipher_driver_name(tfm);
281862306a36Sopenharmony_ci	const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags;
281962306a36Sopenharmony_ci	const char *op = enc ? "encryption" : "decryption";
282062306a36Sopenharmony_ci	DECLARE_CRYPTO_WAIT(wait);
282162306a36Sopenharmony_ci	u8 _iv[3 * (MAX_ALGAPI_ALIGNMASK + 1) + MAX_IVLEN];
282262306a36Sopenharmony_ci	u8 *iv = PTR_ALIGN(&_iv[0], 2 * (MAX_ALGAPI_ALIGNMASK + 1)) +
282362306a36Sopenharmony_ci		 cfg->iv_offset +
282462306a36Sopenharmony_ci		 (cfg->iv_offset_relative_to_alignmask ? alignmask : 0);
282562306a36Sopenharmony_ci	struct kvec input;
282662306a36Sopenharmony_ci	int err;
282762306a36Sopenharmony_ci
282862306a36Sopenharmony_ci	/* Set the key */
282962306a36Sopenharmony_ci	if (vec->wk)
283062306a36Sopenharmony_ci		crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
283162306a36Sopenharmony_ci	else
283262306a36Sopenharmony_ci		crypto_skcipher_clear_flags(tfm,
283362306a36Sopenharmony_ci					    CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
283462306a36Sopenharmony_ci	err = do_setkey(crypto_skcipher_setkey, tfm, vec->key, vec->klen,
283562306a36Sopenharmony_ci			cfg, alignmask);
283662306a36Sopenharmony_ci	if (err) {
283762306a36Sopenharmony_ci		if (err == vec->setkey_error)
283862306a36Sopenharmony_ci			return 0;
283962306a36Sopenharmony_ci		pr_err("alg: skcipher: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
284062306a36Sopenharmony_ci		       driver, vec_name, vec->setkey_error, err,
284162306a36Sopenharmony_ci		       crypto_skcipher_get_flags(tfm));
284262306a36Sopenharmony_ci		return err;
284362306a36Sopenharmony_ci	}
284462306a36Sopenharmony_ci	if (vec->setkey_error) {
284562306a36Sopenharmony_ci		pr_err("alg: skcipher: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
284662306a36Sopenharmony_ci		       driver, vec_name, vec->setkey_error);
284762306a36Sopenharmony_ci		return -EINVAL;
284862306a36Sopenharmony_ci	}
284962306a36Sopenharmony_ci
285062306a36Sopenharmony_ci	/* The IV must be copied to a buffer, as the algorithm may modify it */
285162306a36Sopenharmony_ci	if (ivsize) {
285262306a36Sopenharmony_ci		if (WARN_ON(ivsize > MAX_IVLEN))
285362306a36Sopenharmony_ci			return -EINVAL;
285462306a36Sopenharmony_ci		if (vec->generates_iv && !enc)
285562306a36Sopenharmony_ci			memcpy(iv, vec->iv_out, ivsize);
285662306a36Sopenharmony_ci		else if (vec->iv)
285762306a36Sopenharmony_ci			memcpy(iv, vec->iv, ivsize);
285862306a36Sopenharmony_ci		else
285962306a36Sopenharmony_ci			memset(iv, 0, ivsize);
286062306a36Sopenharmony_ci	} else {
286162306a36Sopenharmony_ci		if (vec->generates_iv) {
286262306a36Sopenharmony_ci			pr_err("alg: skcipher: %s has ivsize=0 but test vector %s generates IV!\n",
286362306a36Sopenharmony_ci			       driver, vec_name);
286462306a36Sopenharmony_ci			return -EINVAL;
286562306a36Sopenharmony_ci		}
286662306a36Sopenharmony_ci		iv = NULL;
286762306a36Sopenharmony_ci	}
286862306a36Sopenharmony_ci
286962306a36Sopenharmony_ci	/* Build the src/dst scatterlists */
287062306a36Sopenharmony_ci	input.iov_base = enc ? (void *)vec->ptext : (void *)vec->ctext;
287162306a36Sopenharmony_ci	input.iov_len = vec->len;
287262306a36Sopenharmony_ci	err = build_cipher_test_sglists(tsgls, cfg, alignmask,
287362306a36Sopenharmony_ci					vec->len, vec->len, &input, 1);
287462306a36Sopenharmony_ci	if (err) {
287562306a36Sopenharmony_ci		pr_err("alg: skcipher: %s %s: error preparing scatterlists for test vector %s, cfg=\"%s\"\n",
287662306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
287762306a36Sopenharmony_ci		return err;
287862306a36Sopenharmony_ci	}
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	/* Do the actual encryption or decryption */
288162306a36Sopenharmony_ci	testmgr_poison(req->__ctx, crypto_skcipher_reqsize(tfm));
288262306a36Sopenharmony_ci	skcipher_request_set_callback(req, req_flags, crypto_req_done, &wait);
288362306a36Sopenharmony_ci	skcipher_request_set_crypt(req, tsgls->src.sgl_ptr, tsgls->dst.sgl_ptr,
288462306a36Sopenharmony_ci				   vec->len, iv);
288562306a36Sopenharmony_ci	if (cfg->nosimd)
288662306a36Sopenharmony_ci		crypto_disable_simd_for_test();
288762306a36Sopenharmony_ci	err = enc ? crypto_skcipher_encrypt(req) : crypto_skcipher_decrypt(req);
288862306a36Sopenharmony_ci	if (cfg->nosimd)
288962306a36Sopenharmony_ci		crypto_reenable_simd_for_test();
289062306a36Sopenharmony_ci	err = crypto_wait_req(err, &wait);
289162306a36Sopenharmony_ci
289262306a36Sopenharmony_ci	/* Check that the algorithm didn't overwrite things it shouldn't have */
289362306a36Sopenharmony_ci	if (req->cryptlen != vec->len ||
289462306a36Sopenharmony_ci	    req->iv != iv ||
289562306a36Sopenharmony_ci	    req->src != tsgls->src.sgl_ptr ||
289662306a36Sopenharmony_ci	    req->dst != tsgls->dst.sgl_ptr ||
289762306a36Sopenharmony_ci	    crypto_skcipher_reqtfm(req) != tfm ||
289862306a36Sopenharmony_ci	    req->base.complete != crypto_req_done ||
289962306a36Sopenharmony_ci	    req->base.flags != req_flags ||
290062306a36Sopenharmony_ci	    req->base.data != &wait) {
290162306a36Sopenharmony_ci		pr_err("alg: skcipher: %s %s corrupted request struct on test vector %s, cfg=\"%s\"\n",
290262306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
290362306a36Sopenharmony_ci		if (req->cryptlen != vec->len)
290462306a36Sopenharmony_ci			pr_err("alg: skcipher: changed 'req->cryptlen'\n");
290562306a36Sopenharmony_ci		if (req->iv != iv)
290662306a36Sopenharmony_ci			pr_err("alg: skcipher: changed 'req->iv'\n");
290762306a36Sopenharmony_ci		if (req->src != tsgls->src.sgl_ptr)
290862306a36Sopenharmony_ci			pr_err("alg: skcipher: changed 'req->src'\n");
290962306a36Sopenharmony_ci		if (req->dst != tsgls->dst.sgl_ptr)
291062306a36Sopenharmony_ci			pr_err("alg: skcipher: changed 'req->dst'\n");
291162306a36Sopenharmony_ci		if (crypto_skcipher_reqtfm(req) != tfm)
291262306a36Sopenharmony_ci			pr_err("alg: skcipher: changed 'req->base.tfm'\n");
291362306a36Sopenharmony_ci		if (req->base.complete != crypto_req_done)
291462306a36Sopenharmony_ci			pr_err("alg: skcipher: changed 'req->base.complete'\n");
291562306a36Sopenharmony_ci		if (req->base.flags != req_flags)
291662306a36Sopenharmony_ci			pr_err("alg: skcipher: changed 'req->base.flags'\n");
291762306a36Sopenharmony_ci		if (req->base.data != &wait)
291862306a36Sopenharmony_ci			pr_err("alg: skcipher: changed 'req->base.data'\n");
291962306a36Sopenharmony_ci		return -EINVAL;
292062306a36Sopenharmony_ci	}
292162306a36Sopenharmony_ci	if (is_test_sglist_corrupted(&tsgls->src)) {
292262306a36Sopenharmony_ci		pr_err("alg: skcipher: %s %s corrupted src sgl on test vector %s, cfg=\"%s\"\n",
292362306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
292462306a36Sopenharmony_ci		return -EINVAL;
292562306a36Sopenharmony_ci	}
292662306a36Sopenharmony_ci	if (tsgls->dst.sgl_ptr != tsgls->src.sgl &&
292762306a36Sopenharmony_ci	    is_test_sglist_corrupted(&tsgls->dst)) {
292862306a36Sopenharmony_ci		pr_err("alg: skcipher: %s %s corrupted dst sgl on test vector %s, cfg=\"%s\"\n",
292962306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
293062306a36Sopenharmony_ci		return -EINVAL;
293162306a36Sopenharmony_ci	}
293262306a36Sopenharmony_ci
293362306a36Sopenharmony_ci	/* Check for success or failure */
293462306a36Sopenharmony_ci	if (err) {
293562306a36Sopenharmony_ci		if (err == vec->crypt_error)
293662306a36Sopenharmony_ci			return 0;
293762306a36Sopenharmony_ci		pr_err("alg: skcipher: %s %s failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
293862306a36Sopenharmony_ci		       driver, op, vec_name, vec->crypt_error, err, cfg->name);
293962306a36Sopenharmony_ci		return err;
294062306a36Sopenharmony_ci	}
294162306a36Sopenharmony_ci	if (vec->crypt_error) {
294262306a36Sopenharmony_ci		pr_err("alg: skcipher: %s %s unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
294362306a36Sopenharmony_ci		       driver, op, vec_name, vec->crypt_error, cfg->name);
294462306a36Sopenharmony_ci		return -EINVAL;
294562306a36Sopenharmony_ci	}
294662306a36Sopenharmony_ci
294762306a36Sopenharmony_ci	/* Check for the correct output (ciphertext or plaintext) */
294862306a36Sopenharmony_ci	err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext,
294962306a36Sopenharmony_ci				    vec->len, 0, true);
295062306a36Sopenharmony_ci	if (err == -EOVERFLOW) {
295162306a36Sopenharmony_ci		pr_err("alg: skcipher: %s %s overran dst buffer on test vector %s, cfg=\"%s\"\n",
295262306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
295362306a36Sopenharmony_ci		return err;
295462306a36Sopenharmony_ci	}
295562306a36Sopenharmony_ci	if (err) {
295662306a36Sopenharmony_ci		pr_err("alg: skcipher: %s %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
295762306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
295862306a36Sopenharmony_ci		return err;
295962306a36Sopenharmony_ci	}
296062306a36Sopenharmony_ci
296162306a36Sopenharmony_ci	/* If applicable, check that the algorithm generated the correct IV */
296262306a36Sopenharmony_ci	if (vec->iv_out && memcmp(iv, vec->iv_out, ivsize) != 0) {
296362306a36Sopenharmony_ci		pr_err("alg: skcipher: %s %s test failed (wrong output IV) on test vector %s, cfg=\"%s\"\n",
296462306a36Sopenharmony_ci		       driver, op, vec_name, cfg->name);
296562306a36Sopenharmony_ci		hexdump(iv, ivsize);
296662306a36Sopenharmony_ci		return -EINVAL;
296762306a36Sopenharmony_ci	}
296862306a36Sopenharmony_ci
296962306a36Sopenharmony_ci	return 0;
297062306a36Sopenharmony_ci}
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_cistatic int test_skcipher_vec(int enc, const struct cipher_testvec *vec,
297362306a36Sopenharmony_ci			     unsigned int vec_num,
297462306a36Sopenharmony_ci			     struct skcipher_request *req,
297562306a36Sopenharmony_ci			     struct cipher_test_sglists *tsgls)
297662306a36Sopenharmony_ci{
297762306a36Sopenharmony_ci	char vec_name[16];
297862306a36Sopenharmony_ci	unsigned int i;
297962306a36Sopenharmony_ci	int err;
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_ci	if (fips_enabled && vec->fips_skip)
298262306a36Sopenharmony_ci		return 0;
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	sprintf(vec_name, "%u", vec_num);
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) {
298762306a36Sopenharmony_ci		err = test_skcipher_vec_cfg(enc, vec, vec_name,
298862306a36Sopenharmony_ci					    &default_cipher_testvec_configs[i],
298962306a36Sopenharmony_ci					    req, tsgls);
299062306a36Sopenharmony_ci		if (err)
299162306a36Sopenharmony_ci			return err;
299262306a36Sopenharmony_ci	}
299362306a36Sopenharmony_ci
299462306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
299562306a36Sopenharmony_ci	if (!noextratests) {
299662306a36Sopenharmony_ci		struct rnd_state rng;
299762306a36Sopenharmony_ci		struct testvec_config cfg;
299862306a36Sopenharmony_ci		char cfgname[TESTVEC_CONFIG_NAMELEN];
299962306a36Sopenharmony_ci
300062306a36Sopenharmony_ci		init_rnd_state(&rng);
300162306a36Sopenharmony_ci
300262306a36Sopenharmony_ci		for (i = 0; i < fuzz_iterations; i++) {
300362306a36Sopenharmony_ci			generate_random_testvec_config(&rng, &cfg, cfgname,
300462306a36Sopenharmony_ci						       sizeof(cfgname));
300562306a36Sopenharmony_ci			err = test_skcipher_vec_cfg(enc, vec, vec_name,
300662306a36Sopenharmony_ci						    &cfg, req, tsgls);
300762306a36Sopenharmony_ci			if (err)
300862306a36Sopenharmony_ci				return err;
300962306a36Sopenharmony_ci			cond_resched();
301062306a36Sopenharmony_ci		}
301162306a36Sopenharmony_ci	}
301262306a36Sopenharmony_ci#endif
301362306a36Sopenharmony_ci	return 0;
301462306a36Sopenharmony_ci}
301562306a36Sopenharmony_ci
301662306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
301762306a36Sopenharmony_ci/*
301862306a36Sopenharmony_ci * Generate a symmetric cipher test vector from the given implementation.
301962306a36Sopenharmony_ci * Assumes the buffers in 'vec' were already allocated.
302062306a36Sopenharmony_ci */
302162306a36Sopenharmony_cistatic void generate_random_cipher_testvec(struct rnd_state *rng,
302262306a36Sopenharmony_ci					   struct skcipher_request *req,
302362306a36Sopenharmony_ci					   struct cipher_testvec *vec,
302462306a36Sopenharmony_ci					   unsigned int maxdatasize,
302562306a36Sopenharmony_ci					   char *name, size_t max_namelen)
302662306a36Sopenharmony_ci{
302762306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
302862306a36Sopenharmony_ci	const unsigned int maxkeysize = crypto_skcipher_max_keysize(tfm);
302962306a36Sopenharmony_ci	const unsigned int ivsize = crypto_skcipher_ivsize(tfm);
303062306a36Sopenharmony_ci	struct scatterlist src, dst;
303162306a36Sopenharmony_ci	u8 iv[MAX_IVLEN];
303262306a36Sopenharmony_ci	DECLARE_CRYPTO_WAIT(wait);
303362306a36Sopenharmony_ci
303462306a36Sopenharmony_ci	/* Key: length in [0, maxkeysize], but usually choose maxkeysize */
303562306a36Sopenharmony_ci	vec->klen = maxkeysize;
303662306a36Sopenharmony_ci	if (prandom_u32_below(rng, 4) == 0)
303762306a36Sopenharmony_ci		vec->klen = prandom_u32_below(rng, maxkeysize + 1);
303862306a36Sopenharmony_ci	generate_random_bytes(rng, (u8 *)vec->key, vec->klen);
303962306a36Sopenharmony_ci	vec->setkey_error = crypto_skcipher_setkey(tfm, vec->key, vec->klen);
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_ci	/* IV */
304262306a36Sopenharmony_ci	generate_random_bytes(rng, (u8 *)vec->iv, ivsize);
304362306a36Sopenharmony_ci
304462306a36Sopenharmony_ci	/* Plaintext */
304562306a36Sopenharmony_ci	vec->len = generate_random_length(rng, maxdatasize);
304662306a36Sopenharmony_ci	generate_random_bytes(rng, (u8 *)vec->ptext, vec->len);
304762306a36Sopenharmony_ci
304862306a36Sopenharmony_ci	/* If the key couldn't be set, no need to continue to encrypt. */
304962306a36Sopenharmony_ci	if (vec->setkey_error)
305062306a36Sopenharmony_ci		goto done;
305162306a36Sopenharmony_ci
305262306a36Sopenharmony_ci	/* Ciphertext */
305362306a36Sopenharmony_ci	sg_init_one(&src, vec->ptext, vec->len);
305462306a36Sopenharmony_ci	sg_init_one(&dst, vec->ctext, vec->len);
305562306a36Sopenharmony_ci	memcpy(iv, vec->iv, ivsize);
305662306a36Sopenharmony_ci	skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
305762306a36Sopenharmony_ci	skcipher_request_set_crypt(req, &src, &dst, vec->len, iv);
305862306a36Sopenharmony_ci	vec->crypt_error = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
305962306a36Sopenharmony_ci	if (vec->crypt_error != 0) {
306062306a36Sopenharmony_ci		/*
306162306a36Sopenharmony_ci		 * The only acceptable error here is for an invalid length, so
306262306a36Sopenharmony_ci		 * skcipher decryption should fail with the same error too.
306362306a36Sopenharmony_ci		 * We'll test for this.  But to keep the API usage well-defined,
306462306a36Sopenharmony_ci		 * explicitly initialize the ciphertext buffer too.
306562306a36Sopenharmony_ci		 */
306662306a36Sopenharmony_ci		memset((u8 *)vec->ctext, 0, vec->len);
306762306a36Sopenharmony_ci	}
306862306a36Sopenharmony_cidone:
306962306a36Sopenharmony_ci	snprintf(name, max_namelen, "\"random: len=%u klen=%u\"",
307062306a36Sopenharmony_ci		 vec->len, vec->klen);
307162306a36Sopenharmony_ci}
307262306a36Sopenharmony_ci
307362306a36Sopenharmony_ci/*
307462306a36Sopenharmony_ci * Test the skcipher algorithm represented by @req against the corresponding
307562306a36Sopenharmony_ci * generic implementation, if one is available.
307662306a36Sopenharmony_ci */
307762306a36Sopenharmony_cistatic int test_skcipher_vs_generic_impl(const char *generic_driver,
307862306a36Sopenharmony_ci					 struct skcipher_request *req,
307962306a36Sopenharmony_ci					 struct cipher_test_sglists *tsgls)
308062306a36Sopenharmony_ci{
308162306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
308262306a36Sopenharmony_ci	const unsigned int maxkeysize = crypto_skcipher_max_keysize(tfm);
308362306a36Sopenharmony_ci	const unsigned int ivsize = crypto_skcipher_ivsize(tfm);
308462306a36Sopenharmony_ci	const unsigned int blocksize = crypto_skcipher_blocksize(tfm);
308562306a36Sopenharmony_ci	const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
308662306a36Sopenharmony_ci	const char *algname = crypto_skcipher_alg(tfm)->base.cra_name;
308762306a36Sopenharmony_ci	const char *driver = crypto_skcipher_driver_name(tfm);
308862306a36Sopenharmony_ci	struct rnd_state rng;
308962306a36Sopenharmony_ci	char _generic_driver[CRYPTO_MAX_ALG_NAME];
309062306a36Sopenharmony_ci	struct crypto_skcipher *generic_tfm = NULL;
309162306a36Sopenharmony_ci	struct skcipher_request *generic_req = NULL;
309262306a36Sopenharmony_ci	unsigned int i;
309362306a36Sopenharmony_ci	struct cipher_testvec vec = { 0 };
309462306a36Sopenharmony_ci	char vec_name[64];
309562306a36Sopenharmony_ci	struct testvec_config *cfg;
309662306a36Sopenharmony_ci	char cfgname[TESTVEC_CONFIG_NAMELEN];
309762306a36Sopenharmony_ci	int err;
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ci	if (noextratests)
310062306a36Sopenharmony_ci		return 0;
310162306a36Sopenharmony_ci
310262306a36Sopenharmony_ci	/* Keywrap isn't supported here yet as it handles its IV differently. */
310362306a36Sopenharmony_ci	if (strncmp(algname, "kw(", 3) == 0)
310462306a36Sopenharmony_ci		return 0;
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci	init_rnd_state(&rng);
310762306a36Sopenharmony_ci
310862306a36Sopenharmony_ci	if (!generic_driver) { /* Use default naming convention? */
310962306a36Sopenharmony_ci		err = build_generic_driver_name(algname, _generic_driver);
311062306a36Sopenharmony_ci		if (err)
311162306a36Sopenharmony_ci			return err;
311262306a36Sopenharmony_ci		generic_driver = _generic_driver;
311362306a36Sopenharmony_ci	}
311462306a36Sopenharmony_ci
311562306a36Sopenharmony_ci	if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */
311662306a36Sopenharmony_ci		return 0;
311762306a36Sopenharmony_ci
311862306a36Sopenharmony_ci	generic_tfm = crypto_alloc_skcipher(generic_driver, 0, 0);
311962306a36Sopenharmony_ci	if (IS_ERR(generic_tfm)) {
312062306a36Sopenharmony_ci		err = PTR_ERR(generic_tfm);
312162306a36Sopenharmony_ci		if (err == -ENOENT) {
312262306a36Sopenharmony_ci			pr_warn("alg: skcipher: skipping comparison tests for %s because %s is unavailable\n",
312362306a36Sopenharmony_ci				driver, generic_driver);
312462306a36Sopenharmony_ci			return 0;
312562306a36Sopenharmony_ci		}
312662306a36Sopenharmony_ci		pr_err("alg: skcipher: error allocating %s (generic impl of %s): %d\n",
312762306a36Sopenharmony_ci		       generic_driver, algname, err);
312862306a36Sopenharmony_ci		return err;
312962306a36Sopenharmony_ci	}
313062306a36Sopenharmony_ci
313162306a36Sopenharmony_ci	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
313262306a36Sopenharmony_ci	if (!cfg) {
313362306a36Sopenharmony_ci		err = -ENOMEM;
313462306a36Sopenharmony_ci		goto out;
313562306a36Sopenharmony_ci	}
313662306a36Sopenharmony_ci
313762306a36Sopenharmony_ci	generic_req = skcipher_request_alloc(generic_tfm, GFP_KERNEL);
313862306a36Sopenharmony_ci	if (!generic_req) {
313962306a36Sopenharmony_ci		err = -ENOMEM;
314062306a36Sopenharmony_ci		goto out;
314162306a36Sopenharmony_ci	}
314262306a36Sopenharmony_ci
314362306a36Sopenharmony_ci	/* Check the algorithm properties for consistency. */
314462306a36Sopenharmony_ci
314562306a36Sopenharmony_ci	if (crypto_skcipher_min_keysize(tfm) !=
314662306a36Sopenharmony_ci	    crypto_skcipher_min_keysize(generic_tfm)) {
314762306a36Sopenharmony_ci		pr_err("alg: skcipher: min keysize for %s (%u) doesn't match generic impl (%u)\n",
314862306a36Sopenharmony_ci		       driver, crypto_skcipher_min_keysize(tfm),
314962306a36Sopenharmony_ci		       crypto_skcipher_min_keysize(generic_tfm));
315062306a36Sopenharmony_ci		err = -EINVAL;
315162306a36Sopenharmony_ci		goto out;
315262306a36Sopenharmony_ci	}
315362306a36Sopenharmony_ci
315462306a36Sopenharmony_ci	if (maxkeysize != crypto_skcipher_max_keysize(generic_tfm)) {
315562306a36Sopenharmony_ci		pr_err("alg: skcipher: max keysize for %s (%u) doesn't match generic impl (%u)\n",
315662306a36Sopenharmony_ci		       driver, maxkeysize,
315762306a36Sopenharmony_ci		       crypto_skcipher_max_keysize(generic_tfm));
315862306a36Sopenharmony_ci		err = -EINVAL;
315962306a36Sopenharmony_ci		goto out;
316062306a36Sopenharmony_ci	}
316162306a36Sopenharmony_ci
316262306a36Sopenharmony_ci	if (ivsize != crypto_skcipher_ivsize(generic_tfm)) {
316362306a36Sopenharmony_ci		pr_err("alg: skcipher: ivsize for %s (%u) doesn't match generic impl (%u)\n",
316462306a36Sopenharmony_ci		       driver, ivsize, crypto_skcipher_ivsize(generic_tfm));
316562306a36Sopenharmony_ci		err = -EINVAL;
316662306a36Sopenharmony_ci		goto out;
316762306a36Sopenharmony_ci	}
316862306a36Sopenharmony_ci
316962306a36Sopenharmony_ci	if (blocksize != crypto_skcipher_blocksize(generic_tfm)) {
317062306a36Sopenharmony_ci		pr_err("alg: skcipher: blocksize for %s (%u) doesn't match generic impl (%u)\n",
317162306a36Sopenharmony_ci		       driver, blocksize,
317262306a36Sopenharmony_ci		       crypto_skcipher_blocksize(generic_tfm));
317362306a36Sopenharmony_ci		err = -EINVAL;
317462306a36Sopenharmony_ci		goto out;
317562306a36Sopenharmony_ci	}
317662306a36Sopenharmony_ci
317762306a36Sopenharmony_ci	/*
317862306a36Sopenharmony_ci	 * Now generate test vectors using the generic implementation, and test
317962306a36Sopenharmony_ci	 * the other implementation against them.
318062306a36Sopenharmony_ci	 */
318162306a36Sopenharmony_ci
318262306a36Sopenharmony_ci	vec.key = kmalloc(maxkeysize, GFP_KERNEL);
318362306a36Sopenharmony_ci	vec.iv = kmalloc(ivsize, GFP_KERNEL);
318462306a36Sopenharmony_ci	vec.ptext = kmalloc(maxdatasize, GFP_KERNEL);
318562306a36Sopenharmony_ci	vec.ctext = kmalloc(maxdatasize, GFP_KERNEL);
318662306a36Sopenharmony_ci	if (!vec.key || !vec.iv || !vec.ptext || !vec.ctext) {
318762306a36Sopenharmony_ci		err = -ENOMEM;
318862306a36Sopenharmony_ci		goto out;
318962306a36Sopenharmony_ci	}
319062306a36Sopenharmony_ci
319162306a36Sopenharmony_ci	for (i = 0; i < fuzz_iterations * 8; i++) {
319262306a36Sopenharmony_ci		generate_random_cipher_testvec(&rng, generic_req, &vec,
319362306a36Sopenharmony_ci					       maxdatasize,
319462306a36Sopenharmony_ci					       vec_name, sizeof(vec_name));
319562306a36Sopenharmony_ci		generate_random_testvec_config(&rng, cfg, cfgname,
319662306a36Sopenharmony_ci					       sizeof(cfgname));
319762306a36Sopenharmony_ci
319862306a36Sopenharmony_ci		err = test_skcipher_vec_cfg(ENCRYPT, &vec, vec_name,
319962306a36Sopenharmony_ci					    cfg, req, tsgls);
320062306a36Sopenharmony_ci		if (err)
320162306a36Sopenharmony_ci			goto out;
320262306a36Sopenharmony_ci		err = test_skcipher_vec_cfg(DECRYPT, &vec, vec_name,
320362306a36Sopenharmony_ci					    cfg, req, tsgls);
320462306a36Sopenharmony_ci		if (err)
320562306a36Sopenharmony_ci			goto out;
320662306a36Sopenharmony_ci		cond_resched();
320762306a36Sopenharmony_ci	}
320862306a36Sopenharmony_ci	err = 0;
320962306a36Sopenharmony_ciout:
321062306a36Sopenharmony_ci	kfree(cfg);
321162306a36Sopenharmony_ci	kfree(vec.key);
321262306a36Sopenharmony_ci	kfree(vec.iv);
321362306a36Sopenharmony_ci	kfree(vec.ptext);
321462306a36Sopenharmony_ci	kfree(vec.ctext);
321562306a36Sopenharmony_ci	crypto_free_skcipher(generic_tfm);
321662306a36Sopenharmony_ci	skcipher_request_free(generic_req);
321762306a36Sopenharmony_ci	return err;
321862306a36Sopenharmony_ci}
321962306a36Sopenharmony_ci#else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
322062306a36Sopenharmony_cistatic int test_skcipher_vs_generic_impl(const char *generic_driver,
322162306a36Sopenharmony_ci					 struct skcipher_request *req,
322262306a36Sopenharmony_ci					 struct cipher_test_sglists *tsgls)
322362306a36Sopenharmony_ci{
322462306a36Sopenharmony_ci	return 0;
322562306a36Sopenharmony_ci}
322662306a36Sopenharmony_ci#endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
322762306a36Sopenharmony_ci
322862306a36Sopenharmony_cistatic int test_skcipher(int enc, const struct cipher_test_suite *suite,
322962306a36Sopenharmony_ci			 struct skcipher_request *req,
323062306a36Sopenharmony_ci			 struct cipher_test_sglists *tsgls)
323162306a36Sopenharmony_ci{
323262306a36Sopenharmony_ci	unsigned int i;
323362306a36Sopenharmony_ci	int err;
323462306a36Sopenharmony_ci
323562306a36Sopenharmony_ci	for (i = 0; i < suite->count; i++) {
323662306a36Sopenharmony_ci		err = test_skcipher_vec(enc, &suite->vecs[i], i, req, tsgls);
323762306a36Sopenharmony_ci		if (err)
323862306a36Sopenharmony_ci			return err;
323962306a36Sopenharmony_ci		cond_resched();
324062306a36Sopenharmony_ci	}
324162306a36Sopenharmony_ci	return 0;
324262306a36Sopenharmony_ci}
324362306a36Sopenharmony_ci
324462306a36Sopenharmony_cistatic int alg_test_skcipher(const struct alg_test_desc *desc,
324562306a36Sopenharmony_ci			     const char *driver, u32 type, u32 mask)
324662306a36Sopenharmony_ci{
324762306a36Sopenharmony_ci	const struct cipher_test_suite *suite = &desc->suite.cipher;
324862306a36Sopenharmony_ci	struct crypto_skcipher *tfm;
324962306a36Sopenharmony_ci	struct skcipher_request *req = NULL;
325062306a36Sopenharmony_ci	struct cipher_test_sglists *tsgls = NULL;
325162306a36Sopenharmony_ci	int err;
325262306a36Sopenharmony_ci
325362306a36Sopenharmony_ci	if (suite->count <= 0) {
325462306a36Sopenharmony_ci		pr_err("alg: skcipher: empty test suite for %s\n", driver);
325562306a36Sopenharmony_ci		return -EINVAL;
325662306a36Sopenharmony_ci	}
325762306a36Sopenharmony_ci
325862306a36Sopenharmony_ci	tfm = crypto_alloc_skcipher(driver, type, mask);
325962306a36Sopenharmony_ci	if (IS_ERR(tfm)) {
326062306a36Sopenharmony_ci		pr_err("alg: skcipher: failed to allocate transform for %s: %ld\n",
326162306a36Sopenharmony_ci		       driver, PTR_ERR(tfm));
326262306a36Sopenharmony_ci		return PTR_ERR(tfm);
326362306a36Sopenharmony_ci	}
326462306a36Sopenharmony_ci	driver = crypto_skcipher_driver_name(tfm);
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci	req = skcipher_request_alloc(tfm, GFP_KERNEL);
326762306a36Sopenharmony_ci	if (!req) {
326862306a36Sopenharmony_ci		pr_err("alg: skcipher: failed to allocate request for %s\n",
326962306a36Sopenharmony_ci		       driver);
327062306a36Sopenharmony_ci		err = -ENOMEM;
327162306a36Sopenharmony_ci		goto out;
327262306a36Sopenharmony_ci	}
327362306a36Sopenharmony_ci
327462306a36Sopenharmony_ci	tsgls = alloc_cipher_test_sglists();
327562306a36Sopenharmony_ci	if (!tsgls) {
327662306a36Sopenharmony_ci		pr_err("alg: skcipher: failed to allocate test buffers for %s\n",
327762306a36Sopenharmony_ci		       driver);
327862306a36Sopenharmony_ci		err = -ENOMEM;
327962306a36Sopenharmony_ci		goto out;
328062306a36Sopenharmony_ci	}
328162306a36Sopenharmony_ci
328262306a36Sopenharmony_ci	err = test_skcipher(ENCRYPT, suite, req, tsgls);
328362306a36Sopenharmony_ci	if (err)
328462306a36Sopenharmony_ci		goto out;
328562306a36Sopenharmony_ci
328662306a36Sopenharmony_ci	err = test_skcipher(DECRYPT, suite, req, tsgls);
328762306a36Sopenharmony_ci	if (err)
328862306a36Sopenharmony_ci		goto out;
328962306a36Sopenharmony_ci
329062306a36Sopenharmony_ci	err = test_skcipher_vs_generic_impl(desc->generic_driver, req, tsgls);
329162306a36Sopenharmony_ciout:
329262306a36Sopenharmony_ci	free_cipher_test_sglists(tsgls);
329362306a36Sopenharmony_ci	skcipher_request_free(req);
329462306a36Sopenharmony_ci	crypto_free_skcipher(tfm);
329562306a36Sopenharmony_ci	return err;
329662306a36Sopenharmony_ci}
329762306a36Sopenharmony_ci
329862306a36Sopenharmony_cistatic int test_comp(struct crypto_comp *tfm,
329962306a36Sopenharmony_ci		     const struct comp_testvec *ctemplate,
330062306a36Sopenharmony_ci		     const struct comp_testvec *dtemplate,
330162306a36Sopenharmony_ci		     int ctcount, int dtcount)
330262306a36Sopenharmony_ci{
330362306a36Sopenharmony_ci	const char *algo = crypto_tfm_alg_driver_name(crypto_comp_tfm(tfm));
330462306a36Sopenharmony_ci	char *output, *decomp_output;
330562306a36Sopenharmony_ci	unsigned int i;
330662306a36Sopenharmony_ci	int ret;
330762306a36Sopenharmony_ci
330862306a36Sopenharmony_ci	output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
330962306a36Sopenharmony_ci	if (!output)
331062306a36Sopenharmony_ci		return -ENOMEM;
331162306a36Sopenharmony_ci
331262306a36Sopenharmony_ci	decomp_output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
331362306a36Sopenharmony_ci	if (!decomp_output) {
331462306a36Sopenharmony_ci		kfree(output);
331562306a36Sopenharmony_ci		return -ENOMEM;
331662306a36Sopenharmony_ci	}
331762306a36Sopenharmony_ci
331862306a36Sopenharmony_ci	for (i = 0; i < ctcount; i++) {
331962306a36Sopenharmony_ci		int ilen;
332062306a36Sopenharmony_ci		unsigned int dlen = COMP_BUF_SIZE;
332162306a36Sopenharmony_ci
332262306a36Sopenharmony_ci		memset(output, 0, COMP_BUF_SIZE);
332362306a36Sopenharmony_ci		memset(decomp_output, 0, COMP_BUF_SIZE);
332462306a36Sopenharmony_ci
332562306a36Sopenharmony_ci		ilen = ctemplate[i].inlen;
332662306a36Sopenharmony_ci		ret = crypto_comp_compress(tfm, ctemplate[i].input,
332762306a36Sopenharmony_ci					   ilen, output, &dlen);
332862306a36Sopenharmony_ci		if (ret) {
332962306a36Sopenharmony_ci			printk(KERN_ERR "alg: comp: compression failed "
333062306a36Sopenharmony_ci			       "on test %d for %s: ret=%d\n", i + 1, algo,
333162306a36Sopenharmony_ci			       -ret);
333262306a36Sopenharmony_ci			goto out;
333362306a36Sopenharmony_ci		}
333462306a36Sopenharmony_ci
333562306a36Sopenharmony_ci		ilen = dlen;
333662306a36Sopenharmony_ci		dlen = COMP_BUF_SIZE;
333762306a36Sopenharmony_ci		ret = crypto_comp_decompress(tfm, output,
333862306a36Sopenharmony_ci					     ilen, decomp_output, &dlen);
333962306a36Sopenharmony_ci		if (ret) {
334062306a36Sopenharmony_ci			pr_err("alg: comp: compression failed: decompress: on test %d for %s failed: ret=%d\n",
334162306a36Sopenharmony_ci			       i + 1, algo, -ret);
334262306a36Sopenharmony_ci			goto out;
334362306a36Sopenharmony_ci		}
334462306a36Sopenharmony_ci
334562306a36Sopenharmony_ci		if (dlen != ctemplate[i].inlen) {
334662306a36Sopenharmony_ci			printk(KERN_ERR "alg: comp: Compression test %d "
334762306a36Sopenharmony_ci			       "failed for %s: output len = %d\n", i + 1, algo,
334862306a36Sopenharmony_ci			       dlen);
334962306a36Sopenharmony_ci			ret = -EINVAL;
335062306a36Sopenharmony_ci			goto out;
335162306a36Sopenharmony_ci		}
335262306a36Sopenharmony_ci
335362306a36Sopenharmony_ci		if (memcmp(decomp_output, ctemplate[i].input,
335462306a36Sopenharmony_ci			   ctemplate[i].inlen)) {
335562306a36Sopenharmony_ci			pr_err("alg: comp: compression failed: output differs: on test %d for %s\n",
335662306a36Sopenharmony_ci			       i + 1, algo);
335762306a36Sopenharmony_ci			hexdump(decomp_output, dlen);
335862306a36Sopenharmony_ci			ret = -EINVAL;
335962306a36Sopenharmony_ci			goto out;
336062306a36Sopenharmony_ci		}
336162306a36Sopenharmony_ci	}
336262306a36Sopenharmony_ci
336362306a36Sopenharmony_ci	for (i = 0; i < dtcount; i++) {
336462306a36Sopenharmony_ci		int ilen;
336562306a36Sopenharmony_ci		unsigned int dlen = COMP_BUF_SIZE;
336662306a36Sopenharmony_ci
336762306a36Sopenharmony_ci		memset(decomp_output, 0, COMP_BUF_SIZE);
336862306a36Sopenharmony_ci
336962306a36Sopenharmony_ci		ilen = dtemplate[i].inlen;
337062306a36Sopenharmony_ci		ret = crypto_comp_decompress(tfm, dtemplate[i].input,
337162306a36Sopenharmony_ci					     ilen, decomp_output, &dlen);
337262306a36Sopenharmony_ci		if (ret) {
337362306a36Sopenharmony_ci			printk(KERN_ERR "alg: comp: decompression failed "
337462306a36Sopenharmony_ci			       "on test %d for %s: ret=%d\n", i + 1, algo,
337562306a36Sopenharmony_ci			       -ret);
337662306a36Sopenharmony_ci			goto out;
337762306a36Sopenharmony_ci		}
337862306a36Sopenharmony_ci
337962306a36Sopenharmony_ci		if (dlen != dtemplate[i].outlen) {
338062306a36Sopenharmony_ci			printk(KERN_ERR "alg: comp: Decompression test %d "
338162306a36Sopenharmony_ci			       "failed for %s: output len = %d\n", i + 1, algo,
338262306a36Sopenharmony_ci			       dlen);
338362306a36Sopenharmony_ci			ret = -EINVAL;
338462306a36Sopenharmony_ci			goto out;
338562306a36Sopenharmony_ci		}
338662306a36Sopenharmony_ci
338762306a36Sopenharmony_ci		if (memcmp(decomp_output, dtemplate[i].output, dlen)) {
338862306a36Sopenharmony_ci			printk(KERN_ERR "alg: comp: Decompression test %d "
338962306a36Sopenharmony_ci			       "failed for %s\n", i + 1, algo);
339062306a36Sopenharmony_ci			hexdump(decomp_output, dlen);
339162306a36Sopenharmony_ci			ret = -EINVAL;
339262306a36Sopenharmony_ci			goto out;
339362306a36Sopenharmony_ci		}
339462306a36Sopenharmony_ci	}
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_ci	ret = 0;
339762306a36Sopenharmony_ci
339862306a36Sopenharmony_ciout:
339962306a36Sopenharmony_ci	kfree(decomp_output);
340062306a36Sopenharmony_ci	kfree(output);
340162306a36Sopenharmony_ci	return ret;
340262306a36Sopenharmony_ci}
340362306a36Sopenharmony_ci
340462306a36Sopenharmony_cistatic int test_acomp(struct crypto_acomp *tfm,
340562306a36Sopenharmony_ci		      const struct comp_testvec *ctemplate,
340662306a36Sopenharmony_ci		      const struct comp_testvec *dtemplate,
340762306a36Sopenharmony_ci		      int ctcount, int dtcount)
340862306a36Sopenharmony_ci{
340962306a36Sopenharmony_ci	const char *algo = crypto_tfm_alg_driver_name(crypto_acomp_tfm(tfm));
341062306a36Sopenharmony_ci	unsigned int i;
341162306a36Sopenharmony_ci	char *output, *decomp_out;
341262306a36Sopenharmony_ci	int ret;
341362306a36Sopenharmony_ci	struct scatterlist src, dst;
341462306a36Sopenharmony_ci	struct acomp_req *req;
341562306a36Sopenharmony_ci	struct crypto_wait wait;
341662306a36Sopenharmony_ci
341762306a36Sopenharmony_ci	output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
341862306a36Sopenharmony_ci	if (!output)
341962306a36Sopenharmony_ci		return -ENOMEM;
342062306a36Sopenharmony_ci
342162306a36Sopenharmony_ci	decomp_out = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
342262306a36Sopenharmony_ci	if (!decomp_out) {
342362306a36Sopenharmony_ci		kfree(output);
342462306a36Sopenharmony_ci		return -ENOMEM;
342562306a36Sopenharmony_ci	}
342662306a36Sopenharmony_ci
342762306a36Sopenharmony_ci	for (i = 0; i < ctcount; i++) {
342862306a36Sopenharmony_ci		unsigned int dlen = COMP_BUF_SIZE;
342962306a36Sopenharmony_ci		int ilen = ctemplate[i].inlen;
343062306a36Sopenharmony_ci		void *input_vec;
343162306a36Sopenharmony_ci
343262306a36Sopenharmony_ci		input_vec = kmemdup(ctemplate[i].input, ilen, GFP_KERNEL);
343362306a36Sopenharmony_ci		if (!input_vec) {
343462306a36Sopenharmony_ci			ret = -ENOMEM;
343562306a36Sopenharmony_ci			goto out;
343662306a36Sopenharmony_ci		}
343762306a36Sopenharmony_ci
343862306a36Sopenharmony_ci		memset(output, 0, dlen);
343962306a36Sopenharmony_ci		crypto_init_wait(&wait);
344062306a36Sopenharmony_ci		sg_init_one(&src, input_vec, ilen);
344162306a36Sopenharmony_ci		sg_init_one(&dst, output, dlen);
344262306a36Sopenharmony_ci
344362306a36Sopenharmony_ci		req = acomp_request_alloc(tfm);
344462306a36Sopenharmony_ci		if (!req) {
344562306a36Sopenharmony_ci			pr_err("alg: acomp: request alloc failed for %s\n",
344662306a36Sopenharmony_ci			       algo);
344762306a36Sopenharmony_ci			kfree(input_vec);
344862306a36Sopenharmony_ci			ret = -ENOMEM;
344962306a36Sopenharmony_ci			goto out;
345062306a36Sopenharmony_ci		}
345162306a36Sopenharmony_ci
345262306a36Sopenharmony_ci		acomp_request_set_params(req, &src, &dst, ilen, dlen);
345362306a36Sopenharmony_ci		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
345462306a36Sopenharmony_ci					   crypto_req_done, &wait);
345562306a36Sopenharmony_ci
345662306a36Sopenharmony_ci		ret = crypto_wait_req(crypto_acomp_compress(req), &wait);
345762306a36Sopenharmony_ci		if (ret) {
345862306a36Sopenharmony_ci			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
345962306a36Sopenharmony_ci			       i + 1, algo, -ret);
346062306a36Sopenharmony_ci			kfree(input_vec);
346162306a36Sopenharmony_ci			acomp_request_free(req);
346262306a36Sopenharmony_ci			goto out;
346362306a36Sopenharmony_ci		}
346462306a36Sopenharmony_ci
346562306a36Sopenharmony_ci		ilen = req->dlen;
346662306a36Sopenharmony_ci		dlen = COMP_BUF_SIZE;
346762306a36Sopenharmony_ci		sg_init_one(&src, output, ilen);
346862306a36Sopenharmony_ci		sg_init_one(&dst, decomp_out, dlen);
346962306a36Sopenharmony_ci		crypto_init_wait(&wait);
347062306a36Sopenharmony_ci		acomp_request_set_params(req, &src, &dst, ilen, dlen);
347162306a36Sopenharmony_ci
347262306a36Sopenharmony_ci		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
347362306a36Sopenharmony_ci		if (ret) {
347462306a36Sopenharmony_ci			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
347562306a36Sopenharmony_ci			       i + 1, algo, -ret);
347662306a36Sopenharmony_ci			kfree(input_vec);
347762306a36Sopenharmony_ci			acomp_request_free(req);
347862306a36Sopenharmony_ci			goto out;
347962306a36Sopenharmony_ci		}
348062306a36Sopenharmony_ci
348162306a36Sopenharmony_ci		if (req->dlen != ctemplate[i].inlen) {
348262306a36Sopenharmony_ci			pr_err("alg: acomp: Compression test %d failed for %s: output len = %d\n",
348362306a36Sopenharmony_ci			       i + 1, algo, req->dlen);
348462306a36Sopenharmony_ci			ret = -EINVAL;
348562306a36Sopenharmony_ci			kfree(input_vec);
348662306a36Sopenharmony_ci			acomp_request_free(req);
348762306a36Sopenharmony_ci			goto out;
348862306a36Sopenharmony_ci		}
348962306a36Sopenharmony_ci
349062306a36Sopenharmony_ci		if (memcmp(input_vec, decomp_out, req->dlen)) {
349162306a36Sopenharmony_ci			pr_err("alg: acomp: Compression test %d failed for %s\n",
349262306a36Sopenharmony_ci			       i + 1, algo);
349362306a36Sopenharmony_ci			hexdump(output, req->dlen);
349462306a36Sopenharmony_ci			ret = -EINVAL;
349562306a36Sopenharmony_ci			kfree(input_vec);
349662306a36Sopenharmony_ci			acomp_request_free(req);
349762306a36Sopenharmony_ci			goto out;
349862306a36Sopenharmony_ci		}
349962306a36Sopenharmony_ci
350062306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
350162306a36Sopenharmony_ci		crypto_init_wait(&wait);
350262306a36Sopenharmony_ci		sg_init_one(&src, input_vec, ilen);
350362306a36Sopenharmony_ci		acomp_request_set_params(req, &src, NULL, ilen, 0);
350462306a36Sopenharmony_ci
350562306a36Sopenharmony_ci		ret = crypto_wait_req(crypto_acomp_compress(req), &wait);
350662306a36Sopenharmony_ci		if (ret) {
350762306a36Sopenharmony_ci			pr_err("alg: acomp: compression failed on NULL dst buffer test %d for %s: ret=%d\n",
350862306a36Sopenharmony_ci			       i + 1, algo, -ret);
350962306a36Sopenharmony_ci			kfree(input_vec);
351062306a36Sopenharmony_ci			acomp_request_free(req);
351162306a36Sopenharmony_ci			goto out;
351262306a36Sopenharmony_ci		}
351362306a36Sopenharmony_ci#endif
351462306a36Sopenharmony_ci
351562306a36Sopenharmony_ci		kfree(input_vec);
351662306a36Sopenharmony_ci		acomp_request_free(req);
351762306a36Sopenharmony_ci	}
351862306a36Sopenharmony_ci
351962306a36Sopenharmony_ci	for (i = 0; i < dtcount; i++) {
352062306a36Sopenharmony_ci		unsigned int dlen = COMP_BUF_SIZE;
352162306a36Sopenharmony_ci		int ilen = dtemplate[i].inlen;
352262306a36Sopenharmony_ci		void *input_vec;
352362306a36Sopenharmony_ci
352462306a36Sopenharmony_ci		input_vec = kmemdup(dtemplate[i].input, ilen, GFP_KERNEL);
352562306a36Sopenharmony_ci		if (!input_vec) {
352662306a36Sopenharmony_ci			ret = -ENOMEM;
352762306a36Sopenharmony_ci			goto out;
352862306a36Sopenharmony_ci		}
352962306a36Sopenharmony_ci
353062306a36Sopenharmony_ci		memset(output, 0, dlen);
353162306a36Sopenharmony_ci		crypto_init_wait(&wait);
353262306a36Sopenharmony_ci		sg_init_one(&src, input_vec, ilen);
353362306a36Sopenharmony_ci		sg_init_one(&dst, output, dlen);
353462306a36Sopenharmony_ci
353562306a36Sopenharmony_ci		req = acomp_request_alloc(tfm);
353662306a36Sopenharmony_ci		if (!req) {
353762306a36Sopenharmony_ci			pr_err("alg: acomp: request alloc failed for %s\n",
353862306a36Sopenharmony_ci			       algo);
353962306a36Sopenharmony_ci			kfree(input_vec);
354062306a36Sopenharmony_ci			ret = -ENOMEM;
354162306a36Sopenharmony_ci			goto out;
354262306a36Sopenharmony_ci		}
354362306a36Sopenharmony_ci
354462306a36Sopenharmony_ci		acomp_request_set_params(req, &src, &dst, ilen, dlen);
354562306a36Sopenharmony_ci		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
354662306a36Sopenharmony_ci					   crypto_req_done, &wait);
354762306a36Sopenharmony_ci
354862306a36Sopenharmony_ci		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
354962306a36Sopenharmony_ci		if (ret) {
355062306a36Sopenharmony_ci			pr_err("alg: acomp: decompression failed on test %d for %s: ret=%d\n",
355162306a36Sopenharmony_ci			       i + 1, algo, -ret);
355262306a36Sopenharmony_ci			kfree(input_vec);
355362306a36Sopenharmony_ci			acomp_request_free(req);
355462306a36Sopenharmony_ci			goto out;
355562306a36Sopenharmony_ci		}
355662306a36Sopenharmony_ci
355762306a36Sopenharmony_ci		if (req->dlen != dtemplate[i].outlen) {
355862306a36Sopenharmony_ci			pr_err("alg: acomp: Decompression test %d failed for %s: output len = %d\n",
355962306a36Sopenharmony_ci			       i + 1, algo, req->dlen);
356062306a36Sopenharmony_ci			ret = -EINVAL;
356162306a36Sopenharmony_ci			kfree(input_vec);
356262306a36Sopenharmony_ci			acomp_request_free(req);
356362306a36Sopenharmony_ci			goto out;
356462306a36Sopenharmony_ci		}
356562306a36Sopenharmony_ci
356662306a36Sopenharmony_ci		if (memcmp(output, dtemplate[i].output, req->dlen)) {
356762306a36Sopenharmony_ci			pr_err("alg: acomp: Decompression test %d failed for %s\n",
356862306a36Sopenharmony_ci			       i + 1, algo);
356962306a36Sopenharmony_ci			hexdump(output, req->dlen);
357062306a36Sopenharmony_ci			ret = -EINVAL;
357162306a36Sopenharmony_ci			kfree(input_vec);
357262306a36Sopenharmony_ci			acomp_request_free(req);
357362306a36Sopenharmony_ci			goto out;
357462306a36Sopenharmony_ci		}
357562306a36Sopenharmony_ci
357662306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
357762306a36Sopenharmony_ci		crypto_init_wait(&wait);
357862306a36Sopenharmony_ci		acomp_request_set_params(req, &src, NULL, ilen, 0);
357962306a36Sopenharmony_ci
358062306a36Sopenharmony_ci		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
358162306a36Sopenharmony_ci		if (ret) {
358262306a36Sopenharmony_ci			pr_err("alg: acomp: decompression failed on NULL dst buffer test %d for %s: ret=%d\n",
358362306a36Sopenharmony_ci			       i + 1, algo, -ret);
358462306a36Sopenharmony_ci			kfree(input_vec);
358562306a36Sopenharmony_ci			acomp_request_free(req);
358662306a36Sopenharmony_ci			goto out;
358762306a36Sopenharmony_ci		}
358862306a36Sopenharmony_ci#endif
358962306a36Sopenharmony_ci
359062306a36Sopenharmony_ci		kfree(input_vec);
359162306a36Sopenharmony_ci		acomp_request_free(req);
359262306a36Sopenharmony_ci	}
359362306a36Sopenharmony_ci
359462306a36Sopenharmony_ci	ret = 0;
359562306a36Sopenharmony_ci
359662306a36Sopenharmony_ciout:
359762306a36Sopenharmony_ci	kfree(decomp_out);
359862306a36Sopenharmony_ci	kfree(output);
359962306a36Sopenharmony_ci	return ret;
360062306a36Sopenharmony_ci}
360162306a36Sopenharmony_ci
360262306a36Sopenharmony_cistatic int test_cprng(struct crypto_rng *tfm,
360362306a36Sopenharmony_ci		      const struct cprng_testvec *template,
360462306a36Sopenharmony_ci		      unsigned int tcount)
360562306a36Sopenharmony_ci{
360662306a36Sopenharmony_ci	const char *algo = crypto_tfm_alg_driver_name(crypto_rng_tfm(tfm));
360762306a36Sopenharmony_ci	int err = 0, i, j, seedsize;
360862306a36Sopenharmony_ci	u8 *seed;
360962306a36Sopenharmony_ci	char result[32];
361062306a36Sopenharmony_ci
361162306a36Sopenharmony_ci	seedsize = crypto_rng_seedsize(tfm);
361262306a36Sopenharmony_ci
361362306a36Sopenharmony_ci	seed = kmalloc(seedsize, GFP_KERNEL);
361462306a36Sopenharmony_ci	if (!seed) {
361562306a36Sopenharmony_ci		printk(KERN_ERR "alg: cprng: Failed to allocate seed space "
361662306a36Sopenharmony_ci		       "for %s\n", algo);
361762306a36Sopenharmony_ci		return -ENOMEM;
361862306a36Sopenharmony_ci	}
361962306a36Sopenharmony_ci
362062306a36Sopenharmony_ci	for (i = 0; i < tcount; i++) {
362162306a36Sopenharmony_ci		memset(result, 0, 32);
362262306a36Sopenharmony_ci
362362306a36Sopenharmony_ci		memcpy(seed, template[i].v, template[i].vlen);
362462306a36Sopenharmony_ci		memcpy(seed + template[i].vlen, template[i].key,
362562306a36Sopenharmony_ci		       template[i].klen);
362662306a36Sopenharmony_ci		memcpy(seed + template[i].vlen + template[i].klen,
362762306a36Sopenharmony_ci		       template[i].dt, template[i].dtlen);
362862306a36Sopenharmony_ci
362962306a36Sopenharmony_ci		err = crypto_rng_reset(tfm, seed, seedsize);
363062306a36Sopenharmony_ci		if (err) {
363162306a36Sopenharmony_ci			printk(KERN_ERR "alg: cprng: Failed to reset rng "
363262306a36Sopenharmony_ci			       "for %s\n", algo);
363362306a36Sopenharmony_ci			goto out;
363462306a36Sopenharmony_ci		}
363562306a36Sopenharmony_ci
363662306a36Sopenharmony_ci		for (j = 0; j < template[i].loops; j++) {
363762306a36Sopenharmony_ci			err = crypto_rng_get_bytes(tfm, result,
363862306a36Sopenharmony_ci						   template[i].rlen);
363962306a36Sopenharmony_ci			if (err < 0) {
364062306a36Sopenharmony_ci				printk(KERN_ERR "alg: cprng: Failed to obtain "
364162306a36Sopenharmony_ci				       "the correct amount of random data for "
364262306a36Sopenharmony_ci				       "%s (requested %d)\n", algo,
364362306a36Sopenharmony_ci				       template[i].rlen);
364462306a36Sopenharmony_ci				goto out;
364562306a36Sopenharmony_ci			}
364662306a36Sopenharmony_ci		}
364762306a36Sopenharmony_ci
364862306a36Sopenharmony_ci		err = memcmp(result, template[i].result,
364962306a36Sopenharmony_ci			     template[i].rlen);
365062306a36Sopenharmony_ci		if (err) {
365162306a36Sopenharmony_ci			printk(KERN_ERR "alg: cprng: Test %d failed for %s\n",
365262306a36Sopenharmony_ci			       i, algo);
365362306a36Sopenharmony_ci			hexdump(result, template[i].rlen);
365462306a36Sopenharmony_ci			err = -EINVAL;
365562306a36Sopenharmony_ci			goto out;
365662306a36Sopenharmony_ci		}
365762306a36Sopenharmony_ci	}
365862306a36Sopenharmony_ci
365962306a36Sopenharmony_ciout:
366062306a36Sopenharmony_ci	kfree(seed);
366162306a36Sopenharmony_ci	return err;
366262306a36Sopenharmony_ci}
366362306a36Sopenharmony_ci
366462306a36Sopenharmony_cistatic int alg_test_cipher(const struct alg_test_desc *desc,
366562306a36Sopenharmony_ci			   const char *driver, u32 type, u32 mask)
366662306a36Sopenharmony_ci{
366762306a36Sopenharmony_ci	const struct cipher_test_suite *suite = &desc->suite.cipher;
366862306a36Sopenharmony_ci	struct crypto_cipher *tfm;
366962306a36Sopenharmony_ci	int err;
367062306a36Sopenharmony_ci
367162306a36Sopenharmony_ci	tfm = crypto_alloc_cipher(driver, type, mask);
367262306a36Sopenharmony_ci	if (IS_ERR(tfm)) {
367362306a36Sopenharmony_ci		printk(KERN_ERR "alg: cipher: Failed to load transform for "
367462306a36Sopenharmony_ci		       "%s: %ld\n", driver, PTR_ERR(tfm));
367562306a36Sopenharmony_ci		return PTR_ERR(tfm);
367662306a36Sopenharmony_ci	}
367762306a36Sopenharmony_ci
367862306a36Sopenharmony_ci	err = test_cipher(tfm, ENCRYPT, suite->vecs, suite->count);
367962306a36Sopenharmony_ci	if (!err)
368062306a36Sopenharmony_ci		err = test_cipher(tfm, DECRYPT, suite->vecs, suite->count);
368162306a36Sopenharmony_ci
368262306a36Sopenharmony_ci	crypto_free_cipher(tfm);
368362306a36Sopenharmony_ci	return err;
368462306a36Sopenharmony_ci}
368562306a36Sopenharmony_ci
368662306a36Sopenharmony_cistatic int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
368762306a36Sopenharmony_ci			 u32 type, u32 mask)
368862306a36Sopenharmony_ci{
368962306a36Sopenharmony_ci	struct crypto_comp *comp;
369062306a36Sopenharmony_ci	struct crypto_acomp *acomp;
369162306a36Sopenharmony_ci	int err;
369262306a36Sopenharmony_ci	u32 algo_type = type & CRYPTO_ALG_TYPE_ACOMPRESS_MASK;
369362306a36Sopenharmony_ci
369462306a36Sopenharmony_ci	if (algo_type == CRYPTO_ALG_TYPE_ACOMPRESS) {
369562306a36Sopenharmony_ci		acomp = crypto_alloc_acomp(driver, type, mask);
369662306a36Sopenharmony_ci		if (IS_ERR(acomp)) {
369762306a36Sopenharmony_ci			pr_err("alg: acomp: Failed to load transform for %s: %ld\n",
369862306a36Sopenharmony_ci			       driver, PTR_ERR(acomp));
369962306a36Sopenharmony_ci			return PTR_ERR(acomp);
370062306a36Sopenharmony_ci		}
370162306a36Sopenharmony_ci		err = test_acomp(acomp, desc->suite.comp.comp.vecs,
370262306a36Sopenharmony_ci				 desc->suite.comp.decomp.vecs,
370362306a36Sopenharmony_ci				 desc->suite.comp.comp.count,
370462306a36Sopenharmony_ci				 desc->suite.comp.decomp.count);
370562306a36Sopenharmony_ci		crypto_free_acomp(acomp);
370662306a36Sopenharmony_ci	} else {
370762306a36Sopenharmony_ci		comp = crypto_alloc_comp(driver, type, mask);
370862306a36Sopenharmony_ci		if (IS_ERR(comp)) {
370962306a36Sopenharmony_ci			pr_err("alg: comp: Failed to load transform for %s: %ld\n",
371062306a36Sopenharmony_ci			       driver, PTR_ERR(comp));
371162306a36Sopenharmony_ci			return PTR_ERR(comp);
371262306a36Sopenharmony_ci		}
371362306a36Sopenharmony_ci
371462306a36Sopenharmony_ci		err = test_comp(comp, desc->suite.comp.comp.vecs,
371562306a36Sopenharmony_ci				desc->suite.comp.decomp.vecs,
371662306a36Sopenharmony_ci				desc->suite.comp.comp.count,
371762306a36Sopenharmony_ci				desc->suite.comp.decomp.count);
371862306a36Sopenharmony_ci
371962306a36Sopenharmony_ci		crypto_free_comp(comp);
372062306a36Sopenharmony_ci	}
372162306a36Sopenharmony_ci	return err;
372262306a36Sopenharmony_ci}
372362306a36Sopenharmony_ci
372462306a36Sopenharmony_cistatic int alg_test_crc32c(const struct alg_test_desc *desc,
372562306a36Sopenharmony_ci			   const char *driver, u32 type, u32 mask)
372662306a36Sopenharmony_ci{
372762306a36Sopenharmony_ci	struct crypto_shash *tfm;
372862306a36Sopenharmony_ci	__le32 val;
372962306a36Sopenharmony_ci	int err;
373062306a36Sopenharmony_ci
373162306a36Sopenharmony_ci	err = alg_test_hash(desc, driver, type, mask);
373262306a36Sopenharmony_ci	if (err)
373362306a36Sopenharmony_ci		return err;
373462306a36Sopenharmony_ci
373562306a36Sopenharmony_ci	tfm = crypto_alloc_shash(driver, type, mask);
373662306a36Sopenharmony_ci	if (IS_ERR(tfm)) {
373762306a36Sopenharmony_ci		if (PTR_ERR(tfm) == -ENOENT) {
373862306a36Sopenharmony_ci			/*
373962306a36Sopenharmony_ci			 * This crc32c implementation is only available through
374062306a36Sopenharmony_ci			 * ahash API, not the shash API, so the remaining part
374162306a36Sopenharmony_ci			 * of the test is not applicable to it.
374262306a36Sopenharmony_ci			 */
374362306a36Sopenharmony_ci			return 0;
374462306a36Sopenharmony_ci		}
374562306a36Sopenharmony_ci		printk(KERN_ERR "alg: crc32c: Failed to load transform for %s: "
374662306a36Sopenharmony_ci		       "%ld\n", driver, PTR_ERR(tfm));
374762306a36Sopenharmony_ci		return PTR_ERR(tfm);
374862306a36Sopenharmony_ci	}
374962306a36Sopenharmony_ci	driver = crypto_shash_driver_name(tfm);
375062306a36Sopenharmony_ci
375162306a36Sopenharmony_ci	do {
375262306a36Sopenharmony_ci		SHASH_DESC_ON_STACK(shash, tfm);
375362306a36Sopenharmony_ci		u32 *ctx = (u32 *)shash_desc_ctx(shash);
375462306a36Sopenharmony_ci
375562306a36Sopenharmony_ci		shash->tfm = tfm;
375662306a36Sopenharmony_ci
375762306a36Sopenharmony_ci		*ctx = 420553207;
375862306a36Sopenharmony_ci		err = crypto_shash_final(shash, (u8 *)&val);
375962306a36Sopenharmony_ci		if (err) {
376062306a36Sopenharmony_ci			printk(KERN_ERR "alg: crc32c: Operation failed for "
376162306a36Sopenharmony_ci			       "%s: %d\n", driver, err);
376262306a36Sopenharmony_ci			break;
376362306a36Sopenharmony_ci		}
376462306a36Sopenharmony_ci
376562306a36Sopenharmony_ci		if (val != cpu_to_le32(~420553207)) {
376662306a36Sopenharmony_ci			pr_err("alg: crc32c: Test failed for %s: %u\n",
376762306a36Sopenharmony_ci			       driver, le32_to_cpu(val));
376862306a36Sopenharmony_ci			err = -EINVAL;
376962306a36Sopenharmony_ci		}
377062306a36Sopenharmony_ci	} while (0);
377162306a36Sopenharmony_ci
377262306a36Sopenharmony_ci	crypto_free_shash(tfm);
377362306a36Sopenharmony_ci
377462306a36Sopenharmony_ci	return err;
377562306a36Sopenharmony_ci}
377662306a36Sopenharmony_ci
377762306a36Sopenharmony_cistatic int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
377862306a36Sopenharmony_ci			  u32 type, u32 mask)
377962306a36Sopenharmony_ci{
378062306a36Sopenharmony_ci	struct crypto_rng *rng;
378162306a36Sopenharmony_ci	int err;
378262306a36Sopenharmony_ci
378362306a36Sopenharmony_ci	rng = crypto_alloc_rng(driver, type, mask);
378462306a36Sopenharmony_ci	if (IS_ERR(rng)) {
378562306a36Sopenharmony_ci		printk(KERN_ERR "alg: cprng: Failed to load transform for %s: "
378662306a36Sopenharmony_ci		       "%ld\n", driver, PTR_ERR(rng));
378762306a36Sopenharmony_ci		return PTR_ERR(rng);
378862306a36Sopenharmony_ci	}
378962306a36Sopenharmony_ci
379062306a36Sopenharmony_ci	err = test_cprng(rng, desc->suite.cprng.vecs, desc->suite.cprng.count);
379162306a36Sopenharmony_ci
379262306a36Sopenharmony_ci	crypto_free_rng(rng);
379362306a36Sopenharmony_ci
379462306a36Sopenharmony_ci	return err;
379562306a36Sopenharmony_ci}
379662306a36Sopenharmony_ci
379762306a36Sopenharmony_ci
379862306a36Sopenharmony_cistatic int drbg_cavs_test(const struct drbg_testvec *test, int pr,
379962306a36Sopenharmony_ci			  const char *driver, u32 type, u32 mask)
380062306a36Sopenharmony_ci{
380162306a36Sopenharmony_ci	int ret = -EAGAIN;
380262306a36Sopenharmony_ci	struct crypto_rng *drng;
380362306a36Sopenharmony_ci	struct drbg_test_data test_data;
380462306a36Sopenharmony_ci	struct drbg_string addtl, pers, testentropy;
380562306a36Sopenharmony_ci	unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
380662306a36Sopenharmony_ci
380762306a36Sopenharmony_ci	if (!buf)
380862306a36Sopenharmony_ci		return -ENOMEM;
380962306a36Sopenharmony_ci
381062306a36Sopenharmony_ci	drng = crypto_alloc_rng(driver, type, mask);
381162306a36Sopenharmony_ci	if (IS_ERR(drng)) {
381262306a36Sopenharmony_ci		printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for "
381362306a36Sopenharmony_ci		       "%s\n", driver);
381462306a36Sopenharmony_ci		kfree_sensitive(buf);
381562306a36Sopenharmony_ci		return -ENOMEM;
381662306a36Sopenharmony_ci	}
381762306a36Sopenharmony_ci
381862306a36Sopenharmony_ci	test_data.testentropy = &testentropy;
381962306a36Sopenharmony_ci	drbg_string_fill(&testentropy, test->entropy, test->entropylen);
382062306a36Sopenharmony_ci	drbg_string_fill(&pers, test->pers, test->perslen);
382162306a36Sopenharmony_ci	ret = crypto_drbg_reset_test(drng, &pers, &test_data);
382262306a36Sopenharmony_ci	if (ret) {
382362306a36Sopenharmony_ci		printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
382462306a36Sopenharmony_ci		goto outbuf;
382562306a36Sopenharmony_ci	}
382662306a36Sopenharmony_ci
382762306a36Sopenharmony_ci	drbg_string_fill(&addtl, test->addtla, test->addtllen);
382862306a36Sopenharmony_ci	if (pr) {
382962306a36Sopenharmony_ci		drbg_string_fill(&testentropy, test->entpra, test->entprlen);
383062306a36Sopenharmony_ci		ret = crypto_drbg_get_bytes_addtl_test(drng,
383162306a36Sopenharmony_ci			buf, test->expectedlen, &addtl,	&test_data);
383262306a36Sopenharmony_ci	} else {
383362306a36Sopenharmony_ci		ret = crypto_drbg_get_bytes_addtl(drng,
383462306a36Sopenharmony_ci			buf, test->expectedlen, &addtl);
383562306a36Sopenharmony_ci	}
383662306a36Sopenharmony_ci	if (ret < 0) {
383762306a36Sopenharmony_ci		printk(KERN_ERR "alg: drbg: could not obtain random data for "
383862306a36Sopenharmony_ci		       "driver %s\n", driver);
383962306a36Sopenharmony_ci		goto outbuf;
384062306a36Sopenharmony_ci	}
384162306a36Sopenharmony_ci
384262306a36Sopenharmony_ci	drbg_string_fill(&addtl, test->addtlb, test->addtllen);
384362306a36Sopenharmony_ci	if (pr) {
384462306a36Sopenharmony_ci		drbg_string_fill(&testentropy, test->entprb, test->entprlen);
384562306a36Sopenharmony_ci		ret = crypto_drbg_get_bytes_addtl_test(drng,
384662306a36Sopenharmony_ci			buf, test->expectedlen, &addtl, &test_data);
384762306a36Sopenharmony_ci	} else {
384862306a36Sopenharmony_ci		ret = crypto_drbg_get_bytes_addtl(drng,
384962306a36Sopenharmony_ci			buf, test->expectedlen, &addtl);
385062306a36Sopenharmony_ci	}
385162306a36Sopenharmony_ci	if (ret < 0) {
385262306a36Sopenharmony_ci		printk(KERN_ERR "alg: drbg: could not obtain random data for "
385362306a36Sopenharmony_ci		       "driver %s\n", driver);
385462306a36Sopenharmony_ci		goto outbuf;
385562306a36Sopenharmony_ci	}
385662306a36Sopenharmony_ci
385762306a36Sopenharmony_ci	ret = memcmp(test->expected, buf, test->expectedlen);
385862306a36Sopenharmony_ci
385962306a36Sopenharmony_cioutbuf:
386062306a36Sopenharmony_ci	crypto_free_rng(drng);
386162306a36Sopenharmony_ci	kfree_sensitive(buf);
386262306a36Sopenharmony_ci	return ret;
386362306a36Sopenharmony_ci}
386462306a36Sopenharmony_ci
386562306a36Sopenharmony_ci
386662306a36Sopenharmony_cistatic int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
386762306a36Sopenharmony_ci			 u32 type, u32 mask)
386862306a36Sopenharmony_ci{
386962306a36Sopenharmony_ci	int err = 0;
387062306a36Sopenharmony_ci	int pr = 0;
387162306a36Sopenharmony_ci	int i = 0;
387262306a36Sopenharmony_ci	const struct drbg_testvec *template = desc->suite.drbg.vecs;
387362306a36Sopenharmony_ci	unsigned int tcount = desc->suite.drbg.count;
387462306a36Sopenharmony_ci
387562306a36Sopenharmony_ci	if (0 == memcmp(driver, "drbg_pr_", 8))
387662306a36Sopenharmony_ci		pr = 1;
387762306a36Sopenharmony_ci
387862306a36Sopenharmony_ci	for (i = 0; i < tcount; i++) {
387962306a36Sopenharmony_ci		err = drbg_cavs_test(&template[i], pr, driver, type, mask);
388062306a36Sopenharmony_ci		if (err) {
388162306a36Sopenharmony_ci			printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
388262306a36Sopenharmony_ci			       i, driver);
388362306a36Sopenharmony_ci			err = -EINVAL;
388462306a36Sopenharmony_ci			break;
388562306a36Sopenharmony_ci		}
388662306a36Sopenharmony_ci	}
388762306a36Sopenharmony_ci	return err;
388862306a36Sopenharmony_ci
388962306a36Sopenharmony_ci}
389062306a36Sopenharmony_ci
389162306a36Sopenharmony_cistatic int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
389262306a36Sopenharmony_ci		       const char *alg)
389362306a36Sopenharmony_ci{
389462306a36Sopenharmony_ci	struct kpp_request *req;
389562306a36Sopenharmony_ci	void *input_buf = NULL;
389662306a36Sopenharmony_ci	void *output_buf = NULL;
389762306a36Sopenharmony_ci	void *a_public = NULL;
389862306a36Sopenharmony_ci	void *a_ss = NULL;
389962306a36Sopenharmony_ci	void *shared_secret = NULL;
390062306a36Sopenharmony_ci	struct crypto_wait wait;
390162306a36Sopenharmony_ci	unsigned int out_len_max;
390262306a36Sopenharmony_ci	int err = -ENOMEM;
390362306a36Sopenharmony_ci	struct scatterlist src, dst;
390462306a36Sopenharmony_ci
390562306a36Sopenharmony_ci	req = kpp_request_alloc(tfm, GFP_KERNEL);
390662306a36Sopenharmony_ci	if (!req)
390762306a36Sopenharmony_ci		return err;
390862306a36Sopenharmony_ci
390962306a36Sopenharmony_ci	crypto_init_wait(&wait);
391062306a36Sopenharmony_ci
391162306a36Sopenharmony_ci	err = crypto_kpp_set_secret(tfm, vec->secret, vec->secret_size);
391262306a36Sopenharmony_ci	if (err < 0)
391362306a36Sopenharmony_ci		goto free_req;
391462306a36Sopenharmony_ci
391562306a36Sopenharmony_ci	out_len_max = crypto_kpp_maxsize(tfm);
391662306a36Sopenharmony_ci	output_buf = kzalloc(out_len_max, GFP_KERNEL);
391762306a36Sopenharmony_ci	if (!output_buf) {
391862306a36Sopenharmony_ci		err = -ENOMEM;
391962306a36Sopenharmony_ci		goto free_req;
392062306a36Sopenharmony_ci	}
392162306a36Sopenharmony_ci
392262306a36Sopenharmony_ci	/* Use appropriate parameter as base */
392362306a36Sopenharmony_ci	kpp_request_set_input(req, NULL, 0);
392462306a36Sopenharmony_ci	sg_init_one(&dst, output_buf, out_len_max);
392562306a36Sopenharmony_ci	kpp_request_set_output(req, &dst, out_len_max);
392662306a36Sopenharmony_ci	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
392762306a36Sopenharmony_ci				 crypto_req_done, &wait);
392862306a36Sopenharmony_ci
392962306a36Sopenharmony_ci	/* Compute party A's public key */
393062306a36Sopenharmony_ci	err = crypto_wait_req(crypto_kpp_generate_public_key(req), &wait);
393162306a36Sopenharmony_ci	if (err) {
393262306a36Sopenharmony_ci		pr_err("alg: %s: Party A: generate public key test failed. err %d\n",
393362306a36Sopenharmony_ci		       alg, err);
393462306a36Sopenharmony_ci		goto free_output;
393562306a36Sopenharmony_ci	}
393662306a36Sopenharmony_ci
393762306a36Sopenharmony_ci	if (vec->genkey) {
393862306a36Sopenharmony_ci		/* Save party A's public key */
393962306a36Sopenharmony_ci		a_public = kmemdup(sg_virt(req->dst), out_len_max, GFP_KERNEL);
394062306a36Sopenharmony_ci		if (!a_public) {
394162306a36Sopenharmony_ci			err = -ENOMEM;
394262306a36Sopenharmony_ci			goto free_output;
394362306a36Sopenharmony_ci		}
394462306a36Sopenharmony_ci	} else {
394562306a36Sopenharmony_ci		/* Verify calculated public key */
394662306a36Sopenharmony_ci		if (memcmp(vec->expected_a_public, sg_virt(req->dst),
394762306a36Sopenharmony_ci			   vec->expected_a_public_size)) {
394862306a36Sopenharmony_ci			pr_err("alg: %s: Party A: generate public key test failed. Invalid output\n",
394962306a36Sopenharmony_ci			       alg);
395062306a36Sopenharmony_ci			err = -EINVAL;
395162306a36Sopenharmony_ci			goto free_output;
395262306a36Sopenharmony_ci		}
395362306a36Sopenharmony_ci	}
395462306a36Sopenharmony_ci
395562306a36Sopenharmony_ci	/* Calculate shared secret key by using counter part (b) public key. */
395662306a36Sopenharmony_ci	input_buf = kmemdup(vec->b_public, vec->b_public_size, GFP_KERNEL);
395762306a36Sopenharmony_ci	if (!input_buf) {
395862306a36Sopenharmony_ci		err = -ENOMEM;
395962306a36Sopenharmony_ci		goto free_output;
396062306a36Sopenharmony_ci	}
396162306a36Sopenharmony_ci
396262306a36Sopenharmony_ci	sg_init_one(&src, input_buf, vec->b_public_size);
396362306a36Sopenharmony_ci	sg_init_one(&dst, output_buf, out_len_max);
396462306a36Sopenharmony_ci	kpp_request_set_input(req, &src, vec->b_public_size);
396562306a36Sopenharmony_ci	kpp_request_set_output(req, &dst, out_len_max);
396662306a36Sopenharmony_ci	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
396762306a36Sopenharmony_ci				 crypto_req_done, &wait);
396862306a36Sopenharmony_ci	err = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait);
396962306a36Sopenharmony_ci	if (err) {
397062306a36Sopenharmony_ci		pr_err("alg: %s: Party A: compute shared secret test failed. err %d\n",
397162306a36Sopenharmony_ci		       alg, err);
397262306a36Sopenharmony_ci		goto free_all;
397362306a36Sopenharmony_ci	}
397462306a36Sopenharmony_ci
397562306a36Sopenharmony_ci	if (vec->genkey) {
397662306a36Sopenharmony_ci		/* Save the shared secret obtained by party A */
397762306a36Sopenharmony_ci		a_ss = kmemdup(sg_virt(req->dst), vec->expected_ss_size, GFP_KERNEL);
397862306a36Sopenharmony_ci		if (!a_ss) {
397962306a36Sopenharmony_ci			err = -ENOMEM;
398062306a36Sopenharmony_ci			goto free_all;
398162306a36Sopenharmony_ci		}
398262306a36Sopenharmony_ci
398362306a36Sopenharmony_ci		/*
398462306a36Sopenharmony_ci		 * Calculate party B's shared secret by using party A's
398562306a36Sopenharmony_ci		 * public key.
398662306a36Sopenharmony_ci		 */
398762306a36Sopenharmony_ci		err = crypto_kpp_set_secret(tfm, vec->b_secret,
398862306a36Sopenharmony_ci					    vec->b_secret_size);
398962306a36Sopenharmony_ci		if (err < 0)
399062306a36Sopenharmony_ci			goto free_all;
399162306a36Sopenharmony_ci
399262306a36Sopenharmony_ci		sg_init_one(&src, a_public, vec->expected_a_public_size);
399362306a36Sopenharmony_ci		sg_init_one(&dst, output_buf, out_len_max);
399462306a36Sopenharmony_ci		kpp_request_set_input(req, &src, vec->expected_a_public_size);
399562306a36Sopenharmony_ci		kpp_request_set_output(req, &dst, out_len_max);
399662306a36Sopenharmony_ci		kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
399762306a36Sopenharmony_ci					 crypto_req_done, &wait);
399862306a36Sopenharmony_ci		err = crypto_wait_req(crypto_kpp_compute_shared_secret(req),
399962306a36Sopenharmony_ci				      &wait);
400062306a36Sopenharmony_ci		if (err) {
400162306a36Sopenharmony_ci			pr_err("alg: %s: Party B: compute shared secret failed. err %d\n",
400262306a36Sopenharmony_ci			       alg, err);
400362306a36Sopenharmony_ci			goto free_all;
400462306a36Sopenharmony_ci		}
400562306a36Sopenharmony_ci
400662306a36Sopenharmony_ci		shared_secret = a_ss;
400762306a36Sopenharmony_ci	} else {
400862306a36Sopenharmony_ci		shared_secret = (void *)vec->expected_ss;
400962306a36Sopenharmony_ci	}
401062306a36Sopenharmony_ci
401162306a36Sopenharmony_ci	/*
401262306a36Sopenharmony_ci	 * verify shared secret from which the user will derive
401362306a36Sopenharmony_ci	 * secret key by executing whatever hash it has chosen
401462306a36Sopenharmony_ci	 */
401562306a36Sopenharmony_ci	if (memcmp(shared_secret, sg_virt(req->dst),
401662306a36Sopenharmony_ci		   vec->expected_ss_size)) {
401762306a36Sopenharmony_ci		pr_err("alg: %s: compute shared secret test failed. Invalid output\n",
401862306a36Sopenharmony_ci		       alg);
401962306a36Sopenharmony_ci		err = -EINVAL;
402062306a36Sopenharmony_ci	}
402162306a36Sopenharmony_ci
402262306a36Sopenharmony_cifree_all:
402362306a36Sopenharmony_ci	kfree(a_ss);
402462306a36Sopenharmony_ci	kfree(input_buf);
402562306a36Sopenharmony_cifree_output:
402662306a36Sopenharmony_ci	kfree(a_public);
402762306a36Sopenharmony_ci	kfree(output_buf);
402862306a36Sopenharmony_cifree_req:
402962306a36Sopenharmony_ci	kpp_request_free(req);
403062306a36Sopenharmony_ci	return err;
403162306a36Sopenharmony_ci}
403262306a36Sopenharmony_ci
403362306a36Sopenharmony_cistatic int test_kpp(struct crypto_kpp *tfm, const char *alg,
403462306a36Sopenharmony_ci		    const struct kpp_testvec *vecs, unsigned int tcount)
403562306a36Sopenharmony_ci{
403662306a36Sopenharmony_ci	int ret, i;
403762306a36Sopenharmony_ci
403862306a36Sopenharmony_ci	for (i = 0; i < tcount; i++) {
403962306a36Sopenharmony_ci		ret = do_test_kpp(tfm, vecs++, alg);
404062306a36Sopenharmony_ci		if (ret) {
404162306a36Sopenharmony_ci			pr_err("alg: %s: test failed on vector %d, err=%d\n",
404262306a36Sopenharmony_ci			       alg, i + 1, ret);
404362306a36Sopenharmony_ci			return ret;
404462306a36Sopenharmony_ci		}
404562306a36Sopenharmony_ci	}
404662306a36Sopenharmony_ci	return 0;
404762306a36Sopenharmony_ci}
404862306a36Sopenharmony_ci
404962306a36Sopenharmony_cistatic int alg_test_kpp(const struct alg_test_desc *desc, const char *driver,
405062306a36Sopenharmony_ci			u32 type, u32 mask)
405162306a36Sopenharmony_ci{
405262306a36Sopenharmony_ci	struct crypto_kpp *tfm;
405362306a36Sopenharmony_ci	int err = 0;
405462306a36Sopenharmony_ci
405562306a36Sopenharmony_ci	tfm = crypto_alloc_kpp(driver, type, mask);
405662306a36Sopenharmony_ci	if (IS_ERR(tfm)) {
405762306a36Sopenharmony_ci		pr_err("alg: kpp: Failed to load tfm for %s: %ld\n",
405862306a36Sopenharmony_ci		       driver, PTR_ERR(tfm));
405962306a36Sopenharmony_ci		return PTR_ERR(tfm);
406062306a36Sopenharmony_ci	}
406162306a36Sopenharmony_ci	if (desc->suite.kpp.vecs)
406262306a36Sopenharmony_ci		err = test_kpp(tfm, desc->alg, desc->suite.kpp.vecs,
406362306a36Sopenharmony_ci			       desc->suite.kpp.count);
406462306a36Sopenharmony_ci
406562306a36Sopenharmony_ci	crypto_free_kpp(tfm);
406662306a36Sopenharmony_ci	return err;
406762306a36Sopenharmony_ci}
406862306a36Sopenharmony_ci
406962306a36Sopenharmony_cistatic u8 *test_pack_u32(u8 *dst, u32 val)
407062306a36Sopenharmony_ci{
407162306a36Sopenharmony_ci	memcpy(dst, &val, sizeof(val));
407262306a36Sopenharmony_ci	return dst + sizeof(val);
407362306a36Sopenharmony_ci}
407462306a36Sopenharmony_ci
407562306a36Sopenharmony_cistatic int test_akcipher_one(struct crypto_akcipher *tfm,
407662306a36Sopenharmony_ci			     const struct akcipher_testvec *vecs)
407762306a36Sopenharmony_ci{
407862306a36Sopenharmony_ci	char *xbuf[XBUFSIZE];
407962306a36Sopenharmony_ci	struct akcipher_request *req;
408062306a36Sopenharmony_ci	void *outbuf_enc = NULL;
408162306a36Sopenharmony_ci	void *outbuf_dec = NULL;
408262306a36Sopenharmony_ci	struct crypto_wait wait;
408362306a36Sopenharmony_ci	unsigned int out_len_max, out_len = 0;
408462306a36Sopenharmony_ci	int err = -ENOMEM;
408562306a36Sopenharmony_ci	struct scatterlist src, dst, src_tab[3];
408662306a36Sopenharmony_ci	const char *m, *c;
408762306a36Sopenharmony_ci	unsigned int m_size, c_size;
408862306a36Sopenharmony_ci	const char *op;
408962306a36Sopenharmony_ci	u8 *key, *ptr;
409062306a36Sopenharmony_ci
409162306a36Sopenharmony_ci	if (testmgr_alloc_buf(xbuf))
409262306a36Sopenharmony_ci		return err;
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_ci	req = akcipher_request_alloc(tfm, GFP_KERNEL);
409562306a36Sopenharmony_ci	if (!req)
409662306a36Sopenharmony_ci		goto free_xbuf;
409762306a36Sopenharmony_ci
409862306a36Sopenharmony_ci	crypto_init_wait(&wait);
409962306a36Sopenharmony_ci
410062306a36Sopenharmony_ci	key = kmalloc(vecs->key_len + sizeof(u32) * 2 + vecs->param_len,
410162306a36Sopenharmony_ci		      GFP_KERNEL);
410262306a36Sopenharmony_ci	if (!key)
410362306a36Sopenharmony_ci		goto free_req;
410462306a36Sopenharmony_ci	memcpy(key, vecs->key, vecs->key_len);
410562306a36Sopenharmony_ci	ptr = key + vecs->key_len;
410662306a36Sopenharmony_ci	ptr = test_pack_u32(ptr, vecs->algo);
410762306a36Sopenharmony_ci	ptr = test_pack_u32(ptr, vecs->param_len);
410862306a36Sopenharmony_ci	memcpy(ptr, vecs->params, vecs->param_len);
410962306a36Sopenharmony_ci
411062306a36Sopenharmony_ci	if (vecs->public_key_vec)
411162306a36Sopenharmony_ci		err = crypto_akcipher_set_pub_key(tfm, key, vecs->key_len);
411262306a36Sopenharmony_ci	else
411362306a36Sopenharmony_ci		err = crypto_akcipher_set_priv_key(tfm, key, vecs->key_len);
411462306a36Sopenharmony_ci	if (err)
411562306a36Sopenharmony_ci		goto free_key;
411662306a36Sopenharmony_ci
411762306a36Sopenharmony_ci	/*
411862306a36Sopenharmony_ci	 * First run test which do not require a private key, such as
411962306a36Sopenharmony_ci	 * encrypt or verify.
412062306a36Sopenharmony_ci	 */
412162306a36Sopenharmony_ci	err = -ENOMEM;
412262306a36Sopenharmony_ci	out_len_max = crypto_akcipher_maxsize(tfm);
412362306a36Sopenharmony_ci	outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
412462306a36Sopenharmony_ci	if (!outbuf_enc)
412562306a36Sopenharmony_ci		goto free_key;
412662306a36Sopenharmony_ci
412762306a36Sopenharmony_ci	if (!vecs->siggen_sigver_test) {
412862306a36Sopenharmony_ci		m = vecs->m;
412962306a36Sopenharmony_ci		m_size = vecs->m_size;
413062306a36Sopenharmony_ci		c = vecs->c;
413162306a36Sopenharmony_ci		c_size = vecs->c_size;
413262306a36Sopenharmony_ci		op = "encrypt";
413362306a36Sopenharmony_ci	} else {
413462306a36Sopenharmony_ci		/* Swap args so we could keep plaintext (digest)
413562306a36Sopenharmony_ci		 * in vecs->m, and cooked signature in vecs->c.
413662306a36Sopenharmony_ci		 */
413762306a36Sopenharmony_ci		m = vecs->c; /* signature */
413862306a36Sopenharmony_ci		m_size = vecs->c_size;
413962306a36Sopenharmony_ci		c = vecs->m; /* digest */
414062306a36Sopenharmony_ci		c_size = vecs->m_size;
414162306a36Sopenharmony_ci		op = "verify";
414262306a36Sopenharmony_ci	}
414362306a36Sopenharmony_ci
414462306a36Sopenharmony_ci	err = -E2BIG;
414562306a36Sopenharmony_ci	if (WARN_ON(m_size > PAGE_SIZE))
414662306a36Sopenharmony_ci		goto free_all;
414762306a36Sopenharmony_ci	memcpy(xbuf[0], m, m_size);
414862306a36Sopenharmony_ci
414962306a36Sopenharmony_ci	sg_init_table(src_tab, 3);
415062306a36Sopenharmony_ci	sg_set_buf(&src_tab[0], xbuf[0], 8);
415162306a36Sopenharmony_ci	sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8);
415262306a36Sopenharmony_ci	if (vecs->siggen_sigver_test) {
415362306a36Sopenharmony_ci		if (WARN_ON(c_size > PAGE_SIZE))
415462306a36Sopenharmony_ci			goto free_all;
415562306a36Sopenharmony_ci		memcpy(xbuf[1], c, c_size);
415662306a36Sopenharmony_ci		sg_set_buf(&src_tab[2], xbuf[1], c_size);
415762306a36Sopenharmony_ci		akcipher_request_set_crypt(req, src_tab, NULL, m_size, c_size);
415862306a36Sopenharmony_ci	} else {
415962306a36Sopenharmony_ci		sg_init_one(&dst, outbuf_enc, out_len_max);
416062306a36Sopenharmony_ci		akcipher_request_set_crypt(req, src_tab, &dst, m_size,
416162306a36Sopenharmony_ci					   out_len_max);
416262306a36Sopenharmony_ci	}
416362306a36Sopenharmony_ci	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
416462306a36Sopenharmony_ci				      crypto_req_done, &wait);
416562306a36Sopenharmony_ci
416662306a36Sopenharmony_ci	err = crypto_wait_req(vecs->siggen_sigver_test ?
416762306a36Sopenharmony_ci			      /* Run asymmetric signature verification */
416862306a36Sopenharmony_ci			      crypto_akcipher_verify(req) :
416962306a36Sopenharmony_ci			      /* Run asymmetric encrypt */
417062306a36Sopenharmony_ci			      crypto_akcipher_encrypt(req), &wait);
417162306a36Sopenharmony_ci	if (err) {
417262306a36Sopenharmony_ci		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
417362306a36Sopenharmony_ci		goto free_all;
417462306a36Sopenharmony_ci	}
417562306a36Sopenharmony_ci	if (!vecs->siggen_sigver_test && c) {
417662306a36Sopenharmony_ci		if (req->dst_len != c_size) {
417762306a36Sopenharmony_ci			pr_err("alg: akcipher: %s test failed. Invalid output len\n",
417862306a36Sopenharmony_ci			       op);
417962306a36Sopenharmony_ci			err = -EINVAL;
418062306a36Sopenharmony_ci			goto free_all;
418162306a36Sopenharmony_ci		}
418262306a36Sopenharmony_ci		/* verify that encrypted message is equal to expected */
418362306a36Sopenharmony_ci		if (memcmp(c, outbuf_enc, c_size) != 0) {
418462306a36Sopenharmony_ci			pr_err("alg: akcipher: %s test failed. Invalid output\n",
418562306a36Sopenharmony_ci			       op);
418662306a36Sopenharmony_ci			hexdump(outbuf_enc, c_size);
418762306a36Sopenharmony_ci			err = -EINVAL;
418862306a36Sopenharmony_ci			goto free_all;
418962306a36Sopenharmony_ci		}
419062306a36Sopenharmony_ci	}
419162306a36Sopenharmony_ci
419262306a36Sopenharmony_ci	/*
419362306a36Sopenharmony_ci	 * Don't invoke (decrypt or sign) test which require a private key
419462306a36Sopenharmony_ci	 * for vectors with only a public key.
419562306a36Sopenharmony_ci	 */
419662306a36Sopenharmony_ci	if (vecs->public_key_vec) {
419762306a36Sopenharmony_ci		err = 0;
419862306a36Sopenharmony_ci		goto free_all;
419962306a36Sopenharmony_ci	}
420062306a36Sopenharmony_ci	outbuf_dec = kzalloc(out_len_max, GFP_KERNEL);
420162306a36Sopenharmony_ci	if (!outbuf_dec) {
420262306a36Sopenharmony_ci		err = -ENOMEM;
420362306a36Sopenharmony_ci		goto free_all;
420462306a36Sopenharmony_ci	}
420562306a36Sopenharmony_ci
420662306a36Sopenharmony_ci	if (!vecs->siggen_sigver_test && !c) {
420762306a36Sopenharmony_ci		c = outbuf_enc;
420862306a36Sopenharmony_ci		c_size = req->dst_len;
420962306a36Sopenharmony_ci	}
421062306a36Sopenharmony_ci
421162306a36Sopenharmony_ci	err = -E2BIG;
421262306a36Sopenharmony_ci	op = vecs->siggen_sigver_test ? "sign" : "decrypt";
421362306a36Sopenharmony_ci	if (WARN_ON(c_size > PAGE_SIZE))
421462306a36Sopenharmony_ci		goto free_all;
421562306a36Sopenharmony_ci	memcpy(xbuf[0], c, c_size);
421662306a36Sopenharmony_ci
421762306a36Sopenharmony_ci	sg_init_one(&src, xbuf[0], c_size);
421862306a36Sopenharmony_ci	sg_init_one(&dst, outbuf_dec, out_len_max);
421962306a36Sopenharmony_ci	crypto_init_wait(&wait);
422062306a36Sopenharmony_ci	akcipher_request_set_crypt(req, &src, &dst, c_size, out_len_max);
422162306a36Sopenharmony_ci
422262306a36Sopenharmony_ci	err = crypto_wait_req(vecs->siggen_sigver_test ?
422362306a36Sopenharmony_ci			      /* Run asymmetric signature generation */
422462306a36Sopenharmony_ci			      crypto_akcipher_sign(req) :
422562306a36Sopenharmony_ci			      /* Run asymmetric decrypt */
422662306a36Sopenharmony_ci			      crypto_akcipher_decrypt(req), &wait);
422762306a36Sopenharmony_ci	if (err) {
422862306a36Sopenharmony_ci		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
422962306a36Sopenharmony_ci		goto free_all;
423062306a36Sopenharmony_ci	}
423162306a36Sopenharmony_ci	out_len = req->dst_len;
423262306a36Sopenharmony_ci	if (out_len < m_size) {
423362306a36Sopenharmony_ci		pr_err("alg: akcipher: %s test failed. Invalid output len %u\n",
423462306a36Sopenharmony_ci		       op, out_len);
423562306a36Sopenharmony_ci		err = -EINVAL;
423662306a36Sopenharmony_ci		goto free_all;
423762306a36Sopenharmony_ci	}
423862306a36Sopenharmony_ci	/* verify that decrypted message is equal to the original msg */
423962306a36Sopenharmony_ci	if (memchr_inv(outbuf_dec, 0, out_len - m_size) ||
424062306a36Sopenharmony_ci	    memcmp(m, outbuf_dec + out_len - m_size, m_size)) {
424162306a36Sopenharmony_ci		pr_err("alg: akcipher: %s test failed. Invalid output\n", op);
424262306a36Sopenharmony_ci		hexdump(outbuf_dec, out_len);
424362306a36Sopenharmony_ci		err = -EINVAL;
424462306a36Sopenharmony_ci	}
424562306a36Sopenharmony_cifree_all:
424662306a36Sopenharmony_ci	kfree(outbuf_dec);
424762306a36Sopenharmony_ci	kfree(outbuf_enc);
424862306a36Sopenharmony_cifree_key:
424962306a36Sopenharmony_ci	kfree(key);
425062306a36Sopenharmony_cifree_req:
425162306a36Sopenharmony_ci	akcipher_request_free(req);
425262306a36Sopenharmony_cifree_xbuf:
425362306a36Sopenharmony_ci	testmgr_free_buf(xbuf);
425462306a36Sopenharmony_ci	return err;
425562306a36Sopenharmony_ci}
425662306a36Sopenharmony_ci
425762306a36Sopenharmony_cistatic int test_akcipher(struct crypto_akcipher *tfm, const char *alg,
425862306a36Sopenharmony_ci			 const struct akcipher_testvec *vecs,
425962306a36Sopenharmony_ci			 unsigned int tcount)
426062306a36Sopenharmony_ci{
426162306a36Sopenharmony_ci	const char *algo =
426262306a36Sopenharmony_ci		crypto_tfm_alg_driver_name(crypto_akcipher_tfm(tfm));
426362306a36Sopenharmony_ci	int ret, i;
426462306a36Sopenharmony_ci
426562306a36Sopenharmony_ci	for (i = 0; i < tcount; i++) {
426662306a36Sopenharmony_ci		ret = test_akcipher_one(tfm, vecs++);
426762306a36Sopenharmony_ci		if (!ret)
426862306a36Sopenharmony_ci			continue;
426962306a36Sopenharmony_ci
427062306a36Sopenharmony_ci		pr_err("alg: akcipher: test %d failed for %s, err=%d\n",
427162306a36Sopenharmony_ci		       i + 1, algo, ret);
427262306a36Sopenharmony_ci		return ret;
427362306a36Sopenharmony_ci	}
427462306a36Sopenharmony_ci	return 0;
427562306a36Sopenharmony_ci}
427662306a36Sopenharmony_ci
427762306a36Sopenharmony_cistatic int alg_test_akcipher(const struct alg_test_desc *desc,
427862306a36Sopenharmony_ci			     const char *driver, u32 type, u32 mask)
427962306a36Sopenharmony_ci{
428062306a36Sopenharmony_ci	struct crypto_akcipher *tfm;
428162306a36Sopenharmony_ci	int err = 0;
428262306a36Sopenharmony_ci
428362306a36Sopenharmony_ci	tfm = crypto_alloc_akcipher(driver, type, mask);
428462306a36Sopenharmony_ci	if (IS_ERR(tfm)) {
428562306a36Sopenharmony_ci		pr_err("alg: akcipher: Failed to load tfm for %s: %ld\n",
428662306a36Sopenharmony_ci		       driver, PTR_ERR(tfm));
428762306a36Sopenharmony_ci		return PTR_ERR(tfm);
428862306a36Sopenharmony_ci	}
428962306a36Sopenharmony_ci	if (desc->suite.akcipher.vecs)
429062306a36Sopenharmony_ci		err = test_akcipher(tfm, desc->alg, desc->suite.akcipher.vecs,
429162306a36Sopenharmony_ci				    desc->suite.akcipher.count);
429262306a36Sopenharmony_ci
429362306a36Sopenharmony_ci	crypto_free_akcipher(tfm);
429462306a36Sopenharmony_ci	return err;
429562306a36Sopenharmony_ci}
429662306a36Sopenharmony_ci
429762306a36Sopenharmony_cistatic int alg_test_null(const struct alg_test_desc *desc,
429862306a36Sopenharmony_ci			     const char *driver, u32 type, u32 mask)
429962306a36Sopenharmony_ci{
430062306a36Sopenharmony_ci	return 0;
430162306a36Sopenharmony_ci}
430262306a36Sopenharmony_ci
430362306a36Sopenharmony_ci#define ____VECS(tv)	.vecs = tv, .count = ARRAY_SIZE(tv)
430462306a36Sopenharmony_ci#define __VECS(tv)	{ ____VECS(tv) }
430562306a36Sopenharmony_ci
430662306a36Sopenharmony_ci/* Please keep this list sorted by algorithm name. */
430762306a36Sopenharmony_cistatic const struct alg_test_desc alg_test_descs[] = {
430862306a36Sopenharmony_ci	{
430962306a36Sopenharmony_ci		.alg = "adiantum(xchacha12,aes)",
431062306a36Sopenharmony_ci		.generic_driver = "adiantum(xchacha12-generic,aes-generic,nhpoly1305-generic)",
431162306a36Sopenharmony_ci		.test = alg_test_skcipher,
431262306a36Sopenharmony_ci		.suite = {
431362306a36Sopenharmony_ci			.cipher = __VECS(adiantum_xchacha12_aes_tv_template)
431462306a36Sopenharmony_ci		},
431562306a36Sopenharmony_ci	}, {
431662306a36Sopenharmony_ci		.alg = "adiantum(xchacha20,aes)",
431762306a36Sopenharmony_ci		.generic_driver = "adiantum(xchacha20-generic,aes-generic,nhpoly1305-generic)",
431862306a36Sopenharmony_ci		.test = alg_test_skcipher,
431962306a36Sopenharmony_ci		.suite = {
432062306a36Sopenharmony_ci			.cipher = __VECS(adiantum_xchacha20_aes_tv_template)
432162306a36Sopenharmony_ci		},
432262306a36Sopenharmony_ci	}, {
432362306a36Sopenharmony_ci		.alg = "aegis128",
432462306a36Sopenharmony_ci		.test = alg_test_aead,
432562306a36Sopenharmony_ci		.suite = {
432662306a36Sopenharmony_ci			.aead = __VECS(aegis128_tv_template)
432762306a36Sopenharmony_ci		}
432862306a36Sopenharmony_ci	}, {
432962306a36Sopenharmony_ci		.alg = "ansi_cprng",
433062306a36Sopenharmony_ci		.test = alg_test_cprng,
433162306a36Sopenharmony_ci		.suite = {
433262306a36Sopenharmony_ci			.cprng = __VECS(ansi_cprng_aes_tv_template)
433362306a36Sopenharmony_ci		}
433462306a36Sopenharmony_ci	}, {
433562306a36Sopenharmony_ci		.alg = "authenc(hmac(md5),ecb(cipher_null))",
433662306a36Sopenharmony_ci		.test = alg_test_aead,
433762306a36Sopenharmony_ci		.suite = {
433862306a36Sopenharmony_ci			.aead = __VECS(hmac_md5_ecb_cipher_null_tv_template)
433962306a36Sopenharmony_ci		}
434062306a36Sopenharmony_ci	}, {
434162306a36Sopenharmony_ci		.alg = "authenc(hmac(sha1),cbc(aes))",
434262306a36Sopenharmony_ci		.test = alg_test_aead,
434362306a36Sopenharmony_ci		.fips_allowed = 1,
434462306a36Sopenharmony_ci		.suite = {
434562306a36Sopenharmony_ci			.aead = __VECS(hmac_sha1_aes_cbc_tv_temp)
434662306a36Sopenharmony_ci		}
434762306a36Sopenharmony_ci	}, {
434862306a36Sopenharmony_ci		.alg = "authenc(hmac(sha1),cbc(des))",
434962306a36Sopenharmony_ci		.test = alg_test_aead,
435062306a36Sopenharmony_ci		.suite = {
435162306a36Sopenharmony_ci			.aead = __VECS(hmac_sha1_des_cbc_tv_temp)
435262306a36Sopenharmony_ci		}
435362306a36Sopenharmony_ci	}, {
435462306a36Sopenharmony_ci		.alg = "authenc(hmac(sha1),cbc(des3_ede))",
435562306a36Sopenharmony_ci		.test = alg_test_aead,
435662306a36Sopenharmony_ci		.suite = {
435762306a36Sopenharmony_ci			.aead = __VECS(hmac_sha1_des3_ede_cbc_tv_temp)
435862306a36Sopenharmony_ci		}
435962306a36Sopenharmony_ci	}, {
436062306a36Sopenharmony_ci		.alg = "authenc(hmac(sha1),ctr(aes))",
436162306a36Sopenharmony_ci		.test = alg_test_null,
436262306a36Sopenharmony_ci		.fips_allowed = 1,
436362306a36Sopenharmony_ci	}, {
436462306a36Sopenharmony_ci		.alg = "authenc(hmac(sha1),ecb(cipher_null))",
436562306a36Sopenharmony_ci		.test = alg_test_aead,
436662306a36Sopenharmony_ci		.suite = {
436762306a36Sopenharmony_ci			.aead = __VECS(hmac_sha1_ecb_cipher_null_tv_temp)
436862306a36Sopenharmony_ci		}
436962306a36Sopenharmony_ci	}, {
437062306a36Sopenharmony_ci		.alg = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
437162306a36Sopenharmony_ci		.test = alg_test_null,
437262306a36Sopenharmony_ci		.fips_allowed = 1,
437362306a36Sopenharmony_ci	}, {
437462306a36Sopenharmony_ci		.alg = "authenc(hmac(sha224),cbc(des))",
437562306a36Sopenharmony_ci		.test = alg_test_aead,
437662306a36Sopenharmony_ci		.suite = {
437762306a36Sopenharmony_ci			.aead = __VECS(hmac_sha224_des_cbc_tv_temp)
437862306a36Sopenharmony_ci		}
437962306a36Sopenharmony_ci	}, {
438062306a36Sopenharmony_ci		.alg = "authenc(hmac(sha224),cbc(des3_ede))",
438162306a36Sopenharmony_ci		.test = alg_test_aead,
438262306a36Sopenharmony_ci		.suite = {
438362306a36Sopenharmony_ci			.aead = __VECS(hmac_sha224_des3_ede_cbc_tv_temp)
438462306a36Sopenharmony_ci		}
438562306a36Sopenharmony_ci	}, {
438662306a36Sopenharmony_ci		.alg = "authenc(hmac(sha256),cbc(aes))",
438762306a36Sopenharmony_ci		.test = alg_test_aead,
438862306a36Sopenharmony_ci		.fips_allowed = 1,
438962306a36Sopenharmony_ci		.suite = {
439062306a36Sopenharmony_ci			.aead = __VECS(hmac_sha256_aes_cbc_tv_temp)
439162306a36Sopenharmony_ci		}
439262306a36Sopenharmony_ci	}, {
439362306a36Sopenharmony_ci		.alg = "authenc(hmac(sha256),cbc(des))",
439462306a36Sopenharmony_ci		.test = alg_test_aead,
439562306a36Sopenharmony_ci		.suite = {
439662306a36Sopenharmony_ci			.aead = __VECS(hmac_sha256_des_cbc_tv_temp)
439762306a36Sopenharmony_ci		}
439862306a36Sopenharmony_ci	}, {
439962306a36Sopenharmony_ci		.alg = "authenc(hmac(sha256),cbc(des3_ede))",
440062306a36Sopenharmony_ci		.test = alg_test_aead,
440162306a36Sopenharmony_ci		.suite = {
440262306a36Sopenharmony_ci			.aead = __VECS(hmac_sha256_des3_ede_cbc_tv_temp)
440362306a36Sopenharmony_ci		}
440462306a36Sopenharmony_ci	}, {
440562306a36Sopenharmony_ci		.alg = "authenc(hmac(sha256),ctr(aes))",
440662306a36Sopenharmony_ci		.test = alg_test_null,
440762306a36Sopenharmony_ci		.fips_allowed = 1,
440862306a36Sopenharmony_ci	}, {
440962306a36Sopenharmony_ci		.alg = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
441062306a36Sopenharmony_ci		.test = alg_test_null,
441162306a36Sopenharmony_ci		.fips_allowed = 1,
441262306a36Sopenharmony_ci	}, {
441362306a36Sopenharmony_ci		.alg = "authenc(hmac(sha384),cbc(des))",
441462306a36Sopenharmony_ci		.test = alg_test_aead,
441562306a36Sopenharmony_ci		.suite = {
441662306a36Sopenharmony_ci			.aead = __VECS(hmac_sha384_des_cbc_tv_temp)
441762306a36Sopenharmony_ci		}
441862306a36Sopenharmony_ci	}, {
441962306a36Sopenharmony_ci		.alg = "authenc(hmac(sha384),cbc(des3_ede))",
442062306a36Sopenharmony_ci		.test = alg_test_aead,
442162306a36Sopenharmony_ci		.suite = {
442262306a36Sopenharmony_ci			.aead = __VECS(hmac_sha384_des3_ede_cbc_tv_temp)
442362306a36Sopenharmony_ci		}
442462306a36Sopenharmony_ci	}, {
442562306a36Sopenharmony_ci		.alg = "authenc(hmac(sha384),ctr(aes))",
442662306a36Sopenharmony_ci		.test = alg_test_null,
442762306a36Sopenharmony_ci		.fips_allowed = 1,
442862306a36Sopenharmony_ci	}, {
442962306a36Sopenharmony_ci		.alg = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
443062306a36Sopenharmony_ci		.test = alg_test_null,
443162306a36Sopenharmony_ci		.fips_allowed = 1,
443262306a36Sopenharmony_ci	}, {
443362306a36Sopenharmony_ci		.alg = "authenc(hmac(sha512),cbc(aes))",
443462306a36Sopenharmony_ci		.fips_allowed = 1,
443562306a36Sopenharmony_ci		.test = alg_test_aead,
443662306a36Sopenharmony_ci		.suite = {
443762306a36Sopenharmony_ci			.aead = __VECS(hmac_sha512_aes_cbc_tv_temp)
443862306a36Sopenharmony_ci		}
443962306a36Sopenharmony_ci	}, {
444062306a36Sopenharmony_ci		.alg = "authenc(hmac(sha512),cbc(des))",
444162306a36Sopenharmony_ci		.test = alg_test_aead,
444262306a36Sopenharmony_ci		.suite = {
444362306a36Sopenharmony_ci			.aead = __VECS(hmac_sha512_des_cbc_tv_temp)
444462306a36Sopenharmony_ci		}
444562306a36Sopenharmony_ci	}, {
444662306a36Sopenharmony_ci		.alg = "authenc(hmac(sha512),cbc(des3_ede))",
444762306a36Sopenharmony_ci		.test = alg_test_aead,
444862306a36Sopenharmony_ci		.suite = {
444962306a36Sopenharmony_ci			.aead = __VECS(hmac_sha512_des3_ede_cbc_tv_temp)
445062306a36Sopenharmony_ci		}
445162306a36Sopenharmony_ci	}, {
445262306a36Sopenharmony_ci		.alg = "authenc(hmac(sha512),ctr(aes))",
445362306a36Sopenharmony_ci		.test = alg_test_null,
445462306a36Sopenharmony_ci		.fips_allowed = 1,
445562306a36Sopenharmony_ci	}, {
445662306a36Sopenharmony_ci		.alg = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
445762306a36Sopenharmony_ci		.test = alg_test_null,
445862306a36Sopenharmony_ci		.fips_allowed = 1,
445962306a36Sopenharmony_ci	}, {
446062306a36Sopenharmony_ci		.alg = "blake2b-160",
446162306a36Sopenharmony_ci		.test = alg_test_hash,
446262306a36Sopenharmony_ci		.fips_allowed = 0,
446362306a36Sopenharmony_ci		.suite = {
446462306a36Sopenharmony_ci			.hash = __VECS(blake2b_160_tv_template)
446562306a36Sopenharmony_ci		}
446662306a36Sopenharmony_ci	}, {
446762306a36Sopenharmony_ci		.alg = "blake2b-256",
446862306a36Sopenharmony_ci		.test = alg_test_hash,
446962306a36Sopenharmony_ci		.fips_allowed = 0,
447062306a36Sopenharmony_ci		.suite = {
447162306a36Sopenharmony_ci			.hash = __VECS(blake2b_256_tv_template)
447262306a36Sopenharmony_ci		}
447362306a36Sopenharmony_ci	}, {
447462306a36Sopenharmony_ci		.alg = "blake2b-384",
447562306a36Sopenharmony_ci		.test = alg_test_hash,
447662306a36Sopenharmony_ci		.fips_allowed = 0,
447762306a36Sopenharmony_ci		.suite = {
447862306a36Sopenharmony_ci			.hash = __VECS(blake2b_384_tv_template)
447962306a36Sopenharmony_ci		}
448062306a36Sopenharmony_ci	}, {
448162306a36Sopenharmony_ci		.alg = "blake2b-512",
448262306a36Sopenharmony_ci		.test = alg_test_hash,
448362306a36Sopenharmony_ci		.fips_allowed = 0,
448462306a36Sopenharmony_ci		.suite = {
448562306a36Sopenharmony_ci			.hash = __VECS(blake2b_512_tv_template)
448662306a36Sopenharmony_ci		}
448762306a36Sopenharmony_ci	}, {
448862306a36Sopenharmony_ci		.alg = "cbc(aes)",
448962306a36Sopenharmony_ci		.test = alg_test_skcipher,
449062306a36Sopenharmony_ci		.fips_allowed = 1,
449162306a36Sopenharmony_ci		.suite = {
449262306a36Sopenharmony_ci			.cipher = __VECS(aes_cbc_tv_template)
449362306a36Sopenharmony_ci		},
449462306a36Sopenharmony_ci	}, {
449562306a36Sopenharmony_ci		.alg = "cbc(anubis)",
449662306a36Sopenharmony_ci		.test = alg_test_skcipher,
449762306a36Sopenharmony_ci		.suite = {
449862306a36Sopenharmony_ci			.cipher = __VECS(anubis_cbc_tv_template)
449962306a36Sopenharmony_ci		},
450062306a36Sopenharmony_ci	}, {
450162306a36Sopenharmony_ci		.alg = "cbc(aria)",
450262306a36Sopenharmony_ci		.test = alg_test_skcipher,
450362306a36Sopenharmony_ci		.suite = {
450462306a36Sopenharmony_ci			.cipher = __VECS(aria_cbc_tv_template)
450562306a36Sopenharmony_ci		},
450662306a36Sopenharmony_ci	}, {
450762306a36Sopenharmony_ci		.alg = "cbc(blowfish)",
450862306a36Sopenharmony_ci		.test = alg_test_skcipher,
450962306a36Sopenharmony_ci		.suite = {
451062306a36Sopenharmony_ci			.cipher = __VECS(bf_cbc_tv_template)
451162306a36Sopenharmony_ci		},
451262306a36Sopenharmony_ci	}, {
451362306a36Sopenharmony_ci		.alg = "cbc(camellia)",
451462306a36Sopenharmony_ci		.test = alg_test_skcipher,
451562306a36Sopenharmony_ci		.suite = {
451662306a36Sopenharmony_ci			.cipher = __VECS(camellia_cbc_tv_template)
451762306a36Sopenharmony_ci		},
451862306a36Sopenharmony_ci	}, {
451962306a36Sopenharmony_ci		.alg = "cbc(cast5)",
452062306a36Sopenharmony_ci		.test = alg_test_skcipher,
452162306a36Sopenharmony_ci		.suite = {
452262306a36Sopenharmony_ci			.cipher = __VECS(cast5_cbc_tv_template)
452362306a36Sopenharmony_ci		},
452462306a36Sopenharmony_ci	}, {
452562306a36Sopenharmony_ci		.alg = "cbc(cast6)",
452662306a36Sopenharmony_ci		.test = alg_test_skcipher,
452762306a36Sopenharmony_ci		.suite = {
452862306a36Sopenharmony_ci			.cipher = __VECS(cast6_cbc_tv_template)
452962306a36Sopenharmony_ci		},
453062306a36Sopenharmony_ci	}, {
453162306a36Sopenharmony_ci		.alg = "cbc(des)",
453262306a36Sopenharmony_ci		.test = alg_test_skcipher,
453362306a36Sopenharmony_ci		.suite = {
453462306a36Sopenharmony_ci			.cipher = __VECS(des_cbc_tv_template)
453562306a36Sopenharmony_ci		},
453662306a36Sopenharmony_ci	}, {
453762306a36Sopenharmony_ci		.alg = "cbc(des3_ede)",
453862306a36Sopenharmony_ci		.test = alg_test_skcipher,
453962306a36Sopenharmony_ci		.suite = {
454062306a36Sopenharmony_ci			.cipher = __VECS(des3_ede_cbc_tv_template)
454162306a36Sopenharmony_ci		},
454262306a36Sopenharmony_ci	}, {
454362306a36Sopenharmony_ci		/* Same as cbc(aes) except the key is stored in
454462306a36Sopenharmony_ci		 * hardware secure memory which we reference by index
454562306a36Sopenharmony_ci		 */
454662306a36Sopenharmony_ci		.alg = "cbc(paes)",
454762306a36Sopenharmony_ci		.test = alg_test_null,
454862306a36Sopenharmony_ci		.fips_allowed = 1,
454962306a36Sopenharmony_ci	}, {
455062306a36Sopenharmony_ci		/* Same as cbc(sm4) except the key is stored in
455162306a36Sopenharmony_ci		 * hardware secure memory which we reference by index
455262306a36Sopenharmony_ci		 */
455362306a36Sopenharmony_ci		.alg = "cbc(psm4)",
455462306a36Sopenharmony_ci		.test = alg_test_null,
455562306a36Sopenharmony_ci	}, {
455662306a36Sopenharmony_ci		.alg = "cbc(serpent)",
455762306a36Sopenharmony_ci		.test = alg_test_skcipher,
455862306a36Sopenharmony_ci		.suite = {
455962306a36Sopenharmony_ci			.cipher = __VECS(serpent_cbc_tv_template)
456062306a36Sopenharmony_ci		},
456162306a36Sopenharmony_ci	}, {
456262306a36Sopenharmony_ci		.alg = "cbc(sm4)",
456362306a36Sopenharmony_ci		.test = alg_test_skcipher,
456462306a36Sopenharmony_ci		.suite = {
456562306a36Sopenharmony_ci			.cipher = __VECS(sm4_cbc_tv_template)
456662306a36Sopenharmony_ci		}
456762306a36Sopenharmony_ci	}, {
456862306a36Sopenharmony_ci		.alg = "cbc(twofish)",
456962306a36Sopenharmony_ci		.test = alg_test_skcipher,
457062306a36Sopenharmony_ci		.suite = {
457162306a36Sopenharmony_ci			.cipher = __VECS(tf_cbc_tv_template)
457262306a36Sopenharmony_ci		},
457362306a36Sopenharmony_ci	}, {
457462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
457562306a36Sopenharmony_ci		.alg = "cbc-paes-s390",
457662306a36Sopenharmony_ci		.fips_allowed = 1,
457762306a36Sopenharmony_ci		.test = alg_test_skcipher,
457862306a36Sopenharmony_ci		.suite = {
457962306a36Sopenharmony_ci			.cipher = __VECS(aes_cbc_tv_template)
458062306a36Sopenharmony_ci		}
458162306a36Sopenharmony_ci	}, {
458262306a36Sopenharmony_ci#endif
458362306a36Sopenharmony_ci		.alg = "cbcmac(aes)",
458462306a36Sopenharmony_ci		.test = alg_test_hash,
458562306a36Sopenharmony_ci		.suite = {
458662306a36Sopenharmony_ci			.hash = __VECS(aes_cbcmac_tv_template)
458762306a36Sopenharmony_ci		}
458862306a36Sopenharmony_ci	}, {
458962306a36Sopenharmony_ci		.alg = "cbcmac(sm4)",
459062306a36Sopenharmony_ci		.test = alg_test_hash,
459162306a36Sopenharmony_ci		.suite = {
459262306a36Sopenharmony_ci			.hash = __VECS(sm4_cbcmac_tv_template)
459362306a36Sopenharmony_ci		}
459462306a36Sopenharmony_ci	}, {
459562306a36Sopenharmony_ci		.alg = "ccm(aes)",
459662306a36Sopenharmony_ci		.generic_driver = "ccm_base(ctr(aes-generic),cbcmac(aes-generic))",
459762306a36Sopenharmony_ci		.test = alg_test_aead,
459862306a36Sopenharmony_ci		.fips_allowed = 1,
459962306a36Sopenharmony_ci		.suite = {
460062306a36Sopenharmony_ci			.aead = {
460162306a36Sopenharmony_ci				____VECS(aes_ccm_tv_template),
460262306a36Sopenharmony_ci				.einval_allowed = 1,
460362306a36Sopenharmony_ci			}
460462306a36Sopenharmony_ci		}
460562306a36Sopenharmony_ci	}, {
460662306a36Sopenharmony_ci		.alg = "ccm(sm4)",
460762306a36Sopenharmony_ci		.generic_driver = "ccm_base(ctr(sm4-generic),cbcmac(sm4-generic))",
460862306a36Sopenharmony_ci		.test = alg_test_aead,
460962306a36Sopenharmony_ci		.suite = {
461062306a36Sopenharmony_ci			.aead = {
461162306a36Sopenharmony_ci				____VECS(sm4_ccm_tv_template),
461262306a36Sopenharmony_ci				.einval_allowed = 1,
461362306a36Sopenharmony_ci			}
461462306a36Sopenharmony_ci		}
461562306a36Sopenharmony_ci	}, {
461662306a36Sopenharmony_ci		.alg = "cfb(aes)",
461762306a36Sopenharmony_ci		.test = alg_test_skcipher,
461862306a36Sopenharmony_ci		.fips_allowed = 1,
461962306a36Sopenharmony_ci		.suite = {
462062306a36Sopenharmony_ci			.cipher = __VECS(aes_cfb_tv_template)
462162306a36Sopenharmony_ci		},
462262306a36Sopenharmony_ci	}, {
462362306a36Sopenharmony_ci		.alg = "cfb(aria)",
462462306a36Sopenharmony_ci		.test = alg_test_skcipher,
462562306a36Sopenharmony_ci		.suite = {
462662306a36Sopenharmony_ci			.cipher = __VECS(aria_cfb_tv_template)
462762306a36Sopenharmony_ci		},
462862306a36Sopenharmony_ci	}, {
462962306a36Sopenharmony_ci		.alg = "cfb(sm4)",
463062306a36Sopenharmony_ci		.test = alg_test_skcipher,
463162306a36Sopenharmony_ci		.suite = {
463262306a36Sopenharmony_ci			.cipher = __VECS(sm4_cfb_tv_template)
463362306a36Sopenharmony_ci		}
463462306a36Sopenharmony_ci	}, {
463562306a36Sopenharmony_ci		.alg = "chacha20",
463662306a36Sopenharmony_ci		.test = alg_test_skcipher,
463762306a36Sopenharmony_ci		.suite = {
463862306a36Sopenharmony_ci			.cipher = __VECS(chacha20_tv_template)
463962306a36Sopenharmony_ci		},
464062306a36Sopenharmony_ci	}, {
464162306a36Sopenharmony_ci		.alg = "cmac(aes)",
464262306a36Sopenharmony_ci		.fips_allowed = 1,
464362306a36Sopenharmony_ci		.test = alg_test_hash,
464462306a36Sopenharmony_ci		.suite = {
464562306a36Sopenharmony_ci			.hash = __VECS(aes_cmac128_tv_template)
464662306a36Sopenharmony_ci		}
464762306a36Sopenharmony_ci	}, {
464862306a36Sopenharmony_ci		.alg = "cmac(camellia)",
464962306a36Sopenharmony_ci		.test = alg_test_hash,
465062306a36Sopenharmony_ci		.suite = {
465162306a36Sopenharmony_ci			.hash = __VECS(camellia_cmac128_tv_template)
465262306a36Sopenharmony_ci		}
465362306a36Sopenharmony_ci	}, {
465462306a36Sopenharmony_ci		.alg = "cmac(des3_ede)",
465562306a36Sopenharmony_ci		.test = alg_test_hash,
465662306a36Sopenharmony_ci		.suite = {
465762306a36Sopenharmony_ci			.hash = __VECS(des3_ede_cmac64_tv_template)
465862306a36Sopenharmony_ci		}
465962306a36Sopenharmony_ci	}, {
466062306a36Sopenharmony_ci		.alg = "cmac(sm4)",
466162306a36Sopenharmony_ci		.test = alg_test_hash,
466262306a36Sopenharmony_ci		.suite = {
466362306a36Sopenharmony_ci			.hash = __VECS(sm4_cmac128_tv_template)
466462306a36Sopenharmony_ci		}
466562306a36Sopenharmony_ci	}, {
466662306a36Sopenharmony_ci		.alg = "compress_null",
466762306a36Sopenharmony_ci		.test = alg_test_null,
466862306a36Sopenharmony_ci	}, {
466962306a36Sopenharmony_ci		.alg = "crc32",
467062306a36Sopenharmony_ci		.test = alg_test_hash,
467162306a36Sopenharmony_ci		.fips_allowed = 1,
467262306a36Sopenharmony_ci		.suite = {
467362306a36Sopenharmony_ci			.hash = __VECS(crc32_tv_template)
467462306a36Sopenharmony_ci		}
467562306a36Sopenharmony_ci	}, {
467662306a36Sopenharmony_ci		.alg = "crc32c",
467762306a36Sopenharmony_ci		.test = alg_test_crc32c,
467862306a36Sopenharmony_ci		.fips_allowed = 1,
467962306a36Sopenharmony_ci		.suite = {
468062306a36Sopenharmony_ci			.hash = __VECS(crc32c_tv_template)
468162306a36Sopenharmony_ci		}
468262306a36Sopenharmony_ci	}, {
468362306a36Sopenharmony_ci		.alg = "crc64-rocksoft",
468462306a36Sopenharmony_ci		.test = alg_test_hash,
468562306a36Sopenharmony_ci		.fips_allowed = 1,
468662306a36Sopenharmony_ci		.suite = {
468762306a36Sopenharmony_ci			.hash = __VECS(crc64_rocksoft_tv_template)
468862306a36Sopenharmony_ci		}
468962306a36Sopenharmony_ci	}, {
469062306a36Sopenharmony_ci		.alg = "crct10dif",
469162306a36Sopenharmony_ci		.test = alg_test_hash,
469262306a36Sopenharmony_ci		.fips_allowed = 1,
469362306a36Sopenharmony_ci		.suite = {
469462306a36Sopenharmony_ci			.hash = __VECS(crct10dif_tv_template)
469562306a36Sopenharmony_ci		}
469662306a36Sopenharmony_ci	}, {
469762306a36Sopenharmony_ci		.alg = "ctr(aes)",
469862306a36Sopenharmony_ci		.test = alg_test_skcipher,
469962306a36Sopenharmony_ci		.fips_allowed = 1,
470062306a36Sopenharmony_ci		.suite = {
470162306a36Sopenharmony_ci			.cipher = __VECS(aes_ctr_tv_template)
470262306a36Sopenharmony_ci		}
470362306a36Sopenharmony_ci	}, {
470462306a36Sopenharmony_ci		.alg = "ctr(aria)",
470562306a36Sopenharmony_ci		.test = alg_test_skcipher,
470662306a36Sopenharmony_ci		.suite = {
470762306a36Sopenharmony_ci			.cipher = __VECS(aria_ctr_tv_template)
470862306a36Sopenharmony_ci		}
470962306a36Sopenharmony_ci	}, {
471062306a36Sopenharmony_ci		.alg = "ctr(blowfish)",
471162306a36Sopenharmony_ci		.test = alg_test_skcipher,
471262306a36Sopenharmony_ci		.suite = {
471362306a36Sopenharmony_ci			.cipher = __VECS(bf_ctr_tv_template)
471462306a36Sopenharmony_ci		}
471562306a36Sopenharmony_ci	}, {
471662306a36Sopenharmony_ci		.alg = "ctr(camellia)",
471762306a36Sopenharmony_ci		.test = alg_test_skcipher,
471862306a36Sopenharmony_ci		.suite = {
471962306a36Sopenharmony_ci			.cipher = __VECS(camellia_ctr_tv_template)
472062306a36Sopenharmony_ci		}
472162306a36Sopenharmony_ci	}, {
472262306a36Sopenharmony_ci		.alg = "ctr(cast5)",
472362306a36Sopenharmony_ci		.test = alg_test_skcipher,
472462306a36Sopenharmony_ci		.suite = {
472562306a36Sopenharmony_ci			.cipher = __VECS(cast5_ctr_tv_template)
472662306a36Sopenharmony_ci		}
472762306a36Sopenharmony_ci	}, {
472862306a36Sopenharmony_ci		.alg = "ctr(cast6)",
472962306a36Sopenharmony_ci		.test = alg_test_skcipher,
473062306a36Sopenharmony_ci		.suite = {
473162306a36Sopenharmony_ci			.cipher = __VECS(cast6_ctr_tv_template)
473262306a36Sopenharmony_ci		}
473362306a36Sopenharmony_ci	}, {
473462306a36Sopenharmony_ci		.alg = "ctr(des)",
473562306a36Sopenharmony_ci		.test = alg_test_skcipher,
473662306a36Sopenharmony_ci		.suite = {
473762306a36Sopenharmony_ci			.cipher = __VECS(des_ctr_tv_template)
473862306a36Sopenharmony_ci		}
473962306a36Sopenharmony_ci	}, {
474062306a36Sopenharmony_ci		.alg = "ctr(des3_ede)",
474162306a36Sopenharmony_ci		.test = alg_test_skcipher,
474262306a36Sopenharmony_ci		.suite = {
474362306a36Sopenharmony_ci			.cipher = __VECS(des3_ede_ctr_tv_template)
474462306a36Sopenharmony_ci		}
474562306a36Sopenharmony_ci	}, {
474662306a36Sopenharmony_ci		/* Same as ctr(aes) except the key is stored in
474762306a36Sopenharmony_ci		 * hardware secure memory which we reference by index
474862306a36Sopenharmony_ci		 */
474962306a36Sopenharmony_ci		.alg = "ctr(paes)",
475062306a36Sopenharmony_ci		.test = alg_test_null,
475162306a36Sopenharmony_ci		.fips_allowed = 1,
475262306a36Sopenharmony_ci	}, {
475362306a36Sopenharmony_ci
475462306a36Sopenharmony_ci		/* Same as ctr(sm4) except the key is stored in
475562306a36Sopenharmony_ci		 * hardware secure memory which we reference by index
475662306a36Sopenharmony_ci		 */
475762306a36Sopenharmony_ci		.alg = "ctr(psm4)",
475862306a36Sopenharmony_ci		.test = alg_test_null,
475962306a36Sopenharmony_ci	}, {
476062306a36Sopenharmony_ci		.alg = "ctr(serpent)",
476162306a36Sopenharmony_ci		.test = alg_test_skcipher,
476262306a36Sopenharmony_ci		.suite = {
476362306a36Sopenharmony_ci			.cipher = __VECS(serpent_ctr_tv_template)
476462306a36Sopenharmony_ci		}
476562306a36Sopenharmony_ci	}, {
476662306a36Sopenharmony_ci		.alg = "ctr(sm4)",
476762306a36Sopenharmony_ci		.test = alg_test_skcipher,
476862306a36Sopenharmony_ci		.suite = {
476962306a36Sopenharmony_ci			.cipher = __VECS(sm4_ctr_tv_template)
477062306a36Sopenharmony_ci		}
477162306a36Sopenharmony_ci	}, {
477262306a36Sopenharmony_ci		.alg = "ctr(twofish)",
477362306a36Sopenharmony_ci		.test = alg_test_skcipher,
477462306a36Sopenharmony_ci		.suite = {
477562306a36Sopenharmony_ci			.cipher = __VECS(tf_ctr_tv_template)
477662306a36Sopenharmony_ci		}
477762306a36Sopenharmony_ci	}, {
477862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
477962306a36Sopenharmony_ci		.alg = "ctr-paes-s390",
478062306a36Sopenharmony_ci		.fips_allowed = 1,
478162306a36Sopenharmony_ci		.test = alg_test_skcipher,
478262306a36Sopenharmony_ci		.suite = {
478362306a36Sopenharmony_ci			.cipher = __VECS(aes_ctr_tv_template)
478462306a36Sopenharmony_ci		}
478562306a36Sopenharmony_ci	}, {
478662306a36Sopenharmony_ci#endif
478762306a36Sopenharmony_ci		.alg = "cts(cbc(aes))",
478862306a36Sopenharmony_ci		.test = alg_test_skcipher,
478962306a36Sopenharmony_ci		.fips_allowed = 1,
479062306a36Sopenharmony_ci		.suite = {
479162306a36Sopenharmony_ci			.cipher = __VECS(cts_mode_tv_template)
479262306a36Sopenharmony_ci		}
479362306a36Sopenharmony_ci	}, {
479462306a36Sopenharmony_ci		/* Same as cts(cbc((aes)) except the key is stored in
479562306a36Sopenharmony_ci		 * hardware secure memory which we reference by index
479662306a36Sopenharmony_ci		 */
479762306a36Sopenharmony_ci		.alg = "cts(cbc(paes))",
479862306a36Sopenharmony_ci		.test = alg_test_null,
479962306a36Sopenharmony_ci		.fips_allowed = 1,
480062306a36Sopenharmony_ci	}, {
480162306a36Sopenharmony_ci		.alg = "cts(cbc(sm4))",
480262306a36Sopenharmony_ci		.test = alg_test_skcipher,
480362306a36Sopenharmony_ci		.suite = {
480462306a36Sopenharmony_ci			.cipher = __VECS(sm4_cts_tv_template)
480562306a36Sopenharmony_ci		}
480662306a36Sopenharmony_ci	}, {
480762306a36Sopenharmony_ci		.alg = "curve25519",
480862306a36Sopenharmony_ci		.test = alg_test_kpp,
480962306a36Sopenharmony_ci		.suite = {
481062306a36Sopenharmony_ci			.kpp = __VECS(curve25519_tv_template)
481162306a36Sopenharmony_ci		}
481262306a36Sopenharmony_ci	}, {
481362306a36Sopenharmony_ci		.alg = "deflate",
481462306a36Sopenharmony_ci		.test = alg_test_comp,
481562306a36Sopenharmony_ci		.fips_allowed = 1,
481662306a36Sopenharmony_ci		.suite = {
481762306a36Sopenharmony_ci			.comp = {
481862306a36Sopenharmony_ci				.comp = __VECS(deflate_comp_tv_template),
481962306a36Sopenharmony_ci				.decomp = __VECS(deflate_decomp_tv_template)
482062306a36Sopenharmony_ci			}
482162306a36Sopenharmony_ci		}
482262306a36Sopenharmony_ci	}, {
482362306a36Sopenharmony_ci		.alg = "dh",
482462306a36Sopenharmony_ci		.test = alg_test_kpp,
482562306a36Sopenharmony_ci		.suite = {
482662306a36Sopenharmony_ci			.kpp = __VECS(dh_tv_template)
482762306a36Sopenharmony_ci		}
482862306a36Sopenharmony_ci	}, {
482962306a36Sopenharmony_ci		.alg = "digest_null",
483062306a36Sopenharmony_ci		.test = alg_test_null,
483162306a36Sopenharmony_ci	}, {
483262306a36Sopenharmony_ci		.alg = "drbg_nopr_ctr_aes128",
483362306a36Sopenharmony_ci		.test = alg_test_drbg,
483462306a36Sopenharmony_ci		.fips_allowed = 1,
483562306a36Sopenharmony_ci		.suite = {
483662306a36Sopenharmony_ci			.drbg = __VECS(drbg_nopr_ctr_aes128_tv_template)
483762306a36Sopenharmony_ci		}
483862306a36Sopenharmony_ci	}, {
483962306a36Sopenharmony_ci		.alg = "drbg_nopr_ctr_aes192",
484062306a36Sopenharmony_ci		.test = alg_test_drbg,
484162306a36Sopenharmony_ci		.fips_allowed = 1,
484262306a36Sopenharmony_ci		.suite = {
484362306a36Sopenharmony_ci			.drbg = __VECS(drbg_nopr_ctr_aes192_tv_template)
484462306a36Sopenharmony_ci		}
484562306a36Sopenharmony_ci	}, {
484662306a36Sopenharmony_ci		.alg = "drbg_nopr_ctr_aes256",
484762306a36Sopenharmony_ci		.test = alg_test_drbg,
484862306a36Sopenharmony_ci		.fips_allowed = 1,
484962306a36Sopenharmony_ci		.suite = {
485062306a36Sopenharmony_ci			.drbg = __VECS(drbg_nopr_ctr_aes256_tv_template)
485162306a36Sopenharmony_ci		}
485262306a36Sopenharmony_ci	}, {
485362306a36Sopenharmony_ci		/*
485462306a36Sopenharmony_ci		 * There is no need to specifically test the DRBG with every
485562306a36Sopenharmony_ci		 * backend cipher -- covered by drbg_nopr_hmac_sha256 test
485662306a36Sopenharmony_ci		 */
485762306a36Sopenharmony_ci		.alg = "drbg_nopr_hmac_sha1",
485862306a36Sopenharmony_ci		.fips_allowed = 1,
485962306a36Sopenharmony_ci		.test = alg_test_null,
486062306a36Sopenharmony_ci	}, {
486162306a36Sopenharmony_ci		.alg = "drbg_nopr_hmac_sha256",
486262306a36Sopenharmony_ci		.test = alg_test_drbg,
486362306a36Sopenharmony_ci		.fips_allowed = 1,
486462306a36Sopenharmony_ci		.suite = {
486562306a36Sopenharmony_ci			.drbg = __VECS(drbg_nopr_hmac_sha256_tv_template)
486662306a36Sopenharmony_ci		}
486762306a36Sopenharmony_ci	}, {
486862306a36Sopenharmony_ci		/* covered by drbg_nopr_hmac_sha256 test */
486962306a36Sopenharmony_ci		.alg = "drbg_nopr_hmac_sha384",
487062306a36Sopenharmony_ci		.test = alg_test_null,
487162306a36Sopenharmony_ci	}, {
487262306a36Sopenharmony_ci		.alg = "drbg_nopr_hmac_sha512",
487362306a36Sopenharmony_ci		.test = alg_test_drbg,
487462306a36Sopenharmony_ci		.fips_allowed = 1,
487562306a36Sopenharmony_ci		.suite = {
487662306a36Sopenharmony_ci			.drbg = __VECS(drbg_nopr_hmac_sha512_tv_template)
487762306a36Sopenharmony_ci		}
487862306a36Sopenharmony_ci	}, {
487962306a36Sopenharmony_ci		.alg = "drbg_nopr_sha1",
488062306a36Sopenharmony_ci		.fips_allowed = 1,
488162306a36Sopenharmony_ci		.test = alg_test_null,
488262306a36Sopenharmony_ci	}, {
488362306a36Sopenharmony_ci		.alg = "drbg_nopr_sha256",
488462306a36Sopenharmony_ci		.test = alg_test_drbg,
488562306a36Sopenharmony_ci		.fips_allowed = 1,
488662306a36Sopenharmony_ci		.suite = {
488762306a36Sopenharmony_ci			.drbg = __VECS(drbg_nopr_sha256_tv_template)
488862306a36Sopenharmony_ci		}
488962306a36Sopenharmony_ci	}, {
489062306a36Sopenharmony_ci		/* covered by drbg_nopr_sha256 test */
489162306a36Sopenharmony_ci		.alg = "drbg_nopr_sha384",
489262306a36Sopenharmony_ci		.test = alg_test_null,
489362306a36Sopenharmony_ci	}, {
489462306a36Sopenharmony_ci		.alg = "drbg_nopr_sha512",
489562306a36Sopenharmony_ci		.fips_allowed = 1,
489662306a36Sopenharmony_ci		.test = alg_test_null,
489762306a36Sopenharmony_ci	}, {
489862306a36Sopenharmony_ci		.alg = "drbg_pr_ctr_aes128",
489962306a36Sopenharmony_ci		.test = alg_test_drbg,
490062306a36Sopenharmony_ci		.fips_allowed = 1,
490162306a36Sopenharmony_ci		.suite = {
490262306a36Sopenharmony_ci			.drbg = __VECS(drbg_pr_ctr_aes128_tv_template)
490362306a36Sopenharmony_ci		}
490462306a36Sopenharmony_ci	}, {
490562306a36Sopenharmony_ci		/* covered by drbg_pr_ctr_aes128 test */
490662306a36Sopenharmony_ci		.alg = "drbg_pr_ctr_aes192",
490762306a36Sopenharmony_ci		.fips_allowed = 1,
490862306a36Sopenharmony_ci		.test = alg_test_null,
490962306a36Sopenharmony_ci	}, {
491062306a36Sopenharmony_ci		.alg = "drbg_pr_ctr_aes256",
491162306a36Sopenharmony_ci		.fips_allowed = 1,
491262306a36Sopenharmony_ci		.test = alg_test_null,
491362306a36Sopenharmony_ci	}, {
491462306a36Sopenharmony_ci		.alg = "drbg_pr_hmac_sha1",
491562306a36Sopenharmony_ci		.fips_allowed = 1,
491662306a36Sopenharmony_ci		.test = alg_test_null,
491762306a36Sopenharmony_ci	}, {
491862306a36Sopenharmony_ci		.alg = "drbg_pr_hmac_sha256",
491962306a36Sopenharmony_ci		.test = alg_test_drbg,
492062306a36Sopenharmony_ci		.fips_allowed = 1,
492162306a36Sopenharmony_ci		.suite = {
492262306a36Sopenharmony_ci			.drbg = __VECS(drbg_pr_hmac_sha256_tv_template)
492362306a36Sopenharmony_ci		}
492462306a36Sopenharmony_ci	}, {
492562306a36Sopenharmony_ci		/* covered by drbg_pr_hmac_sha256 test */
492662306a36Sopenharmony_ci		.alg = "drbg_pr_hmac_sha384",
492762306a36Sopenharmony_ci		.test = alg_test_null,
492862306a36Sopenharmony_ci	}, {
492962306a36Sopenharmony_ci		.alg = "drbg_pr_hmac_sha512",
493062306a36Sopenharmony_ci		.test = alg_test_null,
493162306a36Sopenharmony_ci		.fips_allowed = 1,
493262306a36Sopenharmony_ci	}, {
493362306a36Sopenharmony_ci		.alg = "drbg_pr_sha1",
493462306a36Sopenharmony_ci		.fips_allowed = 1,
493562306a36Sopenharmony_ci		.test = alg_test_null,
493662306a36Sopenharmony_ci	}, {
493762306a36Sopenharmony_ci		.alg = "drbg_pr_sha256",
493862306a36Sopenharmony_ci		.test = alg_test_drbg,
493962306a36Sopenharmony_ci		.fips_allowed = 1,
494062306a36Sopenharmony_ci		.suite = {
494162306a36Sopenharmony_ci			.drbg = __VECS(drbg_pr_sha256_tv_template)
494262306a36Sopenharmony_ci		}
494362306a36Sopenharmony_ci	}, {
494462306a36Sopenharmony_ci		/* covered by drbg_pr_sha256 test */
494562306a36Sopenharmony_ci		.alg = "drbg_pr_sha384",
494662306a36Sopenharmony_ci		.test = alg_test_null,
494762306a36Sopenharmony_ci	}, {
494862306a36Sopenharmony_ci		.alg = "drbg_pr_sha512",
494962306a36Sopenharmony_ci		.fips_allowed = 1,
495062306a36Sopenharmony_ci		.test = alg_test_null,
495162306a36Sopenharmony_ci	}, {
495262306a36Sopenharmony_ci		.alg = "ecb(aes)",
495362306a36Sopenharmony_ci		.test = alg_test_skcipher,
495462306a36Sopenharmony_ci		.fips_allowed = 1,
495562306a36Sopenharmony_ci		.suite = {
495662306a36Sopenharmony_ci			.cipher = __VECS(aes_tv_template)
495762306a36Sopenharmony_ci		}
495862306a36Sopenharmony_ci	}, {
495962306a36Sopenharmony_ci		.alg = "ecb(anubis)",
496062306a36Sopenharmony_ci		.test = alg_test_skcipher,
496162306a36Sopenharmony_ci		.suite = {
496262306a36Sopenharmony_ci			.cipher = __VECS(anubis_tv_template)
496362306a36Sopenharmony_ci		}
496462306a36Sopenharmony_ci	}, {
496562306a36Sopenharmony_ci		.alg = "ecb(arc4)",
496662306a36Sopenharmony_ci		.generic_driver = "ecb(arc4)-generic",
496762306a36Sopenharmony_ci		.test = alg_test_skcipher,
496862306a36Sopenharmony_ci		.suite = {
496962306a36Sopenharmony_ci			.cipher = __VECS(arc4_tv_template)
497062306a36Sopenharmony_ci		}
497162306a36Sopenharmony_ci	}, {
497262306a36Sopenharmony_ci		.alg = "ecb(aria)",
497362306a36Sopenharmony_ci		.test = alg_test_skcipher,
497462306a36Sopenharmony_ci		.suite = {
497562306a36Sopenharmony_ci			.cipher = __VECS(aria_tv_template)
497662306a36Sopenharmony_ci		}
497762306a36Sopenharmony_ci	}, {
497862306a36Sopenharmony_ci		.alg = "ecb(blowfish)",
497962306a36Sopenharmony_ci		.test = alg_test_skcipher,
498062306a36Sopenharmony_ci		.suite = {
498162306a36Sopenharmony_ci			.cipher = __VECS(bf_tv_template)
498262306a36Sopenharmony_ci		}
498362306a36Sopenharmony_ci	}, {
498462306a36Sopenharmony_ci		.alg = "ecb(camellia)",
498562306a36Sopenharmony_ci		.test = alg_test_skcipher,
498662306a36Sopenharmony_ci		.suite = {
498762306a36Sopenharmony_ci			.cipher = __VECS(camellia_tv_template)
498862306a36Sopenharmony_ci		}
498962306a36Sopenharmony_ci	}, {
499062306a36Sopenharmony_ci		.alg = "ecb(cast5)",
499162306a36Sopenharmony_ci		.test = alg_test_skcipher,
499262306a36Sopenharmony_ci		.suite = {
499362306a36Sopenharmony_ci			.cipher = __VECS(cast5_tv_template)
499462306a36Sopenharmony_ci		}
499562306a36Sopenharmony_ci	}, {
499662306a36Sopenharmony_ci		.alg = "ecb(cast6)",
499762306a36Sopenharmony_ci		.test = alg_test_skcipher,
499862306a36Sopenharmony_ci		.suite = {
499962306a36Sopenharmony_ci			.cipher = __VECS(cast6_tv_template)
500062306a36Sopenharmony_ci		}
500162306a36Sopenharmony_ci	}, {
500262306a36Sopenharmony_ci		.alg = "ecb(cipher_null)",
500362306a36Sopenharmony_ci		.test = alg_test_null,
500462306a36Sopenharmony_ci		.fips_allowed = 1,
500562306a36Sopenharmony_ci	}, {
500662306a36Sopenharmony_ci		.alg = "ecb(des)",
500762306a36Sopenharmony_ci		.test = alg_test_skcipher,
500862306a36Sopenharmony_ci		.suite = {
500962306a36Sopenharmony_ci			.cipher = __VECS(des_tv_template)
501062306a36Sopenharmony_ci		}
501162306a36Sopenharmony_ci	}, {
501262306a36Sopenharmony_ci		.alg = "ecb(des3_ede)",
501362306a36Sopenharmony_ci		.test = alg_test_skcipher,
501462306a36Sopenharmony_ci		.suite = {
501562306a36Sopenharmony_ci			.cipher = __VECS(des3_ede_tv_template)
501662306a36Sopenharmony_ci		}
501762306a36Sopenharmony_ci	}, {
501862306a36Sopenharmony_ci		.alg = "ecb(fcrypt)",
501962306a36Sopenharmony_ci		.test = alg_test_skcipher,
502062306a36Sopenharmony_ci		.suite = {
502162306a36Sopenharmony_ci			.cipher = {
502262306a36Sopenharmony_ci				.vecs = fcrypt_pcbc_tv_template,
502362306a36Sopenharmony_ci				.count = 1
502462306a36Sopenharmony_ci			}
502562306a36Sopenharmony_ci		}
502662306a36Sopenharmony_ci	}, {
502762306a36Sopenharmony_ci		.alg = "ecb(khazad)",
502862306a36Sopenharmony_ci		.test = alg_test_skcipher,
502962306a36Sopenharmony_ci		.suite = {
503062306a36Sopenharmony_ci			.cipher = __VECS(khazad_tv_template)
503162306a36Sopenharmony_ci		}
503262306a36Sopenharmony_ci	}, {
503362306a36Sopenharmony_ci		/* Same as ecb(aes) except the key is stored in
503462306a36Sopenharmony_ci		 * hardware secure memory which we reference by index
503562306a36Sopenharmony_ci		 */
503662306a36Sopenharmony_ci		.alg = "ecb(paes)",
503762306a36Sopenharmony_ci		.test = alg_test_null,
503862306a36Sopenharmony_ci		.fips_allowed = 1,
503962306a36Sopenharmony_ci	}, {
504062306a36Sopenharmony_ci		.alg = "ecb(seed)",
504162306a36Sopenharmony_ci		.test = alg_test_skcipher,
504262306a36Sopenharmony_ci		.suite = {
504362306a36Sopenharmony_ci			.cipher = __VECS(seed_tv_template)
504462306a36Sopenharmony_ci		}
504562306a36Sopenharmony_ci	}, {
504662306a36Sopenharmony_ci		.alg = "ecb(serpent)",
504762306a36Sopenharmony_ci		.test = alg_test_skcipher,
504862306a36Sopenharmony_ci		.suite = {
504962306a36Sopenharmony_ci			.cipher = __VECS(serpent_tv_template)
505062306a36Sopenharmony_ci		}
505162306a36Sopenharmony_ci	}, {
505262306a36Sopenharmony_ci		.alg = "ecb(sm4)",
505362306a36Sopenharmony_ci		.test = alg_test_skcipher,
505462306a36Sopenharmony_ci		.suite = {
505562306a36Sopenharmony_ci			.cipher = __VECS(sm4_tv_template)
505662306a36Sopenharmony_ci		}
505762306a36Sopenharmony_ci	}, {
505862306a36Sopenharmony_ci		.alg = "ecb(tea)",
505962306a36Sopenharmony_ci		.test = alg_test_skcipher,
506062306a36Sopenharmony_ci		.suite = {
506162306a36Sopenharmony_ci			.cipher = __VECS(tea_tv_template)
506262306a36Sopenharmony_ci		}
506362306a36Sopenharmony_ci	}, {
506462306a36Sopenharmony_ci		.alg = "ecb(twofish)",
506562306a36Sopenharmony_ci		.test = alg_test_skcipher,
506662306a36Sopenharmony_ci		.suite = {
506762306a36Sopenharmony_ci			.cipher = __VECS(tf_tv_template)
506862306a36Sopenharmony_ci		}
506962306a36Sopenharmony_ci	}, {
507062306a36Sopenharmony_ci		.alg = "ecb(xeta)",
507162306a36Sopenharmony_ci		.test = alg_test_skcipher,
507262306a36Sopenharmony_ci		.suite = {
507362306a36Sopenharmony_ci			.cipher = __VECS(xeta_tv_template)
507462306a36Sopenharmony_ci		}
507562306a36Sopenharmony_ci	}, {
507662306a36Sopenharmony_ci		.alg = "ecb(xtea)",
507762306a36Sopenharmony_ci		.test = alg_test_skcipher,
507862306a36Sopenharmony_ci		.suite = {
507962306a36Sopenharmony_ci			.cipher = __VECS(xtea_tv_template)
508062306a36Sopenharmony_ci		}
508162306a36Sopenharmony_ci	}, {
508262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
508362306a36Sopenharmony_ci		.alg = "ecb-paes-s390",
508462306a36Sopenharmony_ci		.fips_allowed = 1,
508562306a36Sopenharmony_ci		.test = alg_test_skcipher,
508662306a36Sopenharmony_ci		.suite = {
508762306a36Sopenharmony_ci			.cipher = __VECS(aes_tv_template)
508862306a36Sopenharmony_ci		}
508962306a36Sopenharmony_ci	}, {
509062306a36Sopenharmony_ci#endif
509162306a36Sopenharmony_ci		.alg = "ecdh-nist-p192",
509262306a36Sopenharmony_ci		.test = alg_test_kpp,
509362306a36Sopenharmony_ci		.suite = {
509462306a36Sopenharmony_ci			.kpp = __VECS(ecdh_p192_tv_template)
509562306a36Sopenharmony_ci		}
509662306a36Sopenharmony_ci	}, {
509762306a36Sopenharmony_ci		.alg = "ecdh-nist-p256",
509862306a36Sopenharmony_ci		.test = alg_test_kpp,
509962306a36Sopenharmony_ci		.fips_allowed = 1,
510062306a36Sopenharmony_ci		.suite = {
510162306a36Sopenharmony_ci			.kpp = __VECS(ecdh_p256_tv_template)
510262306a36Sopenharmony_ci		}
510362306a36Sopenharmony_ci	}, {
510462306a36Sopenharmony_ci		.alg = "ecdh-nist-p384",
510562306a36Sopenharmony_ci		.test = alg_test_kpp,
510662306a36Sopenharmony_ci		.fips_allowed = 1,
510762306a36Sopenharmony_ci		.suite = {
510862306a36Sopenharmony_ci			.kpp = __VECS(ecdh_p384_tv_template)
510962306a36Sopenharmony_ci		}
511062306a36Sopenharmony_ci	}, {
511162306a36Sopenharmony_ci		.alg = "ecdsa-nist-p192",
511262306a36Sopenharmony_ci		.test = alg_test_akcipher,
511362306a36Sopenharmony_ci		.suite = {
511462306a36Sopenharmony_ci			.akcipher = __VECS(ecdsa_nist_p192_tv_template)
511562306a36Sopenharmony_ci		}
511662306a36Sopenharmony_ci	}, {
511762306a36Sopenharmony_ci		.alg = "ecdsa-nist-p256",
511862306a36Sopenharmony_ci		.test = alg_test_akcipher,
511962306a36Sopenharmony_ci		.fips_allowed = 1,
512062306a36Sopenharmony_ci		.suite = {
512162306a36Sopenharmony_ci			.akcipher = __VECS(ecdsa_nist_p256_tv_template)
512262306a36Sopenharmony_ci		}
512362306a36Sopenharmony_ci	}, {
512462306a36Sopenharmony_ci		.alg = "ecdsa-nist-p384",
512562306a36Sopenharmony_ci		.test = alg_test_akcipher,
512662306a36Sopenharmony_ci		.fips_allowed = 1,
512762306a36Sopenharmony_ci		.suite = {
512862306a36Sopenharmony_ci			.akcipher = __VECS(ecdsa_nist_p384_tv_template)
512962306a36Sopenharmony_ci		}
513062306a36Sopenharmony_ci	}, {
513162306a36Sopenharmony_ci		.alg = "ecrdsa",
513262306a36Sopenharmony_ci		.test = alg_test_akcipher,
513362306a36Sopenharmony_ci		.suite = {
513462306a36Sopenharmony_ci			.akcipher = __VECS(ecrdsa_tv_template)
513562306a36Sopenharmony_ci		}
513662306a36Sopenharmony_ci	}, {
513762306a36Sopenharmony_ci		.alg = "essiv(authenc(hmac(sha256),cbc(aes)),sha256)",
513862306a36Sopenharmony_ci		.test = alg_test_aead,
513962306a36Sopenharmony_ci		.fips_allowed = 1,
514062306a36Sopenharmony_ci		.suite = {
514162306a36Sopenharmony_ci			.aead = __VECS(essiv_hmac_sha256_aes_cbc_tv_temp)
514262306a36Sopenharmony_ci		}
514362306a36Sopenharmony_ci	}, {
514462306a36Sopenharmony_ci		.alg = "essiv(cbc(aes),sha256)",
514562306a36Sopenharmony_ci		.test = alg_test_skcipher,
514662306a36Sopenharmony_ci		.fips_allowed = 1,
514762306a36Sopenharmony_ci		.suite = {
514862306a36Sopenharmony_ci			.cipher = __VECS(essiv_aes_cbc_tv_template)
514962306a36Sopenharmony_ci		}
515062306a36Sopenharmony_ci	}, {
515162306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_CRYPTO_DH_RFC7919_GROUPS)
515262306a36Sopenharmony_ci		.alg = "ffdhe2048(dh)",
515362306a36Sopenharmony_ci		.test = alg_test_kpp,
515462306a36Sopenharmony_ci		.fips_allowed = 1,
515562306a36Sopenharmony_ci		.suite = {
515662306a36Sopenharmony_ci			.kpp = __VECS(ffdhe2048_dh_tv_template)
515762306a36Sopenharmony_ci		}
515862306a36Sopenharmony_ci	}, {
515962306a36Sopenharmony_ci		.alg = "ffdhe3072(dh)",
516062306a36Sopenharmony_ci		.test = alg_test_kpp,
516162306a36Sopenharmony_ci		.fips_allowed = 1,
516262306a36Sopenharmony_ci		.suite = {
516362306a36Sopenharmony_ci			.kpp = __VECS(ffdhe3072_dh_tv_template)
516462306a36Sopenharmony_ci		}
516562306a36Sopenharmony_ci	}, {
516662306a36Sopenharmony_ci		.alg = "ffdhe4096(dh)",
516762306a36Sopenharmony_ci		.test = alg_test_kpp,
516862306a36Sopenharmony_ci		.fips_allowed = 1,
516962306a36Sopenharmony_ci		.suite = {
517062306a36Sopenharmony_ci			.kpp = __VECS(ffdhe4096_dh_tv_template)
517162306a36Sopenharmony_ci		}
517262306a36Sopenharmony_ci	}, {
517362306a36Sopenharmony_ci		.alg = "ffdhe6144(dh)",
517462306a36Sopenharmony_ci		.test = alg_test_kpp,
517562306a36Sopenharmony_ci		.fips_allowed = 1,
517662306a36Sopenharmony_ci		.suite = {
517762306a36Sopenharmony_ci			.kpp = __VECS(ffdhe6144_dh_tv_template)
517862306a36Sopenharmony_ci		}
517962306a36Sopenharmony_ci	}, {
518062306a36Sopenharmony_ci		.alg = "ffdhe8192(dh)",
518162306a36Sopenharmony_ci		.test = alg_test_kpp,
518262306a36Sopenharmony_ci		.fips_allowed = 1,
518362306a36Sopenharmony_ci		.suite = {
518462306a36Sopenharmony_ci			.kpp = __VECS(ffdhe8192_dh_tv_template)
518562306a36Sopenharmony_ci		}
518662306a36Sopenharmony_ci	}, {
518762306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_DH_RFC7919_GROUPS */
518862306a36Sopenharmony_ci		.alg = "gcm(aes)",
518962306a36Sopenharmony_ci		.generic_driver = "gcm_base(ctr(aes-generic),ghash-generic)",
519062306a36Sopenharmony_ci		.test = alg_test_aead,
519162306a36Sopenharmony_ci		.fips_allowed = 1,
519262306a36Sopenharmony_ci		.suite = {
519362306a36Sopenharmony_ci			.aead = __VECS(aes_gcm_tv_template)
519462306a36Sopenharmony_ci		}
519562306a36Sopenharmony_ci	}, {
519662306a36Sopenharmony_ci		.alg = "gcm(aria)",
519762306a36Sopenharmony_ci		.generic_driver = "gcm_base(ctr(aria-generic),ghash-generic)",
519862306a36Sopenharmony_ci		.test = alg_test_aead,
519962306a36Sopenharmony_ci		.suite = {
520062306a36Sopenharmony_ci			.aead = __VECS(aria_gcm_tv_template)
520162306a36Sopenharmony_ci		}
520262306a36Sopenharmony_ci	}, {
520362306a36Sopenharmony_ci		.alg = "gcm(sm4)",
520462306a36Sopenharmony_ci		.generic_driver = "gcm_base(ctr(sm4-generic),ghash-generic)",
520562306a36Sopenharmony_ci		.test = alg_test_aead,
520662306a36Sopenharmony_ci		.suite = {
520762306a36Sopenharmony_ci			.aead = __VECS(sm4_gcm_tv_template)
520862306a36Sopenharmony_ci		}
520962306a36Sopenharmony_ci	}, {
521062306a36Sopenharmony_ci		.alg = "ghash",
521162306a36Sopenharmony_ci		.test = alg_test_hash,
521262306a36Sopenharmony_ci		.suite = {
521362306a36Sopenharmony_ci			.hash = __VECS(ghash_tv_template)
521462306a36Sopenharmony_ci		}
521562306a36Sopenharmony_ci	}, {
521662306a36Sopenharmony_ci		.alg = "hctr2(aes)",
521762306a36Sopenharmony_ci		.generic_driver =
521862306a36Sopenharmony_ci		    "hctr2_base(xctr(aes-generic),polyval-generic)",
521962306a36Sopenharmony_ci		.test = alg_test_skcipher,
522062306a36Sopenharmony_ci		.suite = {
522162306a36Sopenharmony_ci			.cipher = __VECS(aes_hctr2_tv_template)
522262306a36Sopenharmony_ci		}
522362306a36Sopenharmony_ci	}, {
522462306a36Sopenharmony_ci		.alg = "hmac(md5)",
522562306a36Sopenharmony_ci		.test = alg_test_hash,
522662306a36Sopenharmony_ci		.suite = {
522762306a36Sopenharmony_ci			.hash = __VECS(hmac_md5_tv_template)
522862306a36Sopenharmony_ci		}
522962306a36Sopenharmony_ci	}, {
523062306a36Sopenharmony_ci		.alg = "hmac(rmd160)",
523162306a36Sopenharmony_ci		.test = alg_test_hash,
523262306a36Sopenharmony_ci		.suite = {
523362306a36Sopenharmony_ci			.hash = __VECS(hmac_rmd160_tv_template)
523462306a36Sopenharmony_ci		}
523562306a36Sopenharmony_ci	}, {
523662306a36Sopenharmony_ci		.alg = "hmac(sha1)",
523762306a36Sopenharmony_ci		.test = alg_test_hash,
523862306a36Sopenharmony_ci		.fips_allowed = 1,
523962306a36Sopenharmony_ci		.suite = {
524062306a36Sopenharmony_ci			.hash = __VECS(hmac_sha1_tv_template)
524162306a36Sopenharmony_ci		}
524262306a36Sopenharmony_ci	}, {
524362306a36Sopenharmony_ci		.alg = "hmac(sha224)",
524462306a36Sopenharmony_ci		.test = alg_test_hash,
524562306a36Sopenharmony_ci		.fips_allowed = 1,
524662306a36Sopenharmony_ci		.suite = {
524762306a36Sopenharmony_ci			.hash = __VECS(hmac_sha224_tv_template)
524862306a36Sopenharmony_ci		}
524962306a36Sopenharmony_ci	}, {
525062306a36Sopenharmony_ci		.alg = "hmac(sha256)",
525162306a36Sopenharmony_ci		.test = alg_test_hash,
525262306a36Sopenharmony_ci		.fips_allowed = 1,
525362306a36Sopenharmony_ci		.suite = {
525462306a36Sopenharmony_ci			.hash = __VECS(hmac_sha256_tv_template)
525562306a36Sopenharmony_ci		}
525662306a36Sopenharmony_ci	}, {
525762306a36Sopenharmony_ci		.alg = "hmac(sha3-224)",
525862306a36Sopenharmony_ci		.test = alg_test_hash,
525962306a36Sopenharmony_ci		.fips_allowed = 1,
526062306a36Sopenharmony_ci		.suite = {
526162306a36Sopenharmony_ci			.hash = __VECS(hmac_sha3_224_tv_template)
526262306a36Sopenharmony_ci		}
526362306a36Sopenharmony_ci	}, {
526462306a36Sopenharmony_ci		.alg = "hmac(sha3-256)",
526562306a36Sopenharmony_ci		.test = alg_test_hash,
526662306a36Sopenharmony_ci		.fips_allowed = 1,
526762306a36Sopenharmony_ci		.suite = {
526862306a36Sopenharmony_ci			.hash = __VECS(hmac_sha3_256_tv_template)
526962306a36Sopenharmony_ci		}
527062306a36Sopenharmony_ci	}, {
527162306a36Sopenharmony_ci		.alg = "hmac(sha3-384)",
527262306a36Sopenharmony_ci		.test = alg_test_hash,
527362306a36Sopenharmony_ci		.fips_allowed = 1,
527462306a36Sopenharmony_ci		.suite = {
527562306a36Sopenharmony_ci			.hash = __VECS(hmac_sha3_384_tv_template)
527662306a36Sopenharmony_ci		}
527762306a36Sopenharmony_ci	}, {
527862306a36Sopenharmony_ci		.alg = "hmac(sha3-512)",
527962306a36Sopenharmony_ci		.test = alg_test_hash,
528062306a36Sopenharmony_ci		.fips_allowed = 1,
528162306a36Sopenharmony_ci		.suite = {
528262306a36Sopenharmony_ci			.hash = __VECS(hmac_sha3_512_tv_template)
528362306a36Sopenharmony_ci		}
528462306a36Sopenharmony_ci	}, {
528562306a36Sopenharmony_ci		.alg = "hmac(sha384)",
528662306a36Sopenharmony_ci		.test = alg_test_hash,
528762306a36Sopenharmony_ci		.fips_allowed = 1,
528862306a36Sopenharmony_ci		.suite = {
528962306a36Sopenharmony_ci			.hash = __VECS(hmac_sha384_tv_template)
529062306a36Sopenharmony_ci		}
529162306a36Sopenharmony_ci	}, {
529262306a36Sopenharmony_ci		.alg = "hmac(sha512)",
529362306a36Sopenharmony_ci		.test = alg_test_hash,
529462306a36Sopenharmony_ci		.fips_allowed = 1,
529562306a36Sopenharmony_ci		.suite = {
529662306a36Sopenharmony_ci			.hash = __VECS(hmac_sha512_tv_template)
529762306a36Sopenharmony_ci		}
529862306a36Sopenharmony_ci	}, {
529962306a36Sopenharmony_ci		.alg = "hmac(sm3)",
530062306a36Sopenharmony_ci		.test = alg_test_hash,
530162306a36Sopenharmony_ci		.suite = {
530262306a36Sopenharmony_ci			.hash = __VECS(hmac_sm3_tv_template)
530362306a36Sopenharmony_ci		}
530462306a36Sopenharmony_ci	}, {
530562306a36Sopenharmony_ci		.alg = "hmac(streebog256)",
530662306a36Sopenharmony_ci		.test = alg_test_hash,
530762306a36Sopenharmony_ci		.suite = {
530862306a36Sopenharmony_ci			.hash = __VECS(hmac_streebog256_tv_template)
530962306a36Sopenharmony_ci		}
531062306a36Sopenharmony_ci	}, {
531162306a36Sopenharmony_ci		.alg = "hmac(streebog512)",
531262306a36Sopenharmony_ci		.test = alg_test_hash,
531362306a36Sopenharmony_ci		.suite = {
531462306a36Sopenharmony_ci			.hash = __VECS(hmac_streebog512_tv_template)
531562306a36Sopenharmony_ci		}
531662306a36Sopenharmony_ci	}, {
531762306a36Sopenharmony_ci		.alg = "jitterentropy_rng",
531862306a36Sopenharmony_ci		.fips_allowed = 1,
531962306a36Sopenharmony_ci		.test = alg_test_null,
532062306a36Sopenharmony_ci	}, {
532162306a36Sopenharmony_ci		.alg = "kw(aes)",
532262306a36Sopenharmony_ci		.test = alg_test_skcipher,
532362306a36Sopenharmony_ci		.fips_allowed = 1,
532462306a36Sopenharmony_ci		.suite = {
532562306a36Sopenharmony_ci			.cipher = __VECS(aes_kw_tv_template)
532662306a36Sopenharmony_ci		}
532762306a36Sopenharmony_ci	}, {
532862306a36Sopenharmony_ci		.alg = "lrw(aes)",
532962306a36Sopenharmony_ci		.generic_driver = "lrw(ecb(aes-generic))",
533062306a36Sopenharmony_ci		.test = alg_test_skcipher,
533162306a36Sopenharmony_ci		.suite = {
533262306a36Sopenharmony_ci			.cipher = __VECS(aes_lrw_tv_template)
533362306a36Sopenharmony_ci		}
533462306a36Sopenharmony_ci	}, {
533562306a36Sopenharmony_ci		.alg = "lrw(camellia)",
533662306a36Sopenharmony_ci		.generic_driver = "lrw(ecb(camellia-generic))",
533762306a36Sopenharmony_ci		.test = alg_test_skcipher,
533862306a36Sopenharmony_ci		.suite = {
533962306a36Sopenharmony_ci			.cipher = __VECS(camellia_lrw_tv_template)
534062306a36Sopenharmony_ci		}
534162306a36Sopenharmony_ci	}, {
534262306a36Sopenharmony_ci		.alg = "lrw(cast6)",
534362306a36Sopenharmony_ci		.generic_driver = "lrw(ecb(cast6-generic))",
534462306a36Sopenharmony_ci		.test = alg_test_skcipher,
534562306a36Sopenharmony_ci		.suite = {
534662306a36Sopenharmony_ci			.cipher = __VECS(cast6_lrw_tv_template)
534762306a36Sopenharmony_ci		}
534862306a36Sopenharmony_ci	}, {
534962306a36Sopenharmony_ci		.alg = "lrw(serpent)",
535062306a36Sopenharmony_ci		.generic_driver = "lrw(ecb(serpent-generic))",
535162306a36Sopenharmony_ci		.test = alg_test_skcipher,
535262306a36Sopenharmony_ci		.suite = {
535362306a36Sopenharmony_ci			.cipher = __VECS(serpent_lrw_tv_template)
535462306a36Sopenharmony_ci		}
535562306a36Sopenharmony_ci	}, {
535662306a36Sopenharmony_ci		.alg = "lrw(twofish)",
535762306a36Sopenharmony_ci		.generic_driver = "lrw(ecb(twofish-generic))",
535862306a36Sopenharmony_ci		.test = alg_test_skcipher,
535962306a36Sopenharmony_ci		.suite = {
536062306a36Sopenharmony_ci			.cipher = __VECS(tf_lrw_tv_template)
536162306a36Sopenharmony_ci		}
536262306a36Sopenharmony_ci	}, {
536362306a36Sopenharmony_ci		.alg = "lz4",
536462306a36Sopenharmony_ci		.test = alg_test_comp,
536562306a36Sopenharmony_ci		.fips_allowed = 1,
536662306a36Sopenharmony_ci		.suite = {
536762306a36Sopenharmony_ci			.comp = {
536862306a36Sopenharmony_ci				.comp = __VECS(lz4_comp_tv_template),
536962306a36Sopenharmony_ci				.decomp = __VECS(lz4_decomp_tv_template)
537062306a36Sopenharmony_ci			}
537162306a36Sopenharmony_ci		}
537262306a36Sopenharmony_ci	}, {
537362306a36Sopenharmony_ci		.alg = "lz4hc",
537462306a36Sopenharmony_ci		.test = alg_test_comp,
537562306a36Sopenharmony_ci		.fips_allowed = 1,
537662306a36Sopenharmony_ci		.suite = {
537762306a36Sopenharmony_ci			.comp = {
537862306a36Sopenharmony_ci				.comp = __VECS(lz4hc_comp_tv_template),
537962306a36Sopenharmony_ci				.decomp = __VECS(lz4hc_decomp_tv_template)
538062306a36Sopenharmony_ci			}
538162306a36Sopenharmony_ci		}
538262306a36Sopenharmony_ci	}, {
538362306a36Sopenharmony_ci		.alg = "lzo",
538462306a36Sopenharmony_ci		.test = alg_test_comp,
538562306a36Sopenharmony_ci		.fips_allowed = 1,
538662306a36Sopenharmony_ci		.suite = {
538762306a36Sopenharmony_ci			.comp = {
538862306a36Sopenharmony_ci				.comp = __VECS(lzo_comp_tv_template),
538962306a36Sopenharmony_ci				.decomp = __VECS(lzo_decomp_tv_template)
539062306a36Sopenharmony_ci			}
539162306a36Sopenharmony_ci		}
539262306a36Sopenharmony_ci	}, {
539362306a36Sopenharmony_ci		.alg = "lzo-rle",
539462306a36Sopenharmony_ci		.test = alg_test_comp,
539562306a36Sopenharmony_ci		.fips_allowed = 1,
539662306a36Sopenharmony_ci		.suite = {
539762306a36Sopenharmony_ci			.comp = {
539862306a36Sopenharmony_ci				.comp = __VECS(lzorle_comp_tv_template),
539962306a36Sopenharmony_ci				.decomp = __VECS(lzorle_decomp_tv_template)
540062306a36Sopenharmony_ci			}
540162306a36Sopenharmony_ci		}
540262306a36Sopenharmony_ci	}, {
540362306a36Sopenharmony_ci		.alg = "md4",
540462306a36Sopenharmony_ci		.test = alg_test_hash,
540562306a36Sopenharmony_ci		.suite = {
540662306a36Sopenharmony_ci			.hash = __VECS(md4_tv_template)
540762306a36Sopenharmony_ci		}
540862306a36Sopenharmony_ci	}, {
540962306a36Sopenharmony_ci		.alg = "md5",
541062306a36Sopenharmony_ci		.test = alg_test_hash,
541162306a36Sopenharmony_ci		.suite = {
541262306a36Sopenharmony_ci			.hash = __VECS(md5_tv_template)
541362306a36Sopenharmony_ci		}
541462306a36Sopenharmony_ci	}, {
541562306a36Sopenharmony_ci		.alg = "michael_mic",
541662306a36Sopenharmony_ci		.test = alg_test_hash,
541762306a36Sopenharmony_ci		.suite = {
541862306a36Sopenharmony_ci			.hash = __VECS(michael_mic_tv_template)
541962306a36Sopenharmony_ci		}
542062306a36Sopenharmony_ci	}, {
542162306a36Sopenharmony_ci		.alg = "nhpoly1305",
542262306a36Sopenharmony_ci		.test = alg_test_hash,
542362306a36Sopenharmony_ci		.suite = {
542462306a36Sopenharmony_ci			.hash = __VECS(nhpoly1305_tv_template)
542562306a36Sopenharmony_ci		}
542662306a36Sopenharmony_ci	}, {
542762306a36Sopenharmony_ci		.alg = "ofb(aes)",
542862306a36Sopenharmony_ci		.test = alg_test_skcipher,
542962306a36Sopenharmony_ci		.fips_allowed = 1,
543062306a36Sopenharmony_ci		.suite = {
543162306a36Sopenharmony_ci			.cipher = __VECS(aes_ofb_tv_template)
543262306a36Sopenharmony_ci		}
543362306a36Sopenharmony_ci	}, {
543462306a36Sopenharmony_ci		/* Same as ofb(aes) except the key is stored in
543562306a36Sopenharmony_ci		 * hardware secure memory which we reference by index
543662306a36Sopenharmony_ci		 */
543762306a36Sopenharmony_ci		.alg = "ofb(paes)",
543862306a36Sopenharmony_ci		.test = alg_test_null,
543962306a36Sopenharmony_ci		.fips_allowed = 1,
544062306a36Sopenharmony_ci	}, {
544162306a36Sopenharmony_ci		.alg = "ofb(sm4)",
544262306a36Sopenharmony_ci		.test = alg_test_skcipher,
544362306a36Sopenharmony_ci		.suite = {
544462306a36Sopenharmony_ci			.cipher = __VECS(sm4_ofb_tv_template)
544562306a36Sopenharmony_ci		}
544662306a36Sopenharmony_ci	}, {
544762306a36Sopenharmony_ci		.alg = "pcbc(fcrypt)",
544862306a36Sopenharmony_ci		.test = alg_test_skcipher,
544962306a36Sopenharmony_ci		.suite = {
545062306a36Sopenharmony_ci			.cipher = __VECS(fcrypt_pcbc_tv_template)
545162306a36Sopenharmony_ci		}
545262306a36Sopenharmony_ci	}, {
545362306a36Sopenharmony_ci		.alg = "pkcs1pad(rsa,sha224)",
545462306a36Sopenharmony_ci		.test = alg_test_null,
545562306a36Sopenharmony_ci		.fips_allowed = 1,
545662306a36Sopenharmony_ci	}, {
545762306a36Sopenharmony_ci		.alg = "pkcs1pad(rsa,sha256)",
545862306a36Sopenharmony_ci		.test = alg_test_akcipher,
545962306a36Sopenharmony_ci		.fips_allowed = 1,
546062306a36Sopenharmony_ci		.suite = {
546162306a36Sopenharmony_ci			.akcipher = __VECS(pkcs1pad_rsa_tv_template)
546262306a36Sopenharmony_ci		}
546362306a36Sopenharmony_ci	}, {
546462306a36Sopenharmony_ci		.alg = "pkcs1pad(rsa,sha384)",
546562306a36Sopenharmony_ci		.test = alg_test_null,
546662306a36Sopenharmony_ci		.fips_allowed = 1,
546762306a36Sopenharmony_ci	}, {
546862306a36Sopenharmony_ci		.alg = "pkcs1pad(rsa,sha512)",
546962306a36Sopenharmony_ci		.test = alg_test_null,
547062306a36Sopenharmony_ci		.fips_allowed = 1,
547162306a36Sopenharmony_ci	}, {
547262306a36Sopenharmony_ci		.alg = "poly1305",
547362306a36Sopenharmony_ci		.test = alg_test_hash,
547462306a36Sopenharmony_ci		.suite = {
547562306a36Sopenharmony_ci			.hash = __VECS(poly1305_tv_template)
547662306a36Sopenharmony_ci		}
547762306a36Sopenharmony_ci	}, {
547862306a36Sopenharmony_ci		.alg = "polyval",
547962306a36Sopenharmony_ci		.test = alg_test_hash,
548062306a36Sopenharmony_ci		.suite = {
548162306a36Sopenharmony_ci			.hash = __VECS(polyval_tv_template)
548262306a36Sopenharmony_ci		}
548362306a36Sopenharmony_ci	}, {
548462306a36Sopenharmony_ci		.alg = "rfc3686(ctr(aes))",
548562306a36Sopenharmony_ci		.test = alg_test_skcipher,
548662306a36Sopenharmony_ci		.fips_allowed = 1,
548762306a36Sopenharmony_ci		.suite = {
548862306a36Sopenharmony_ci			.cipher = __VECS(aes_ctr_rfc3686_tv_template)
548962306a36Sopenharmony_ci		}
549062306a36Sopenharmony_ci	}, {
549162306a36Sopenharmony_ci		.alg = "rfc3686(ctr(sm4))",
549262306a36Sopenharmony_ci		.test = alg_test_skcipher,
549362306a36Sopenharmony_ci		.suite = {
549462306a36Sopenharmony_ci			.cipher = __VECS(sm4_ctr_rfc3686_tv_template)
549562306a36Sopenharmony_ci		}
549662306a36Sopenharmony_ci	}, {
549762306a36Sopenharmony_ci		.alg = "rfc4106(gcm(aes))",
549862306a36Sopenharmony_ci		.generic_driver = "rfc4106(gcm_base(ctr(aes-generic),ghash-generic))",
549962306a36Sopenharmony_ci		.test = alg_test_aead,
550062306a36Sopenharmony_ci		.fips_allowed = 1,
550162306a36Sopenharmony_ci		.suite = {
550262306a36Sopenharmony_ci			.aead = {
550362306a36Sopenharmony_ci				____VECS(aes_gcm_rfc4106_tv_template),
550462306a36Sopenharmony_ci				.einval_allowed = 1,
550562306a36Sopenharmony_ci				.aad_iv = 1,
550662306a36Sopenharmony_ci			}
550762306a36Sopenharmony_ci		}
550862306a36Sopenharmony_ci	}, {
550962306a36Sopenharmony_ci		.alg = "rfc4309(ccm(aes))",
551062306a36Sopenharmony_ci		.generic_driver = "rfc4309(ccm_base(ctr(aes-generic),cbcmac(aes-generic)))",
551162306a36Sopenharmony_ci		.test = alg_test_aead,
551262306a36Sopenharmony_ci		.fips_allowed = 1,
551362306a36Sopenharmony_ci		.suite = {
551462306a36Sopenharmony_ci			.aead = {
551562306a36Sopenharmony_ci				____VECS(aes_ccm_rfc4309_tv_template),
551662306a36Sopenharmony_ci				.einval_allowed = 1,
551762306a36Sopenharmony_ci				.aad_iv = 1,
551862306a36Sopenharmony_ci			}
551962306a36Sopenharmony_ci		}
552062306a36Sopenharmony_ci	}, {
552162306a36Sopenharmony_ci		.alg = "rfc4543(gcm(aes))",
552262306a36Sopenharmony_ci		.generic_driver = "rfc4543(gcm_base(ctr(aes-generic),ghash-generic))",
552362306a36Sopenharmony_ci		.test = alg_test_aead,
552462306a36Sopenharmony_ci		.suite = {
552562306a36Sopenharmony_ci			.aead = {
552662306a36Sopenharmony_ci				____VECS(aes_gcm_rfc4543_tv_template),
552762306a36Sopenharmony_ci				.einval_allowed = 1,
552862306a36Sopenharmony_ci				.aad_iv = 1,
552962306a36Sopenharmony_ci			}
553062306a36Sopenharmony_ci		}
553162306a36Sopenharmony_ci	}, {
553262306a36Sopenharmony_ci		.alg = "rfc7539(chacha20,poly1305)",
553362306a36Sopenharmony_ci		.test = alg_test_aead,
553462306a36Sopenharmony_ci		.suite = {
553562306a36Sopenharmony_ci			.aead = __VECS(rfc7539_tv_template)
553662306a36Sopenharmony_ci		}
553762306a36Sopenharmony_ci	}, {
553862306a36Sopenharmony_ci		.alg = "rfc7539esp(chacha20,poly1305)",
553962306a36Sopenharmony_ci		.test = alg_test_aead,
554062306a36Sopenharmony_ci		.suite = {
554162306a36Sopenharmony_ci			.aead = {
554262306a36Sopenharmony_ci				____VECS(rfc7539esp_tv_template),
554362306a36Sopenharmony_ci				.einval_allowed = 1,
554462306a36Sopenharmony_ci				.aad_iv = 1,
554562306a36Sopenharmony_ci			}
554662306a36Sopenharmony_ci		}
554762306a36Sopenharmony_ci	}, {
554862306a36Sopenharmony_ci		.alg = "rmd160",
554962306a36Sopenharmony_ci		.test = alg_test_hash,
555062306a36Sopenharmony_ci		.suite = {
555162306a36Sopenharmony_ci			.hash = __VECS(rmd160_tv_template)
555262306a36Sopenharmony_ci		}
555362306a36Sopenharmony_ci	}, {
555462306a36Sopenharmony_ci		.alg = "rsa",
555562306a36Sopenharmony_ci		.test = alg_test_akcipher,
555662306a36Sopenharmony_ci		.fips_allowed = 1,
555762306a36Sopenharmony_ci		.suite = {
555862306a36Sopenharmony_ci			.akcipher = __VECS(rsa_tv_template)
555962306a36Sopenharmony_ci		}
556062306a36Sopenharmony_ci	}, {
556162306a36Sopenharmony_ci		.alg = "sha1",
556262306a36Sopenharmony_ci		.test = alg_test_hash,
556362306a36Sopenharmony_ci		.fips_allowed = 1,
556462306a36Sopenharmony_ci		.suite = {
556562306a36Sopenharmony_ci			.hash = __VECS(sha1_tv_template)
556662306a36Sopenharmony_ci		}
556762306a36Sopenharmony_ci	}, {
556862306a36Sopenharmony_ci		.alg = "sha224",
556962306a36Sopenharmony_ci		.test = alg_test_hash,
557062306a36Sopenharmony_ci		.fips_allowed = 1,
557162306a36Sopenharmony_ci		.suite = {
557262306a36Sopenharmony_ci			.hash = __VECS(sha224_tv_template)
557362306a36Sopenharmony_ci		}
557462306a36Sopenharmony_ci	}, {
557562306a36Sopenharmony_ci		.alg = "sha256",
557662306a36Sopenharmony_ci		.test = alg_test_hash,
557762306a36Sopenharmony_ci		.fips_allowed = 1,
557862306a36Sopenharmony_ci		.suite = {
557962306a36Sopenharmony_ci			.hash = __VECS(sha256_tv_template)
558062306a36Sopenharmony_ci		}
558162306a36Sopenharmony_ci	}, {
558262306a36Sopenharmony_ci		.alg = "sha3-224",
558362306a36Sopenharmony_ci		.test = alg_test_hash,
558462306a36Sopenharmony_ci		.fips_allowed = 1,
558562306a36Sopenharmony_ci		.suite = {
558662306a36Sopenharmony_ci			.hash = __VECS(sha3_224_tv_template)
558762306a36Sopenharmony_ci		}
558862306a36Sopenharmony_ci	}, {
558962306a36Sopenharmony_ci		.alg = "sha3-256",
559062306a36Sopenharmony_ci		.test = alg_test_hash,
559162306a36Sopenharmony_ci		.fips_allowed = 1,
559262306a36Sopenharmony_ci		.suite = {
559362306a36Sopenharmony_ci			.hash = __VECS(sha3_256_tv_template)
559462306a36Sopenharmony_ci		}
559562306a36Sopenharmony_ci	}, {
559662306a36Sopenharmony_ci		.alg = "sha3-384",
559762306a36Sopenharmony_ci		.test = alg_test_hash,
559862306a36Sopenharmony_ci		.fips_allowed = 1,
559962306a36Sopenharmony_ci		.suite = {
560062306a36Sopenharmony_ci			.hash = __VECS(sha3_384_tv_template)
560162306a36Sopenharmony_ci		}
560262306a36Sopenharmony_ci	}, {
560362306a36Sopenharmony_ci		.alg = "sha3-512",
560462306a36Sopenharmony_ci		.test = alg_test_hash,
560562306a36Sopenharmony_ci		.fips_allowed = 1,
560662306a36Sopenharmony_ci		.suite = {
560762306a36Sopenharmony_ci			.hash = __VECS(sha3_512_tv_template)
560862306a36Sopenharmony_ci		}
560962306a36Sopenharmony_ci	}, {
561062306a36Sopenharmony_ci		.alg = "sha384",
561162306a36Sopenharmony_ci		.test = alg_test_hash,
561262306a36Sopenharmony_ci		.fips_allowed = 1,
561362306a36Sopenharmony_ci		.suite = {
561462306a36Sopenharmony_ci			.hash = __VECS(sha384_tv_template)
561562306a36Sopenharmony_ci		}
561662306a36Sopenharmony_ci	}, {
561762306a36Sopenharmony_ci		.alg = "sha512",
561862306a36Sopenharmony_ci		.test = alg_test_hash,
561962306a36Sopenharmony_ci		.fips_allowed = 1,
562062306a36Sopenharmony_ci		.suite = {
562162306a36Sopenharmony_ci			.hash = __VECS(sha512_tv_template)
562262306a36Sopenharmony_ci		}
562362306a36Sopenharmony_ci	}, {
562462306a36Sopenharmony_ci		.alg = "sm2",
562562306a36Sopenharmony_ci		.test = alg_test_akcipher,
562662306a36Sopenharmony_ci		.suite = {
562762306a36Sopenharmony_ci			.akcipher = __VECS(sm2_tv_template)
562862306a36Sopenharmony_ci		}
562962306a36Sopenharmony_ci	}, {
563062306a36Sopenharmony_ci		.alg = "sm3",
563162306a36Sopenharmony_ci		.test = alg_test_hash,
563262306a36Sopenharmony_ci		.suite = {
563362306a36Sopenharmony_ci			.hash = __VECS(sm3_tv_template)
563462306a36Sopenharmony_ci		}
563562306a36Sopenharmony_ci	}, {
563662306a36Sopenharmony_ci		.alg = "streebog256",
563762306a36Sopenharmony_ci		.test = alg_test_hash,
563862306a36Sopenharmony_ci		.suite = {
563962306a36Sopenharmony_ci			.hash = __VECS(streebog256_tv_template)
564062306a36Sopenharmony_ci		}
564162306a36Sopenharmony_ci	}, {
564262306a36Sopenharmony_ci		.alg = "streebog512",
564362306a36Sopenharmony_ci		.test = alg_test_hash,
564462306a36Sopenharmony_ci		.suite = {
564562306a36Sopenharmony_ci			.hash = __VECS(streebog512_tv_template)
564662306a36Sopenharmony_ci		}
564762306a36Sopenharmony_ci	}, {
564862306a36Sopenharmony_ci		.alg = "vmac64(aes)",
564962306a36Sopenharmony_ci		.test = alg_test_hash,
565062306a36Sopenharmony_ci		.suite = {
565162306a36Sopenharmony_ci			.hash = __VECS(vmac64_aes_tv_template)
565262306a36Sopenharmony_ci		}
565362306a36Sopenharmony_ci	}, {
565462306a36Sopenharmony_ci		.alg = "wp256",
565562306a36Sopenharmony_ci		.test = alg_test_hash,
565662306a36Sopenharmony_ci		.suite = {
565762306a36Sopenharmony_ci			.hash = __VECS(wp256_tv_template)
565862306a36Sopenharmony_ci		}
565962306a36Sopenharmony_ci	}, {
566062306a36Sopenharmony_ci		.alg = "wp384",
566162306a36Sopenharmony_ci		.test = alg_test_hash,
566262306a36Sopenharmony_ci		.suite = {
566362306a36Sopenharmony_ci			.hash = __VECS(wp384_tv_template)
566462306a36Sopenharmony_ci		}
566562306a36Sopenharmony_ci	}, {
566662306a36Sopenharmony_ci		.alg = "wp512",
566762306a36Sopenharmony_ci		.test = alg_test_hash,
566862306a36Sopenharmony_ci		.suite = {
566962306a36Sopenharmony_ci			.hash = __VECS(wp512_tv_template)
567062306a36Sopenharmony_ci		}
567162306a36Sopenharmony_ci	}, {
567262306a36Sopenharmony_ci		.alg = "xcbc(aes)",
567362306a36Sopenharmony_ci		.test = alg_test_hash,
567462306a36Sopenharmony_ci		.suite = {
567562306a36Sopenharmony_ci			.hash = __VECS(aes_xcbc128_tv_template)
567662306a36Sopenharmony_ci		}
567762306a36Sopenharmony_ci	}, {
567862306a36Sopenharmony_ci		.alg = "xcbc(sm4)",
567962306a36Sopenharmony_ci		.test = alg_test_hash,
568062306a36Sopenharmony_ci		.suite = {
568162306a36Sopenharmony_ci			.hash = __VECS(sm4_xcbc128_tv_template)
568262306a36Sopenharmony_ci		}
568362306a36Sopenharmony_ci	}, {
568462306a36Sopenharmony_ci		.alg = "xchacha12",
568562306a36Sopenharmony_ci		.test = alg_test_skcipher,
568662306a36Sopenharmony_ci		.suite = {
568762306a36Sopenharmony_ci			.cipher = __VECS(xchacha12_tv_template)
568862306a36Sopenharmony_ci		},
568962306a36Sopenharmony_ci	}, {
569062306a36Sopenharmony_ci		.alg = "xchacha20",
569162306a36Sopenharmony_ci		.test = alg_test_skcipher,
569262306a36Sopenharmony_ci		.suite = {
569362306a36Sopenharmony_ci			.cipher = __VECS(xchacha20_tv_template)
569462306a36Sopenharmony_ci		},
569562306a36Sopenharmony_ci	}, {
569662306a36Sopenharmony_ci		.alg = "xctr(aes)",
569762306a36Sopenharmony_ci		.test = alg_test_skcipher,
569862306a36Sopenharmony_ci		.suite = {
569962306a36Sopenharmony_ci			.cipher = __VECS(aes_xctr_tv_template)
570062306a36Sopenharmony_ci		}
570162306a36Sopenharmony_ci	}, {
570262306a36Sopenharmony_ci		.alg = "xts(aes)",
570362306a36Sopenharmony_ci		.generic_driver = "xts(ecb(aes-generic))",
570462306a36Sopenharmony_ci		.test = alg_test_skcipher,
570562306a36Sopenharmony_ci		.fips_allowed = 1,
570662306a36Sopenharmony_ci		.suite = {
570762306a36Sopenharmony_ci			.cipher = __VECS(aes_xts_tv_template)
570862306a36Sopenharmony_ci		}
570962306a36Sopenharmony_ci	}, {
571062306a36Sopenharmony_ci		.alg = "xts(camellia)",
571162306a36Sopenharmony_ci		.generic_driver = "xts(ecb(camellia-generic))",
571262306a36Sopenharmony_ci		.test = alg_test_skcipher,
571362306a36Sopenharmony_ci		.suite = {
571462306a36Sopenharmony_ci			.cipher = __VECS(camellia_xts_tv_template)
571562306a36Sopenharmony_ci		}
571662306a36Sopenharmony_ci	}, {
571762306a36Sopenharmony_ci		.alg = "xts(cast6)",
571862306a36Sopenharmony_ci		.generic_driver = "xts(ecb(cast6-generic))",
571962306a36Sopenharmony_ci		.test = alg_test_skcipher,
572062306a36Sopenharmony_ci		.suite = {
572162306a36Sopenharmony_ci			.cipher = __VECS(cast6_xts_tv_template)
572262306a36Sopenharmony_ci		}
572362306a36Sopenharmony_ci	}, {
572462306a36Sopenharmony_ci		/* Same as xts(aes) except the key is stored in
572562306a36Sopenharmony_ci		 * hardware secure memory which we reference by index
572662306a36Sopenharmony_ci		 */
572762306a36Sopenharmony_ci		.alg = "xts(paes)",
572862306a36Sopenharmony_ci		.test = alg_test_null,
572962306a36Sopenharmony_ci		.fips_allowed = 1,
573062306a36Sopenharmony_ci	}, {
573162306a36Sopenharmony_ci		.alg = "xts(serpent)",
573262306a36Sopenharmony_ci		.generic_driver = "xts(ecb(serpent-generic))",
573362306a36Sopenharmony_ci		.test = alg_test_skcipher,
573462306a36Sopenharmony_ci		.suite = {
573562306a36Sopenharmony_ci			.cipher = __VECS(serpent_xts_tv_template)
573662306a36Sopenharmony_ci		}
573762306a36Sopenharmony_ci	}, {
573862306a36Sopenharmony_ci		.alg = "xts(sm4)",
573962306a36Sopenharmony_ci		.generic_driver = "xts(ecb(sm4-generic))",
574062306a36Sopenharmony_ci		.test = alg_test_skcipher,
574162306a36Sopenharmony_ci		.suite = {
574262306a36Sopenharmony_ci			.cipher = __VECS(sm4_xts_tv_template)
574362306a36Sopenharmony_ci		}
574462306a36Sopenharmony_ci	}, {
574562306a36Sopenharmony_ci		.alg = "xts(twofish)",
574662306a36Sopenharmony_ci		.generic_driver = "xts(ecb(twofish-generic))",
574762306a36Sopenharmony_ci		.test = alg_test_skcipher,
574862306a36Sopenharmony_ci		.suite = {
574962306a36Sopenharmony_ci			.cipher = __VECS(tf_xts_tv_template)
575062306a36Sopenharmony_ci		}
575162306a36Sopenharmony_ci	}, {
575262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
575362306a36Sopenharmony_ci		.alg = "xts-paes-s390",
575462306a36Sopenharmony_ci		.fips_allowed = 1,
575562306a36Sopenharmony_ci		.test = alg_test_skcipher,
575662306a36Sopenharmony_ci		.suite = {
575762306a36Sopenharmony_ci			.cipher = __VECS(aes_xts_tv_template)
575862306a36Sopenharmony_ci		}
575962306a36Sopenharmony_ci	}, {
576062306a36Sopenharmony_ci#endif
576162306a36Sopenharmony_ci		.alg = "xts4096(paes)",
576262306a36Sopenharmony_ci		.test = alg_test_null,
576362306a36Sopenharmony_ci		.fips_allowed = 1,
576462306a36Sopenharmony_ci	}, {
576562306a36Sopenharmony_ci		.alg = "xts512(paes)",
576662306a36Sopenharmony_ci		.test = alg_test_null,
576762306a36Sopenharmony_ci		.fips_allowed = 1,
576862306a36Sopenharmony_ci	}, {
576962306a36Sopenharmony_ci		.alg = "xxhash64",
577062306a36Sopenharmony_ci		.test = alg_test_hash,
577162306a36Sopenharmony_ci		.fips_allowed = 1,
577262306a36Sopenharmony_ci		.suite = {
577362306a36Sopenharmony_ci			.hash = __VECS(xxhash64_tv_template)
577462306a36Sopenharmony_ci		}
577562306a36Sopenharmony_ci	}, {
577662306a36Sopenharmony_ci		.alg = "zlib-deflate",
577762306a36Sopenharmony_ci		.test = alg_test_comp,
577862306a36Sopenharmony_ci		.fips_allowed = 1,
577962306a36Sopenharmony_ci		.suite = {
578062306a36Sopenharmony_ci			.comp = {
578162306a36Sopenharmony_ci				.comp = __VECS(zlib_deflate_comp_tv_template),
578262306a36Sopenharmony_ci				.decomp = __VECS(zlib_deflate_decomp_tv_template)
578362306a36Sopenharmony_ci			}
578462306a36Sopenharmony_ci		}
578562306a36Sopenharmony_ci	}, {
578662306a36Sopenharmony_ci		.alg = "zstd",
578762306a36Sopenharmony_ci		.test = alg_test_comp,
578862306a36Sopenharmony_ci		.fips_allowed = 1,
578962306a36Sopenharmony_ci		.suite = {
579062306a36Sopenharmony_ci			.comp = {
579162306a36Sopenharmony_ci				.comp = __VECS(zstd_comp_tv_template),
579262306a36Sopenharmony_ci				.decomp = __VECS(zstd_decomp_tv_template)
579362306a36Sopenharmony_ci			}
579462306a36Sopenharmony_ci		}
579562306a36Sopenharmony_ci	}
579662306a36Sopenharmony_ci};
579762306a36Sopenharmony_ci
579862306a36Sopenharmony_cistatic void alg_check_test_descs_order(void)
579962306a36Sopenharmony_ci{
580062306a36Sopenharmony_ci	int i;
580162306a36Sopenharmony_ci
580262306a36Sopenharmony_ci	for (i = 1; i < ARRAY_SIZE(alg_test_descs); i++) {
580362306a36Sopenharmony_ci		int diff = strcmp(alg_test_descs[i - 1].alg,
580462306a36Sopenharmony_ci				  alg_test_descs[i].alg);
580562306a36Sopenharmony_ci
580662306a36Sopenharmony_ci		if (WARN_ON(diff > 0)) {
580762306a36Sopenharmony_ci			pr_warn("testmgr: alg_test_descs entries in wrong order: '%s' before '%s'\n",
580862306a36Sopenharmony_ci				alg_test_descs[i - 1].alg,
580962306a36Sopenharmony_ci				alg_test_descs[i].alg);
581062306a36Sopenharmony_ci		}
581162306a36Sopenharmony_ci
581262306a36Sopenharmony_ci		if (WARN_ON(diff == 0)) {
581362306a36Sopenharmony_ci			pr_warn("testmgr: duplicate alg_test_descs entry: '%s'\n",
581462306a36Sopenharmony_ci				alg_test_descs[i].alg);
581562306a36Sopenharmony_ci		}
581662306a36Sopenharmony_ci	}
581762306a36Sopenharmony_ci}
581862306a36Sopenharmony_ci
581962306a36Sopenharmony_cistatic void alg_check_testvec_configs(void)
582062306a36Sopenharmony_ci{
582162306a36Sopenharmony_ci	int i;
582262306a36Sopenharmony_ci
582362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++)
582462306a36Sopenharmony_ci		WARN_ON(!valid_testvec_config(
582562306a36Sopenharmony_ci				&default_cipher_testvec_configs[i]));
582662306a36Sopenharmony_ci
582762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++)
582862306a36Sopenharmony_ci		WARN_ON(!valid_testvec_config(
582962306a36Sopenharmony_ci				&default_hash_testvec_configs[i]));
583062306a36Sopenharmony_ci}
583162306a36Sopenharmony_ci
583262306a36Sopenharmony_cistatic void testmgr_onetime_init(void)
583362306a36Sopenharmony_ci{
583462306a36Sopenharmony_ci	alg_check_test_descs_order();
583562306a36Sopenharmony_ci	alg_check_testvec_configs();
583662306a36Sopenharmony_ci
583762306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
583862306a36Sopenharmony_ci	pr_warn("alg: extra crypto tests enabled.  This is intended for developer use only.\n");
583962306a36Sopenharmony_ci#endif
584062306a36Sopenharmony_ci}
584162306a36Sopenharmony_ci
584262306a36Sopenharmony_cistatic int alg_find_test(const char *alg)
584362306a36Sopenharmony_ci{
584462306a36Sopenharmony_ci	int start = 0;
584562306a36Sopenharmony_ci	int end = ARRAY_SIZE(alg_test_descs);
584662306a36Sopenharmony_ci
584762306a36Sopenharmony_ci	while (start < end) {
584862306a36Sopenharmony_ci		int i = (start + end) / 2;
584962306a36Sopenharmony_ci		int diff = strcmp(alg_test_descs[i].alg, alg);
585062306a36Sopenharmony_ci
585162306a36Sopenharmony_ci		if (diff > 0) {
585262306a36Sopenharmony_ci			end = i;
585362306a36Sopenharmony_ci			continue;
585462306a36Sopenharmony_ci		}
585562306a36Sopenharmony_ci
585662306a36Sopenharmony_ci		if (diff < 0) {
585762306a36Sopenharmony_ci			start = i + 1;
585862306a36Sopenharmony_ci			continue;
585962306a36Sopenharmony_ci		}
586062306a36Sopenharmony_ci
586162306a36Sopenharmony_ci		return i;
586262306a36Sopenharmony_ci	}
586362306a36Sopenharmony_ci
586462306a36Sopenharmony_ci	return -1;
586562306a36Sopenharmony_ci}
586662306a36Sopenharmony_ci
586762306a36Sopenharmony_cistatic int alg_fips_disabled(const char *driver, const char *alg)
586862306a36Sopenharmony_ci{
586962306a36Sopenharmony_ci	pr_info("alg: %s (%s) is disabled due to FIPS\n", alg, driver);
587062306a36Sopenharmony_ci
587162306a36Sopenharmony_ci	return -ECANCELED;
587262306a36Sopenharmony_ci}
587362306a36Sopenharmony_ci
587462306a36Sopenharmony_ciint alg_test(const char *driver, const char *alg, u32 type, u32 mask)
587562306a36Sopenharmony_ci{
587662306a36Sopenharmony_ci	int i;
587762306a36Sopenharmony_ci	int j;
587862306a36Sopenharmony_ci	int rc;
587962306a36Sopenharmony_ci
588062306a36Sopenharmony_ci	if (!fips_enabled && notests) {
588162306a36Sopenharmony_ci		printk_once(KERN_INFO "alg: self-tests disabled\n");
588262306a36Sopenharmony_ci		return 0;
588362306a36Sopenharmony_ci	}
588462306a36Sopenharmony_ci
588562306a36Sopenharmony_ci	DO_ONCE(testmgr_onetime_init);
588662306a36Sopenharmony_ci
588762306a36Sopenharmony_ci	if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) {
588862306a36Sopenharmony_ci		char nalg[CRYPTO_MAX_ALG_NAME];
588962306a36Sopenharmony_ci
589062306a36Sopenharmony_ci		if (snprintf(nalg, sizeof(nalg), "ecb(%s)", alg) >=
589162306a36Sopenharmony_ci		    sizeof(nalg))
589262306a36Sopenharmony_ci			return -ENAMETOOLONG;
589362306a36Sopenharmony_ci
589462306a36Sopenharmony_ci		i = alg_find_test(nalg);
589562306a36Sopenharmony_ci		if (i < 0)
589662306a36Sopenharmony_ci			goto notest;
589762306a36Sopenharmony_ci
589862306a36Sopenharmony_ci		if (fips_enabled && !alg_test_descs[i].fips_allowed)
589962306a36Sopenharmony_ci			goto non_fips_alg;
590062306a36Sopenharmony_ci
590162306a36Sopenharmony_ci		rc = alg_test_cipher(alg_test_descs + i, driver, type, mask);
590262306a36Sopenharmony_ci		goto test_done;
590362306a36Sopenharmony_ci	}
590462306a36Sopenharmony_ci
590562306a36Sopenharmony_ci	i = alg_find_test(alg);
590662306a36Sopenharmony_ci	j = alg_find_test(driver);
590762306a36Sopenharmony_ci	if (i < 0 && j < 0)
590862306a36Sopenharmony_ci		goto notest;
590962306a36Sopenharmony_ci
591062306a36Sopenharmony_ci	if (fips_enabled) {
591162306a36Sopenharmony_ci		if (j >= 0 && !alg_test_descs[j].fips_allowed)
591262306a36Sopenharmony_ci			return -EINVAL;
591362306a36Sopenharmony_ci
591462306a36Sopenharmony_ci		if (i >= 0 && !alg_test_descs[i].fips_allowed)
591562306a36Sopenharmony_ci			goto non_fips_alg;
591662306a36Sopenharmony_ci	}
591762306a36Sopenharmony_ci
591862306a36Sopenharmony_ci	rc = 0;
591962306a36Sopenharmony_ci	if (i >= 0)
592062306a36Sopenharmony_ci		rc |= alg_test_descs[i].test(alg_test_descs + i, driver,
592162306a36Sopenharmony_ci					     type, mask);
592262306a36Sopenharmony_ci	if (j >= 0 && j != i)
592362306a36Sopenharmony_ci		rc |= alg_test_descs[j].test(alg_test_descs + j, driver,
592462306a36Sopenharmony_ci					     type, mask);
592562306a36Sopenharmony_ci
592662306a36Sopenharmony_citest_done:
592762306a36Sopenharmony_ci	if (rc) {
592862306a36Sopenharmony_ci		if (fips_enabled || panic_on_fail) {
592962306a36Sopenharmony_ci			fips_fail_notify();
593062306a36Sopenharmony_ci			panic("alg: self-tests for %s (%s) failed in %s mode!\n",
593162306a36Sopenharmony_ci			      driver, alg,
593262306a36Sopenharmony_ci			      fips_enabled ? "fips" : "panic_on_fail");
593362306a36Sopenharmony_ci		}
593462306a36Sopenharmony_ci		pr_warn("alg: self-tests for %s using %s failed (rc=%d)",
593562306a36Sopenharmony_ci			alg, driver, rc);
593662306a36Sopenharmony_ci		WARN(rc != -ENOENT,
593762306a36Sopenharmony_ci		     "alg: self-tests for %s using %s failed (rc=%d)",
593862306a36Sopenharmony_ci		     alg, driver, rc);
593962306a36Sopenharmony_ci	} else {
594062306a36Sopenharmony_ci		if (fips_enabled)
594162306a36Sopenharmony_ci			pr_info("alg: self-tests for %s (%s) passed\n",
594262306a36Sopenharmony_ci				driver, alg);
594362306a36Sopenharmony_ci	}
594462306a36Sopenharmony_ci
594562306a36Sopenharmony_ci	return rc;
594662306a36Sopenharmony_ci
594762306a36Sopenharmony_cinotest:
594862306a36Sopenharmony_ci	printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);
594962306a36Sopenharmony_ci
595062306a36Sopenharmony_ci	if (type & CRYPTO_ALG_FIPS_INTERNAL)
595162306a36Sopenharmony_ci		return alg_fips_disabled(driver, alg);
595262306a36Sopenharmony_ci
595362306a36Sopenharmony_ci	return 0;
595462306a36Sopenharmony_cinon_fips_alg:
595562306a36Sopenharmony_ci	return alg_fips_disabled(driver, alg);
595662306a36Sopenharmony_ci}
595762306a36Sopenharmony_ci
595862306a36Sopenharmony_ci#endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */
595962306a36Sopenharmony_ci
596062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(alg_test);
5961