xref: /openbmc/linux/crypto/testmgr.c (revision ba24b8eb)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2da7f033dSHerbert Xu /*
3da7f033dSHerbert Xu  * Algorithm testing framework and tests.
4da7f033dSHerbert Xu  *
5da7f033dSHerbert Xu  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
6da7f033dSHerbert Xu  * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
7da7f033dSHerbert Xu  * Copyright (c) 2007 Nokia Siemens Networks
8da7f033dSHerbert Xu  * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
93f47a03dSEric Biggers  * Copyright (c) 2019 Google LLC
10da7f033dSHerbert Xu  *
1169435b94SAdrian Hoban  * Updated RFC4106 AES-GCM testing.
1269435b94SAdrian Hoban  *    Authors: Aidan O'Mahony (aidan.o.mahony@intel.com)
1369435b94SAdrian Hoban  *             Adrian Hoban <adrian.hoban@intel.com>
1469435b94SAdrian Hoban  *             Gabriele Paoloni <gabriele.paoloni@intel.com>
1569435b94SAdrian Hoban  *             Tadeusz Struk (tadeusz.struk@intel.com)
1669435b94SAdrian Hoban  *    Copyright (c) 2010, Intel Corporation.
17da7f033dSHerbert Xu  */
18da7f033dSHerbert Xu 
191ce33115SHerbert Xu #include <crypto/aead.h>
20da7f033dSHerbert Xu #include <crypto/hash.h>
2112773d93SHerbert Xu #include <crypto/skcipher.h>
22da7f033dSHerbert Xu #include <linux/err.h>
231c41b882SHerbert Xu #include <linux/fips.h>
24da7f033dSHerbert Xu #include <linux/module.h>
253f47a03dSEric Biggers #include <linux/once.h>
2625f9dddbSEric Biggers #include <linux/random.h>
27da7f033dSHerbert Xu #include <linux/scatterlist.h>
28da7f033dSHerbert Xu #include <linux/slab.h>
29da7f033dSHerbert Xu #include <linux/string.h>
300c3dc787SHerbert Xu #include <linux/uio.h>
317647d6ceSJarod Wilson #include <crypto/rng.h>
3264d1cdfbSStephan Mueller #include <crypto/drbg.h>
33946cc463STadeusz Struk #include <crypto/akcipher.h>
34802c7f1cSSalvatore Benedetto #include <crypto/kpp.h>
35d7db7a88SGiovanni Cabiddu #include <crypto/acompress.h>
360eb76ba2SArd Biesheuvel #include <crypto/internal/cipher.h>
37b55e1a39SEric Biggers #include <crypto/internal/simd.h>
38da7f033dSHerbert Xu 
39da7f033dSHerbert Xu #include "internal.h"
400b767f96SAlexander Shishkin 
410eb76ba2SArd Biesheuvel MODULE_IMPORT_NS(CRYPTO_INTERNAL);
420eb76ba2SArd Biesheuvel 
439e5c9fe4SRichard W.M. Jones static bool notests;
449e5c9fe4SRichard W.M. Jones module_param(notests, bool, 0644);
459e5c9fe4SRichard W.M. Jones MODULE_PARM_DESC(notests, "disable crypto self-tests");
469e5c9fe4SRichard W.M. Jones 
47eda69b0cSEric Biggers static bool panic_on_fail;
48eda69b0cSEric Biggers module_param(panic_on_fail, bool, 0444);
49eda69b0cSEric Biggers 
505b2706a4SEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
515b2706a4SEric Biggers static bool noextratests;
525b2706a4SEric Biggers module_param(noextratests, bool, 0644);
535b2706a4SEric Biggers MODULE_PARM_DESC(noextratests, "disable expensive crypto self-tests");
545b2706a4SEric Biggers 
555b2706a4SEric Biggers static unsigned int fuzz_iterations = 100;
565b2706a4SEric Biggers module_param(fuzz_iterations, uint, 0644);
575b2706a4SEric Biggers MODULE_PARM_DESC(fuzz_iterations, "number of fuzz test iterations");
585b2706a4SEric Biggers #endif
595b2706a4SEric Biggers 
60326a6346SHerbert Xu #ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
610b767f96SAlexander Shishkin 
620b767f96SAlexander Shishkin /* a perfect nop */
alg_test(const char * driver,const char * alg,u32 type,u32 mask)630b767f96SAlexander Shishkin int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
640b767f96SAlexander Shishkin {
650b767f96SAlexander Shishkin 	return 0;
660b767f96SAlexander Shishkin }
670b767f96SAlexander Shishkin 
680b767f96SAlexander Shishkin #else
690b767f96SAlexander Shishkin 
70da7f033dSHerbert Xu #include "testmgr.h"
71da7f033dSHerbert Xu 
72da7f033dSHerbert Xu /*
73da7f033dSHerbert Xu  * Need slab memory for testing (size in number of pages).
74da7f033dSHerbert Xu  */
75da7f033dSHerbert Xu #define XBUFSIZE	8
76da7f033dSHerbert Xu 
77da7f033dSHerbert Xu /*
78da7f033dSHerbert Xu * Used by test_cipher()
79da7f033dSHerbert Xu */
80da7f033dSHerbert Xu #define ENCRYPT 1
81da7f033dSHerbert Xu #define DECRYPT 0
82da7f033dSHerbert Xu 
83da7f033dSHerbert Xu struct aead_test_suite {
84b13b1e0cSEric Biggers 	const struct aead_testvec *vecs;
85da7f033dSHerbert Xu 	unsigned int count;
8649763fc6SEric Biggers 
8749763fc6SEric Biggers 	/*
8849763fc6SEric Biggers 	 * Set if trying to decrypt an inauthentic ciphertext with this
8949763fc6SEric Biggers 	 * algorithm might result in EINVAL rather than EBADMSG, due to other
9049763fc6SEric Biggers 	 * validation the algorithm does on the inputs such as length checks.
9149763fc6SEric Biggers 	 */
9249763fc6SEric Biggers 	unsigned int einval_allowed : 1;
9349763fc6SEric Biggers 
9449763fc6SEric Biggers 	/*
956f3a06d9SEric Biggers 	 * Set if this algorithm requires that the IV be located at the end of
966f3a06d9SEric Biggers 	 * the AAD buffer, in addition to being given in the normal way.  The
976f3a06d9SEric Biggers 	 * behavior when the two IV copies differ is implementation-defined.
9849763fc6SEric Biggers 	 */
996f3a06d9SEric Biggers 	unsigned int aad_iv : 1;
100da7f033dSHerbert Xu };
101da7f033dSHerbert Xu 
102da7f033dSHerbert Xu struct cipher_test_suite {
103b13b1e0cSEric Biggers 	const struct cipher_testvec *vecs;
104da7f033dSHerbert Xu 	unsigned int count;
105da7f033dSHerbert Xu };
106da7f033dSHerbert Xu 
107da7f033dSHerbert Xu struct comp_test_suite {
108da7f033dSHerbert Xu 	struct {
109b13b1e0cSEric Biggers 		const struct comp_testvec *vecs;
110da7f033dSHerbert Xu 		unsigned int count;
111da7f033dSHerbert Xu 	} comp, decomp;
112da7f033dSHerbert Xu };
113da7f033dSHerbert Xu 
114da7f033dSHerbert Xu struct hash_test_suite {
115b13b1e0cSEric Biggers 	const struct hash_testvec *vecs;
116da7f033dSHerbert Xu 	unsigned int count;
117da7f033dSHerbert Xu };
118da7f033dSHerbert Xu 
1197647d6ceSJarod Wilson struct cprng_test_suite {
120b13b1e0cSEric Biggers 	const struct cprng_testvec *vecs;
1217647d6ceSJarod Wilson 	unsigned int count;
1227647d6ceSJarod Wilson };
1237647d6ceSJarod Wilson 
12464d1cdfbSStephan Mueller struct drbg_test_suite {
125b13b1e0cSEric Biggers 	const struct drbg_testvec *vecs;
12664d1cdfbSStephan Mueller 	unsigned int count;
12764d1cdfbSStephan Mueller };
12864d1cdfbSStephan Mueller 
129946cc463STadeusz Struk struct akcipher_test_suite {
130b13b1e0cSEric Biggers 	const struct akcipher_testvec *vecs;
131946cc463STadeusz Struk 	unsigned int count;
132946cc463STadeusz Struk };
133946cc463STadeusz Struk 
134802c7f1cSSalvatore Benedetto struct kpp_test_suite {
135b13b1e0cSEric Biggers 	const struct kpp_testvec *vecs;
136802c7f1cSSalvatore Benedetto 	unsigned int count;
137802c7f1cSSalvatore Benedetto };
138802c7f1cSSalvatore Benedetto 
139da7f033dSHerbert Xu struct alg_test_desc {
140da7f033dSHerbert Xu 	const char *alg;
141f2bb770aSEric Biggers 	const char *generic_driver;
142da7f033dSHerbert Xu 	int (*test)(const struct alg_test_desc *desc, const char *driver,
143da7f033dSHerbert Xu 		    u32 type, u32 mask);
144a1915d51SJarod Wilson 	int fips_allowed;	/* set if alg is allowed in fips mode */
145da7f033dSHerbert Xu 
146da7f033dSHerbert Xu 	union {
147da7f033dSHerbert Xu 		struct aead_test_suite aead;
148da7f033dSHerbert Xu 		struct cipher_test_suite cipher;
149da7f033dSHerbert Xu 		struct comp_test_suite comp;
150da7f033dSHerbert Xu 		struct hash_test_suite hash;
1517647d6ceSJarod Wilson 		struct cprng_test_suite cprng;
15264d1cdfbSStephan Mueller 		struct drbg_test_suite drbg;
153946cc463STadeusz Struk 		struct akcipher_test_suite akcipher;
154802c7f1cSSalvatore Benedetto 		struct kpp_test_suite kpp;
155da7f033dSHerbert Xu 	} suite;
156da7f033dSHerbert Xu };
157da7f033dSHerbert Xu 
hexdump(unsigned char * buf,unsigned int len)158da7f033dSHerbert Xu static void hexdump(unsigned char *buf, unsigned int len)
159da7f033dSHerbert Xu {
160da7f033dSHerbert Xu 	print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
161da7f033dSHerbert Xu 			16, 1,
162da7f033dSHerbert Xu 			buf, len, false);
163da7f033dSHerbert Xu }
164da7f033dSHerbert Xu 
__testmgr_alloc_buf(char * buf[XBUFSIZE],int order)1653f47a03dSEric Biggers static int __testmgr_alloc_buf(char *buf[XBUFSIZE], int order)
166f8b0d4d0SHerbert Xu {
167f8b0d4d0SHerbert Xu 	int i;
168f8b0d4d0SHerbert Xu 
169f8b0d4d0SHerbert Xu 	for (i = 0; i < XBUFSIZE; i++) {
1703f47a03dSEric Biggers 		buf[i] = (char *)__get_free_pages(GFP_KERNEL, order);
171f8b0d4d0SHerbert Xu 		if (!buf[i])
172f8b0d4d0SHerbert Xu 			goto err_free_buf;
173f8b0d4d0SHerbert Xu 	}
174f8b0d4d0SHerbert Xu 
175f8b0d4d0SHerbert Xu 	return 0;
176f8b0d4d0SHerbert Xu 
177f8b0d4d0SHerbert Xu err_free_buf:
178f8b0d4d0SHerbert Xu 	while (i-- > 0)
1793f47a03dSEric Biggers 		free_pages((unsigned long)buf[i], order);
180f8b0d4d0SHerbert Xu 
181f8b0d4d0SHerbert Xu 	return -ENOMEM;
182f8b0d4d0SHerbert Xu }
183f8b0d4d0SHerbert Xu 
testmgr_alloc_buf(char * buf[XBUFSIZE])1843f47a03dSEric Biggers static int testmgr_alloc_buf(char *buf[XBUFSIZE])
1853f47a03dSEric Biggers {
1863f47a03dSEric Biggers 	return __testmgr_alloc_buf(buf, 0);
1873f47a03dSEric Biggers }
1883f47a03dSEric Biggers 
__testmgr_free_buf(char * buf[XBUFSIZE],int order)1893f47a03dSEric Biggers static void __testmgr_free_buf(char *buf[XBUFSIZE], int order)
190f8b0d4d0SHerbert Xu {
191f8b0d4d0SHerbert Xu 	int i;
192f8b0d4d0SHerbert Xu 
193f8b0d4d0SHerbert Xu 	for (i = 0; i < XBUFSIZE; i++)
1943f47a03dSEric Biggers 		free_pages((unsigned long)buf[i], order);
1953f47a03dSEric Biggers }
1963f47a03dSEric Biggers 
testmgr_free_buf(char * buf[XBUFSIZE])1973f47a03dSEric Biggers static void testmgr_free_buf(char *buf[XBUFSIZE])
1983f47a03dSEric Biggers {
1993f47a03dSEric Biggers 	__testmgr_free_buf(buf, 0);
2003f47a03dSEric Biggers }
2013f47a03dSEric Biggers 
2023f47a03dSEric Biggers #define TESTMGR_POISON_BYTE	0xfe
2033f47a03dSEric Biggers #define TESTMGR_POISON_LEN	16
2043f47a03dSEric Biggers 
testmgr_poison(void * addr,size_t len)2053f47a03dSEric Biggers static inline void testmgr_poison(void *addr, size_t len)
2063f47a03dSEric Biggers {
2073f47a03dSEric Biggers 	memset(addr, TESTMGR_POISON_BYTE, len);
2083f47a03dSEric Biggers }
2093f47a03dSEric Biggers 
2103f47a03dSEric Biggers /* Is the memory region still fully poisoned? */
testmgr_is_poison(const void * addr,size_t len)2113f47a03dSEric Biggers static inline bool testmgr_is_poison(const void *addr, size_t len)
2123f47a03dSEric Biggers {
2133f47a03dSEric Biggers 	return memchr_inv(addr, TESTMGR_POISON_BYTE, len) == NULL;
2143f47a03dSEric Biggers }
2153f47a03dSEric Biggers 
2163f47a03dSEric Biggers /* flush type for hash algorithms */
2173f47a03dSEric Biggers enum flush_type {
2183f47a03dSEric Biggers 	/* merge with update of previous buffer(s) */
2193f47a03dSEric Biggers 	FLUSH_TYPE_NONE = 0,
2203f47a03dSEric Biggers 
2213f47a03dSEric Biggers 	/* update with previous buffer(s) before doing this one */
2223f47a03dSEric Biggers 	FLUSH_TYPE_FLUSH,
2233f47a03dSEric Biggers 
2243f47a03dSEric Biggers 	/* likewise, but also export and re-import the intermediate state */
2253f47a03dSEric Biggers 	FLUSH_TYPE_REIMPORT,
2263f47a03dSEric Biggers };
2273f47a03dSEric Biggers 
2283f47a03dSEric Biggers /* finalization function for hash algorithms */
2293f47a03dSEric Biggers enum finalization_type {
2303f47a03dSEric Biggers 	FINALIZATION_TYPE_FINAL,	/* use final() */
2313f47a03dSEric Biggers 	FINALIZATION_TYPE_FINUP,	/* use finup() */
2323f47a03dSEric Biggers 	FINALIZATION_TYPE_DIGEST,	/* use digest() */
2333f47a03dSEric Biggers };
2343f47a03dSEric Biggers 
235f17f9e90SEric Biggers /*
236f17f9e90SEric Biggers  * Whether the crypto operation will occur in-place, and if so whether the
237f17f9e90SEric Biggers  * source and destination scatterlist pointers will coincide (req->src ==
238f17f9e90SEric Biggers  * req->dst), or whether they'll merely point to two separate scatterlists
239f17f9e90SEric Biggers  * (req->src != req->dst) that reference the same underlying memory.
240f17f9e90SEric Biggers  *
241f17f9e90SEric Biggers  * This is only relevant for algorithm types that support in-place operation.
242f17f9e90SEric Biggers  */
243f17f9e90SEric Biggers enum inplace_mode {
244f17f9e90SEric Biggers 	OUT_OF_PLACE,
245f17f9e90SEric Biggers 	INPLACE_ONE_SGLIST,
246f17f9e90SEric Biggers 	INPLACE_TWO_SGLISTS,
247f17f9e90SEric Biggers };
248f17f9e90SEric Biggers 
2493f47a03dSEric Biggers #define TEST_SG_TOTAL	10000
2503f47a03dSEric Biggers 
2513f47a03dSEric Biggers /**
2523f47a03dSEric Biggers  * struct test_sg_division - description of a scatterlist entry
2533f47a03dSEric Biggers  *
2543f47a03dSEric Biggers  * This struct describes one entry of a scatterlist being constructed to check a
2553f47a03dSEric Biggers  * crypto test vector.
2563f47a03dSEric Biggers  *
2573f47a03dSEric Biggers  * @proportion_of_total: length of this chunk relative to the total length,
2583f47a03dSEric Biggers  *			 given as a proportion out of TEST_SG_TOTAL so that it
2593f47a03dSEric Biggers  *			 scales to fit any test vector
2603f47a03dSEric Biggers  * @offset: byte offset into a 2-page buffer at which this chunk will start
2613f47a03dSEric Biggers  * @offset_relative_to_alignmask: if true, add the algorithm's alignmask to the
2623f47a03dSEric Biggers  *				  @offset
2633f47a03dSEric Biggers  * @flush_type: for hashes, whether an update() should be done now vs.
2643f47a03dSEric Biggers  *		continuing to accumulate data
2656570737cSEric Biggers  * @nosimd: if doing the pending update(), do it with SIMD disabled?
2663f47a03dSEric Biggers  */
2673f47a03dSEric Biggers struct test_sg_division {
2683f47a03dSEric Biggers 	unsigned int proportion_of_total;
2693f47a03dSEric Biggers 	unsigned int offset;
2703f47a03dSEric Biggers 	bool offset_relative_to_alignmask;
2713f47a03dSEric Biggers 	enum flush_type flush_type;
2726570737cSEric Biggers 	bool nosimd;
2733f47a03dSEric Biggers };
2743f47a03dSEric Biggers 
2753f47a03dSEric Biggers /**
2763f47a03dSEric Biggers  * struct testvec_config - configuration for testing a crypto test vector
2773f47a03dSEric Biggers  *
2783f47a03dSEric Biggers  * This struct describes the data layout and other parameters with which each
2793f47a03dSEric Biggers  * crypto test vector can be tested.
2803f47a03dSEric Biggers  *
2813f47a03dSEric Biggers  * @name: name of this config, logged for debugging purposes if a test fails
282f17f9e90SEric Biggers  * @inplace_mode: whether and how to operate on the data in-place, if applicable
2833f47a03dSEric Biggers  * @req_flags: extra request_flags, e.g. CRYPTO_TFM_REQ_MAY_SLEEP
2843f47a03dSEric Biggers  * @src_divs: description of how to arrange the source scatterlist
2853f47a03dSEric Biggers  * @dst_divs: description of how to arrange the dst scatterlist, if applicable
2863f47a03dSEric Biggers  *	      for the algorithm type.  Defaults to @src_divs if unset.
2873f47a03dSEric Biggers  * @iv_offset: misalignment of the IV in the range [0..MAX_ALGAPI_ALIGNMASK+1],
2883f47a03dSEric Biggers  *	       where 0 is aligned to a 2*(MAX_ALGAPI_ALIGNMASK+1) byte boundary
2893f47a03dSEric Biggers  * @iv_offset_relative_to_alignmask: if true, add the algorithm's alignmask to
2903f47a03dSEric Biggers  *				     the @iv_offset
291fd8c37c7SEric Biggers  * @key_offset: misalignment of the key, where 0 is default alignment
292fd8c37c7SEric Biggers  * @key_offset_relative_to_alignmask: if true, add the algorithm's alignmask to
293fd8c37c7SEric Biggers  *				      the @key_offset
2943f47a03dSEric Biggers  * @finalization_type: what finalization function to use for hashes
2956570737cSEric Biggers  * @nosimd: execute with SIMD disabled?  Requires !CRYPTO_TFM_REQ_MAY_SLEEP.
2963f47a03dSEric Biggers  */
2973f47a03dSEric Biggers struct testvec_config {
2983f47a03dSEric Biggers 	const char *name;
299f17f9e90SEric Biggers 	enum inplace_mode inplace_mode;
3003f47a03dSEric Biggers 	u32 req_flags;
3013f47a03dSEric Biggers 	struct test_sg_division src_divs[XBUFSIZE];
3023f47a03dSEric Biggers 	struct test_sg_division dst_divs[XBUFSIZE];
3033f47a03dSEric Biggers 	unsigned int iv_offset;
304fd8c37c7SEric Biggers 	unsigned int key_offset;
3053f47a03dSEric Biggers 	bool iv_offset_relative_to_alignmask;
306fd8c37c7SEric Biggers 	bool key_offset_relative_to_alignmask;
3073f47a03dSEric Biggers 	enum finalization_type finalization_type;
3086570737cSEric Biggers 	bool nosimd;
3093f47a03dSEric Biggers };
3103f47a03dSEric Biggers 
3113f47a03dSEric Biggers #define TESTVEC_CONFIG_NAMELEN	192
3123f47a03dSEric Biggers 
3134e7babbaSEric Biggers /*
3144e7babbaSEric Biggers  * The following are the lists of testvec_configs to test for each algorithm
3154e7babbaSEric Biggers  * type when the basic crypto self-tests are enabled, i.e. when
3164e7babbaSEric Biggers  * CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is unset.  They aim to provide good test
3174e7babbaSEric Biggers  * coverage, while keeping the test time much shorter than the full fuzz tests
3184e7babbaSEric Biggers  * so that the basic tests can be enabled in a wider range of circumstances.
3194e7babbaSEric Biggers  */
3204e7babbaSEric Biggers 
3214e7babbaSEric Biggers /* Configs for skciphers and aeads */
3224e7babbaSEric Biggers static const struct testvec_config default_cipher_testvec_configs[] = {
3234e7babbaSEric Biggers 	{
324f17f9e90SEric Biggers 		.name = "in-place (one sglist)",
325f17f9e90SEric Biggers 		.inplace_mode = INPLACE_ONE_SGLIST,
326f17f9e90SEric Biggers 		.src_divs = { { .proportion_of_total = 10000 } },
327f17f9e90SEric Biggers 	}, {
328f17f9e90SEric Biggers 		.name = "in-place (two sglists)",
329f17f9e90SEric Biggers 		.inplace_mode = INPLACE_TWO_SGLISTS,
3304e7babbaSEric Biggers 		.src_divs = { { .proportion_of_total = 10000 } },
3314e7babbaSEric Biggers 	}, {
3324e7babbaSEric Biggers 		.name = "out-of-place",
333f17f9e90SEric Biggers 		.inplace_mode = OUT_OF_PLACE,
3344e7babbaSEric Biggers 		.src_divs = { { .proportion_of_total = 10000 } },
3354e7babbaSEric Biggers 	}, {
3364e7babbaSEric Biggers 		.name = "unaligned buffer, offset=1",
3374e7babbaSEric Biggers 		.src_divs = { { .proportion_of_total = 10000, .offset = 1 } },
3384e7babbaSEric Biggers 		.iv_offset = 1,
339fd8c37c7SEric Biggers 		.key_offset = 1,
3404e7babbaSEric Biggers 	}, {
3414e7babbaSEric Biggers 		.name = "buffer aligned only to alignmask",
3424e7babbaSEric Biggers 		.src_divs = {
3434e7babbaSEric Biggers 			{
3444e7babbaSEric Biggers 				.proportion_of_total = 10000,
3454e7babbaSEric Biggers 				.offset = 1,
3464e7babbaSEric Biggers 				.offset_relative_to_alignmask = true,
3474e7babbaSEric Biggers 			},
3484e7babbaSEric Biggers 		},
3494e7babbaSEric Biggers 		.iv_offset = 1,
3504e7babbaSEric Biggers 		.iv_offset_relative_to_alignmask = true,
351fd8c37c7SEric Biggers 		.key_offset = 1,
352fd8c37c7SEric Biggers 		.key_offset_relative_to_alignmask = true,
3534e7babbaSEric Biggers 	}, {
3544e7babbaSEric Biggers 		.name = "two even aligned splits",
3554e7babbaSEric Biggers 		.src_divs = {
3564e7babbaSEric Biggers 			{ .proportion_of_total = 5000 },
3574e7babbaSEric Biggers 			{ .proportion_of_total = 5000 },
3584e7babbaSEric Biggers 		},
3594e7babbaSEric Biggers 	}, {
360acd4045dSZhang Yiqun 		.name = "one src, two even splits dst",
361acd4045dSZhang Yiqun 		.inplace_mode = OUT_OF_PLACE,
362acd4045dSZhang Yiqun 		.src_divs = { { .proportion_of_total = 10000 } },
363acd4045dSZhang Yiqun 		.dst_divs = {
364acd4045dSZhang Yiqun 			{ .proportion_of_total = 5000 },
365acd4045dSZhang Yiqun 			{ .proportion_of_total = 5000 },
366acd4045dSZhang Yiqun 		 },
367acd4045dSZhang Yiqun 	}, {
3684e7babbaSEric Biggers 		.name = "uneven misaligned splits, may sleep",
3694e7babbaSEric Biggers 		.req_flags = CRYPTO_TFM_REQ_MAY_SLEEP,
3704e7babbaSEric Biggers 		.src_divs = {
3714e7babbaSEric Biggers 			{ .proportion_of_total = 1900, .offset = 33 },
3724e7babbaSEric Biggers 			{ .proportion_of_total = 3300, .offset = 7  },
3734e7babbaSEric Biggers 			{ .proportion_of_total = 4800, .offset = 18 },
3744e7babbaSEric Biggers 		},
3754e7babbaSEric Biggers 		.iv_offset = 3,
376fd8c37c7SEric Biggers 		.key_offset = 3,
3774e7babbaSEric Biggers 	}, {
3784e7babbaSEric Biggers 		.name = "misaligned splits crossing pages, inplace",
379f17f9e90SEric Biggers 		.inplace_mode = INPLACE_ONE_SGLIST,
3804e7babbaSEric Biggers 		.src_divs = {
3814e7babbaSEric Biggers 			{
3824e7babbaSEric Biggers 				.proportion_of_total = 7500,
3834e7babbaSEric Biggers 				.offset = PAGE_SIZE - 32
3844e7babbaSEric Biggers 			}, {
3854e7babbaSEric Biggers 				.proportion_of_total = 2500,
3864e7babbaSEric Biggers 				.offset = PAGE_SIZE - 7
3874e7babbaSEric Biggers 			},
3884e7babbaSEric Biggers 		},
3894e7babbaSEric Biggers 	}
3904e7babbaSEric Biggers };
3914e7babbaSEric Biggers 
3924cc2dcf9SEric Biggers static const struct testvec_config default_hash_testvec_configs[] = {
3934cc2dcf9SEric Biggers 	{
3944cc2dcf9SEric Biggers 		.name = "init+update+final aligned buffer",
3954cc2dcf9SEric Biggers 		.src_divs = { { .proportion_of_total = 10000 } },
3964cc2dcf9SEric Biggers 		.finalization_type = FINALIZATION_TYPE_FINAL,
3974cc2dcf9SEric Biggers 	}, {
3984cc2dcf9SEric Biggers 		.name = "init+finup aligned buffer",
3994cc2dcf9SEric Biggers 		.src_divs = { { .proportion_of_total = 10000 } },
4004cc2dcf9SEric Biggers 		.finalization_type = FINALIZATION_TYPE_FINUP,
4014cc2dcf9SEric Biggers 	}, {
4024cc2dcf9SEric Biggers 		.name = "digest aligned buffer",
4034cc2dcf9SEric Biggers 		.src_divs = { { .proportion_of_total = 10000 } },
4044cc2dcf9SEric Biggers 		.finalization_type = FINALIZATION_TYPE_DIGEST,
4054cc2dcf9SEric Biggers 	}, {
4064cc2dcf9SEric Biggers 		.name = "init+update+final misaligned buffer",
4074cc2dcf9SEric Biggers 		.src_divs = { { .proportion_of_total = 10000, .offset = 1 } },
4084cc2dcf9SEric Biggers 		.finalization_type = FINALIZATION_TYPE_FINAL,
409fd8c37c7SEric Biggers 		.key_offset = 1,
4104cc2dcf9SEric Biggers 	}, {
4114cc2dcf9SEric Biggers 		.name = "digest buffer aligned only to alignmask",
4124cc2dcf9SEric Biggers 		.src_divs = {
4134cc2dcf9SEric Biggers 			{
4144cc2dcf9SEric Biggers 				.proportion_of_total = 10000,
4154cc2dcf9SEric Biggers 				.offset = 1,
4164cc2dcf9SEric Biggers 				.offset_relative_to_alignmask = true,
4174cc2dcf9SEric Biggers 			},
4184cc2dcf9SEric Biggers 		},
4194cc2dcf9SEric Biggers 		.finalization_type = FINALIZATION_TYPE_DIGEST,
420fd8c37c7SEric Biggers 		.key_offset = 1,
421fd8c37c7SEric Biggers 		.key_offset_relative_to_alignmask = true,
4224cc2dcf9SEric Biggers 	}, {
4234cc2dcf9SEric Biggers 		.name = "init+update+update+final two even splits",
4244cc2dcf9SEric Biggers 		.src_divs = {
4254cc2dcf9SEric Biggers 			{ .proportion_of_total = 5000 },
4264cc2dcf9SEric Biggers 			{
4274cc2dcf9SEric Biggers 				.proportion_of_total = 5000,
4284cc2dcf9SEric Biggers 				.flush_type = FLUSH_TYPE_FLUSH,
4294cc2dcf9SEric Biggers 			},
4304cc2dcf9SEric Biggers 		},
4314cc2dcf9SEric Biggers 		.finalization_type = FINALIZATION_TYPE_FINAL,
4324cc2dcf9SEric Biggers 	}, {
4334cc2dcf9SEric Biggers 		.name = "digest uneven misaligned splits, may sleep",
4344cc2dcf9SEric Biggers 		.req_flags = CRYPTO_TFM_REQ_MAY_SLEEP,
4354cc2dcf9SEric Biggers 		.src_divs = {
4364cc2dcf9SEric Biggers 			{ .proportion_of_total = 1900, .offset = 33 },
4374cc2dcf9SEric Biggers 			{ .proportion_of_total = 3300, .offset = 7  },
4384cc2dcf9SEric Biggers 			{ .proportion_of_total = 4800, .offset = 18 },
4394cc2dcf9SEric Biggers 		},
4404cc2dcf9SEric Biggers 		.finalization_type = FINALIZATION_TYPE_DIGEST,
4414cc2dcf9SEric Biggers 	}, {
4424cc2dcf9SEric Biggers 		.name = "digest misaligned splits crossing pages",
4434cc2dcf9SEric Biggers 		.src_divs = {
4444cc2dcf9SEric Biggers 			{
4454cc2dcf9SEric Biggers 				.proportion_of_total = 7500,
4464cc2dcf9SEric Biggers 				.offset = PAGE_SIZE - 32,
4474cc2dcf9SEric Biggers 			}, {
4484cc2dcf9SEric Biggers 				.proportion_of_total = 2500,
4494cc2dcf9SEric Biggers 				.offset = PAGE_SIZE - 7,
4504cc2dcf9SEric Biggers 			},
4514cc2dcf9SEric Biggers 		},
4524cc2dcf9SEric Biggers 		.finalization_type = FINALIZATION_TYPE_DIGEST,
4534cc2dcf9SEric Biggers 	}, {
4544cc2dcf9SEric Biggers 		.name = "import/export",
4554cc2dcf9SEric Biggers 		.src_divs = {
4564cc2dcf9SEric Biggers 			{
4574cc2dcf9SEric Biggers 				.proportion_of_total = 6500,
4584cc2dcf9SEric Biggers 				.flush_type = FLUSH_TYPE_REIMPORT,
4594cc2dcf9SEric Biggers 			}, {
4604cc2dcf9SEric Biggers 				.proportion_of_total = 3500,
4614cc2dcf9SEric Biggers 				.flush_type = FLUSH_TYPE_REIMPORT,
4624cc2dcf9SEric Biggers 			},
4634cc2dcf9SEric Biggers 		},
4644cc2dcf9SEric Biggers 		.finalization_type = FINALIZATION_TYPE_FINAL,
4654cc2dcf9SEric Biggers 	}
4664cc2dcf9SEric Biggers };
4674cc2dcf9SEric Biggers 
count_test_sg_divisions(const struct test_sg_division * divs)4683f47a03dSEric Biggers static unsigned int count_test_sg_divisions(const struct test_sg_division *divs)
4693f47a03dSEric Biggers {
4703f47a03dSEric Biggers 	unsigned int remaining = TEST_SG_TOTAL;
4713f47a03dSEric Biggers 	unsigned int ndivs = 0;
4723f47a03dSEric Biggers 
4733f47a03dSEric Biggers 	do {
4743f47a03dSEric Biggers 		remaining -= divs[ndivs++].proportion_of_total;
4753f47a03dSEric Biggers 	} while (remaining);
4763f47a03dSEric Biggers 
4773f47a03dSEric Biggers 	return ndivs;
4783f47a03dSEric Biggers }
4793f47a03dSEric Biggers 
4806570737cSEric Biggers #define SGDIVS_HAVE_FLUSHES	BIT(0)
4816570737cSEric Biggers #define SGDIVS_HAVE_NOSIMD	BIT(1)
4826570737cSEric Biggers 
valid_sg_divisions(const struct test_sg_division * divs,unsigned int count,int * flags_ret)4833f47a03dSEric Biggers static bool valid_sg_divisions(const struct test_sg_division *divs,
4846570737cSEric Biggers 			       unsigned int count, int *flags_ret)
4853f47a03dSEric Biggers {
4863f47a03dSEric Biggers 	unsigned int total = 0;
4873f47a03dSEric Biggers 	unsigned int i;
4883f47a03dSEric Biggers 
4893f47a03dSEric Biggers 	for (i = 0; i < count && total != TEST_SG_TOTAL; i++) {
4903f47a03dSEric Biggers 		if (divs[i].proportion_of_total <= 0 ||
4913f47a03dSEric Biggers 		    divs[i].proportion_of_total > TEST_SG_TOTAL - total)
4923f47a03dSEric Biggers 			return false;
4933f47a03dSEric Biggers 		total += divs[i].proportion_of_total;
4943f47a03dSEric Biggers 		if (divs[i].flush_type != FLUSH_TYPE_NONE)
4956570737cSEric Biggers 			*flags_ret |= SGDIVS_HAVE_FLUSHES;
4966570737cSEric Biggers 		if (divs[i].nosimd)
4976570737cSEric Biggers 			*flags_ret |= SGDIVS_HAVE_NOSIMD;
4983f47a03dSEric Biggers 	}
4993f47a03dSEric Biggers 	return total == TEST_SG_TOTAL &&
5003f47a03dSEric Biggers 		memchr_inv(&divs[i], 0, (count - i) * sizeof(divs[0])) == NULL;
5013f47a03dSEric Biggers }
5023f47a03dSEric Biggers 
5033f47a03dSEric Biggers /*
5043f47a03dSEric Biggers  * Check whether the given testvec_config is valid.  This isn't strictly needed
5053f47a03dSEric Biggers  * since every testvec_config should be valid, but check anyway so that people
5063f47a03dSEric Biggers  * don't unknowingly add broken configs that don't do what they wanted.
5073f47a03dSEric Biggers  */
valid_testvec_config(const struct testvec_config * cfg)5083f47a03dSEric Biggers static bool valid_testvec_config(const struct testvec_config *cfg)
5093f47a03dSEric Biggers {
5106570737cSEric Biggers 	int flags = 0;
5113f47a03dSEric Biggers 
5123f47a03dSEric Biggers 	if (cfg->name == NULL)
5133f47a03dSEric Biggers 		return false;
5143f47a03dSEric Biggers 
5153f47a03dSEric Biggers 	if (!valid_sg_divisions(cfg->src_divs, ARRAY_SIZE(cfg->src_divs),
5166570737cSEric Biggers 				&flags))
5173f47a03dSEric Biggers 		return false;
5183f47a03dSEric Biggers 
5193f47a03dSEric Biggers 	if (cfg->dst_divs[0].proportion_of_total) {
5203f47a03dSEric Biggers 		if (!valid_sg_divisions(cfg->dst_divs,
5216570737cSEric Biggers 					ARRAY_SIZE(cfg->dst_divs), &flags))
5223f47a03dSEric Biggers 			return false;
5233f47a03dSEric Biggers 	} else {
5243f47a03dSEric Biggers 		if (memchr_inv(cfg->dst_divs, 0, sizeof(cfg->dst_divs)))
5253f47a03dSEric Biggers 			return false;
5263f47a03dSEric Biggers 		/* defaults to dst_divs=src_divs */
5273f47a03dSEric Biggers 	}
5283f47a03dSEric Biggers 
5293f47a03dSEric Biggers 	if (cfg->iv_offset +
5303f47a03dSEric Biggers 	    (cfg->iv_offset_relative_to_alignmask ? MAX_ALGAPI_ALIGNMASK : 0) >
5313f47a03dSEric Biggers 	    MAX_ALGAPI_ALIGNMASK + 1)
5323f47a03dSEric Biggers 		return false;
5333f47a03dSEric Biggers 
5346570737cSEric Biggers 	if ((flags & (SGDIVS_HAVE_FLUSHES | SGDIVS_HAVE_NOSIMD)) &&
5356570737cSEric Biggers 	    cfg->finalization_type == FINALIZATION_TYPE_DIGEST)
5366570737cSEric Biggers 		return false;
5376570737cSEric Biggers 
5386570737cSEric Biggers 	if ((cfg->nosimd || (flags & SGDIVS_HAVE_NOSIMD)) &&
5396570737cSEric Biggers 	    (cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP))
5403f47a03dSEric Biggers 		return false;
5413f47a03dSEric Biggers 
5423f47a03dSEric Biggers 	return true;
5433f47a03dSEric Biggers }
5443f47a03dSEric Biggers 
5453f47a03dSEric Biggers struct test_sglist {
5463f47a03dSEric Biggers 	char *bufs[XBUFSIZE];
5473f47a03dSEric Biggers 	struct scatterlist sgl[XBUFSIZE];
5483f47a03dSEric Biggers 	struct scatterlist sgl_saved[XBUFSIZE];
5493f47a03dSEric Biggers 	struct scatterlist *sgl_ptr;
5503f47a03dSEric Biggers 	unsigned int nents;
5513f47a03dSEric Biggers };
5523f47a03dSEric Biggers 
init_test_sglist(struct test_sglist * tsgl)5533f47a03dSEric Biggers static int init_test_sglist(struct test_sglist *tsgl)
5543f47a03dSEric Biggers {
5553f47a03dSEric Biggers 	return __testmgr_alloc_buf(tsgl->bufs, 1 /* two pages per buffer */);
5563f47a03dSEric Biggers }
5573f47a03dSEric Biggers 
destroy_test_sglist(struct test_sglist * tsgl)5583f47a03dSEric Biggers static void destroy_test_sglist(struct test_sglist *tsgl)
5593f47a03dSEric Biggers {
5603f47a03dSEric Biggers 	return __testmgr_free_buf(tsgl->bufs, 1 /* two pages per buffer */);
5613f47a03dSEric Biggers }
5623f47a03dSEric Biggers 
5633f47a03dSEric Biggers /**
5643f47a03dSEric Biggers  * build_test_sglist() - build a scatterlist for a crypto test
5653f47a03dSEric Biggers  *
5663f47a03dSEric Biggers  * @tsgl: the scatterlist to build.  @tsgl->bufs[] contains an array of 2-page
5673f47a03dSEric Biggers  *	  buffers which the scatterlist @tsgl->sgl[] will be made to point into.
5683f47a03dSEric Biggers  * @divs: the layout specification on which the scatterlist will be based
5693f47a03dSEric Biggers  * @alignmask: the algorithm's alignmask
5703f47a03dSEric Biggers  * @total_len: the total length of the scatterlist to build in bytes
5713f47a03dSEric Biggers  * @data: if non-NULL, the buffers will be filled with this data until it ends.
5723f47a03dSEric Biggers  *	  Otherwise the buffers will be poisoned.  In both cases, some bytes
5733f47a03dSEric Biggers  *	  past the end of each buffer will be poisoned to help detect overruns.
5743f47a03dSEric Biggers  * @out_divs: if non-NULL, the test_sg_division to which each scatterlist entry
5753f47a03dSEric Biggers  *	      corresponds will be returned here.  This will match @divs except
5763f47a03dSEric Biggers  *	      that divisions resolving to a length of 0 are omitted as they are
5773f47a03dSEric Biggers  *	      not included in the scatterlist.
5783f47a03dSEric Biggers  *
5793f47a03dSEric Biggers  * Return: 0 or a -errno value
5803f47a03dSEric Biggers  */
build_test_sglist(struct test_sglist * tsgl,const struct test_sg_division * divs,const unsigned int alignmask,const unsigned int total_len,struct iov_iter * data,const struct test_sg_division * out_divs[XBUFSIZE])5813f47a03dSEric Biggers static int build_test_sglist(struct test_sglist *tsgl,
5823f47a03dSEric Biggers 			     const struct test_sg_division *divs,
5833f47a03dSEric Biggers 			     const unsigned int alignmask,
5843f47a03dSEric Biggers 			     const unsigned int total_len,
5853f47a03dSEric Biggers 			     struct iov_iter *data,
5863f47a03dSEric Biggers 			     const struct test_sg_division *out_divs[XBUFSIZE])
5873f47a03dSEric Biggers {
5883f47a03dSEric Biggers 	struct {
5893f47a03dSEric Biggers 		const struct test_sg_division *div;
5903f47a03dSEric Biggers 		size_t length;
5913f47a03dSEric Biggers 	} partitions[XBUFSIZE];
5923f47a03dSEric Biggers 	const unsigned int ndivs = count_test_sg_divisions(divs);
5933f47a03dSEric Biggers 	unsigned int len_remaining = total_len;
5943f47a03dSEric Biggers 	unsigned int i;
5953f47a03dSEric Biggers 
5963f47a03dSEric Biggers 	BUILD_BUG_ON(ARRAY_SIZE(partitions) != ARRAY_SIZE(tsgl->sgl));
5973f47a03dSEric Biggers 	if (WARN_ON(ndivs > ARRAY_SIZE(partitions)))
5983f47a03dSEric Biggers 		return -EINVAL;
5993f47a03dSEric Biggers 
6003f47a03dSEric Biggers 	/* Calculate the (div, length) pairs */
6013f47a03dSEric Biggers 	tsgl->nents = 0;
6023f47a03dSEric Biggers 	for (i = 0; i < ndivs; i++) {
6033f47a03dSEric Biggers 		unsigned int len_this_sg =
6043f47a03dSEric Biggers 			min(len_remaining,
6053f47a03dSEric Biggers 			    (total_len * divs[i].proportion_of_total +
6063f47a03dSEric Biggers 			     TEST_SG_TOTAL / 2) / TEST_SG_TOTAL);
6073f47a03dSEric Biggers 
6083f47a03dSEric Biggers 		if (len_this_sg != 0) {
6093f47a03dSEric Biggers 			partitions[tsgl->nents].div = &divs[i];
6103f47a03dSEric Biggers 			partitions[tsgl->nents].length = len_this_sg;
6113f47a03dSEric Biggers 			tsgl->nents++;
6123f47a03dSEric Biggers 			len_remaining -= len_this_sg;
6133f47a03dSEric Biggers 		}
6143f47a03dSEric Biggers 	}
6153f47a03dSEric Biggers 	if (tsgl->nents == 0) {
6163f47a03dSEric Biggers 		partitions[tsgl->nents].div = &divs[0];
6173f47a03dSEric Biggers 		partitions[tsgl->nents].length = 0;
6183f47a03dSEric Biggers 		tsgl->nents++;
6193f47a03dSEric Biggers 	}
6203f47a03dSEric Biggers 	partitions[tsgl->nents - 1].length += len_remaining;
6213f47a03dSEric Biggers 
6223f47a03dSEric Biggers 	/* Set up the sgl entries and fill the data or poison */
6233f47a03dSEric Biggers 	sg_init_table(tsgl->sgl, tsgl->nents);
6243f47a03dSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
6253f47a03dSEric Biggers 		unsigned int offset = partitions[i].div->offset;
6263f47a03dSEric Biggers 		void *addr;
6273f47a03dSEric Biggers 
6283f47a03dSEric Biggers 		if (partitions[i].div->offset_relative_to_alignmask)
6293f47a03dSEric Biggers 			offset += alignmask;
6303f47a03dSEric Biggers 
6313f47a03dSEric Biggers 		while (offset + partitions[i].length + TESTMGR_POISON_LEN >
6323f47a03dSEric Biggers 		       2 * PAGE_SIZE) {
6333f47a03dSEric Biggers 			if (WARN_ON(offset <= 0))
6343f47a03dSEric Biggers 				return -EINVAL;
6353f47a03dSEric Biggers 			offset /= 2;
6363f47a03dSEric Biggers 		}
6373f47a03dSEric Biggers 
6383f47a03dSEric Biggers 		addr = &tsgl->bufs[i][offset];
6393f47a03dSEric Biggers 		sg_set_buf(&tsgl->sgl[i], addr, partitions[i].length);
6403f47a03dSEric Biggers 
6413f47a03dSEric Biggers 		if (out_divs)
6423f47a03dSEric Biggers 			out_divs[i] = partitions[i].div;
6433f47a03dSEric Biggers 
6443f47a03dSEric Biggers 		if (data) {
6453f47a03dSEric Biggers 			size_t copy_len, copied;
6463f47a03dSEric Biggers 
6473f47a03dSEric Biggers 			copy_len = min(partitions[i].length, data->count);
6483f47a03dSEric Biggers 			copied = copy_from_iter(addr, copy_len, data);
6493f47a03dSEric Biggers 			if (WARN_ON(copied != copy_len))
6503f47a03dSEric Biggers 				return -EINVAL;
6513f47a03dSEric Biggers 			testmgr_poison(addr + copy_len, partitions[i].length +
6523f47a03dSEric Biggers 				       TESTMGR_POISON_LEN - copy_len);
6533f47a03dSEric Biggers 		} else {
6543f47a03dSEric Biggers 			testmgr_poison(addr, partitions[i].length +
6553f47a03dSEric Biggers 				       TESTMGR_POISON_LEN);
6563f47a03dSEric Biggers 		}
6573f47a03dSEric Biggers 	}
6583f47a03dSEric Biggers 
6593f47a03dSEric Biggers 	sg_mark_end(&tsgl->sgl[tsgl->nents - 1]);
6603f47a03dSEric Biggers 	tsgl->sgl_ptr = tsgl->sgl;
6613f47a03dSEric Biggers 	memcpy(tsgl->sgl_saved, tsgl->sgl, tsgl->nents * sizeof(tsgl->sgl[0]));
6623f47a03dSEric Biggers 	return 0;
6633f47a03dSEric Biggers }
6643f47a03dSEric Biggers 
6653f47a03dSEric Biggers /*
6663f47a03dSEric Biggers  * Verify that a scatterlist crypto operation produced the correct output.
6673f47a03dSEric Biggers  *
6683f47a03dSEric Biggers  * @tsgl: scatterlist containing the actual output
6693f47a03dSEric Biggers  * @expected_output: buffer containing the expected output
6703f47a03dSEric Biggers  * @len_to_check: length of @expected_output in bytes
6713f47a03dSEric Biggers  * @unchecked_prefix_len: number of ignored bytes in @tsgl prior to real result
6723f47a03dSEric Biggers  * @check_poison: verify that the poison bytes after each chunk are intact?
6733f47a03dSEric Biggers  *
6743f47a03dSEric Biggers  * Return: 0 if correct, -EINVAL if incorrect, -EOVERFLOW if buffer overrun.
6753f47a03dSEric Biggers  */
verify_correct_output(const struct test_sglist * tsgl,const char * expected_output,unsigned int len_to_check,unsigned int unchecked_prefix_len,bool check_poison)6763f47a03dSEric Biggers static int verify_correct_output(const struct test_sglist *tsgl,
6773f47a03dSEric Biggers 				 const char *expected_output,
6783f47a03dSEric Biggers 				 unsigned int len_to_check,
6793f47a03dSEric Biggers 				 unsigned int unchecked_prefix_len,
6803f47a03dSEric Biggers 				 bool check_poison)
6813f47a03dSEric Biggers {
6823f47a03dSEric Biggers 	unsigned int i;
6833f47a03dSEric Biggers 
6843f47a03dSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
6853f47a03dSEric Biggers 		struct scatterlist *sg = &tsgl->sgl_ptr[i];
6863f47a03dSEric Biggers 		unsigned int len = sg->length;
6873f47a03dSEric Biggers 		unsigned int offset = sg->offset;
6883f47a03dSEric Biggers 		const char *actual_output;
6893f47a03dSEric Biggers 
6903f47a03dSEric Biggers 		if (unchecked_prefix_len) {
6913f47a03dSEric Biggers 			if (unchecked_prefix_len >= len) {
6923f47a03dSEric Biggers 				unchecked_prefix_len -= len;
6933f47a03dSEric Biggers 				continue;
6943f47a03dSEric Biggers 			}
6953f47a03dSEric Biggers 			offset += unchecked_prefix_len;
6963f47a03dSEric Biggers 			len -= unchecked_prefix_len;
6973f47a03dSEric Biggers 			unchecked_prefix_len = 0;
6983f47a03dSEric Biggers 		}
6993f47a03dSEric Biggers 		len = min(len, len_to_check);
7003f47a03dSEric Biggers 		actual_output = page_address(sg_page(sg)) + offset;
7013f47a03dSEric Biggers 		if (memcmp(expected_output, actual_output, len) != 0)
7023f47a03dSEric Biggers 			return -EINVAL;
7033f47a03dSEric Biggers 		if (check_poison &&
7043f47a03dSEric Biggers 		    !testmgr_is_poison(actual_output + len, TESTMGR_POISON_LEN))
7053f47a03dSEric Biggers 			return -EOVERFLOW;
7063f47a03dSEric Biggers 		len_to_check -= len;
7073f47a03dSEric Biggers 		expected_output += len;
7083f47a03dSEric Biggers 	}
7093f47a03dSEric Biggers 	if (WARN_ON(len_to_check != 0))
7103f47a03dSEric Biggers 		return -EINVAL;
7113f47a03dSEric Biggers 	return 0;
7123f47a03dSEric Biggers }
7133f47a03dSEric Biggers 
is_test_sglist_corrupted(const struct test_sglist * tsgl)7143f47a03dSEric Biggers static bool is_test_sglist_corrupted(const struct test_sglist *tsgl)
7153f47a03dSEric Biggers {
7163f47a03dSEric Biggers 	unsigned int i;
7173f47a03dSEric Biggers 
7183f47a03dSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
7193f47a03dSEric Biggers 		if (tsgl->sgl[i].page_link != tsgl->sgl_saved[i].page_link)
7203f47a03dSEric Biggers 			return true;
7213f47a03dSEric Biggers 		if (tsgl->sgl[i].offset != tsgl->sgl_saved[i].offset)
7223f47a03dSEric Biggers 			return true;
7233f47a03dSEric Biggers 		if (tsgl->sgl[i].length != tsgl->sgl_saved[i].length)
7243f47a03dSEric Biggers 			return true;
7253f47a03dSEric Biggers 	}
7263f47a03dSEric Biggers 	return false;
7273f47a03dSEric Biggers }
7283f47a03dSEric Biggers 
7293f47a03dSEric Biggers struct cipher_test_sglists {
7303f47a03dSEric Biggers 	struct test_sglist src;
7313f47a03dSEric Biggers 	struct test_sglist dst;
7323f47a03dSEric Biggers };
7333f47a03dSEric Biggers 
alloc_cipher_test_sglists(void)7343f47a03dSEric Biggers static struct cipher_test_sglists *alloc_cipher_test_sglists(void)
7353f47a03dSEric Biggers {
7363f47a03dSEric Biggers 	struct cipher_test_sglists *tsgls;
7373f47a03dSEric Biggers 
7383f47a03dSEric Biggers 	tsgls = kmalloc(sizeof(*tsgls), GFP_KERNEL);
7393f47a03dSEric Biggers 	if (!tsgls)
7403f47a03dSEric Biggers 		return NULL;
7413f47a03dSEric Biggers 
7423f47a03dSEric Biggers 	if (init_test_sglist(&tsgls->src) != 0)
7433f47a03dSEric Biggers 		goto fail_kfree;
7443f47a03dSEric Biggers 	if (init_test_sglist(&tsgls->dst) != 0)
7453f47a03dSEric Biggers 		goto fail_destroy_src;
7463f47a03dSEric Biggers 
7473f47a03dSEric Biggers 	return tsgls;
7483f47a03dSEric Biggers 
7493f47a03dSEric Biggers fail_destroy_src:
7503f47a03dSEric Biggers 	destroy_test_sglist(&tsgls->src);
7513f47a03dSEric Biggers fail_kfree:
7523f47a03dSEric Biggers 	kfree(tsgls);
7533f47a03dSEric Biggers 	return NULL;
7543f47a03dSEric Biggers }
7553f47a03dSEric Biggers 
free_cipher_test_sglists(struct cipher_test_sglists * tsgls)7563f47a03dSEric Biggers static void free_cipher_test_sglists(struct cipher_test_sglists *tsgls)
7573f47a03dSEric Biggers {
7583f47a03dSEric Biggers 	if (tsgls) {
7593f47a03dSEric Biggers 		destroy_test_sglist(&tsgls->src);
7603f47a03dSEric Biggers 		destroy_test_sglist(&tsgls->dst);
7613f47a03dSEric Biggers 		kfree(tsgls);
7623f47a03dSEric Biggers 	}
7633f47a03dSEric Biggers }
7643f47a03dSEric Biggers 
7653f47a03dSEric Biggers /* Build the src and dst scatterlists for an skcipher or AEAD test */
build_cipher_test_sglists(struct cipher_test_sglists * tsgls,const struct testvec_config * cfg,unsigned int alignmask,unsigned int src_total_len,unsigned int dst_total_len,const struct kvec * inputs,unsigned int nr_inputs)7663f47a03dSEric Biggers static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls,
7673f47a03dSEric Biggers 				     const struct testvec_config *cfg,
7683f47a03dSEric Biggers 				     unsigned int alignmask,
7693f47a03dSEric Biggers 				     unsigned int src_total_len,
7703f47a03dSEric Biggers 				     unsigned int dst_total_len,
7713f47a03dSEric Biggers 				     const struct kvec *inputs,
7723f47a03dSEric Biggers 				     unsigned int nr_inputs)
7733f47a03dSEric Biggers {
7743f47a03dSEric Biggers 	struct iov_iter input;
7753f47a03dSEric Biggers 	int err;
7763f47a03dSEric Biggers 
777de4eda9dSAl Viro 	iov_iter_kvec(&input, ITER_SOURCE, inputs, nr_inputs, src_total_len);
7783f47a03dSEric Biggers 	err = build_test_sglist(&tsgls->src, cfg->src_divs, alignmask,
779f17f9e90SEric Biggers 				cfg->inplace_mode != OUT_OF_PLACE ?
7803f47a03dSEric Biggers 					max(dst_total_len, src_total_len) :
7813f47a03dSEric Biggers 					src_total_len,
7823f47a03dSEric Biggers 				&input, NULL);
7833f47a03dSEric Biggers 	if (err)
7843f47a03dSEric Biggers 		return err;
7853f47a03dSEric Biggers 
786f17f9e90SEric Biggers 	/*
787f17f9e90SEric Biggers 	 * In-place crypto operations can use the same scatterlist for both the
788f17f9e90SEric Biggers 	 * source and destination (req->src == req->dst), or can use separate
789f17f9e90SEric Biggers 	 * scatterlists (req->src != req->dst) which point to the same
790f17f9e90SEric Biggers 	 * underlying memory.  Make sure to test both cases.
791f17f9e90SEric Biggers 	 */
792f17f9e90SEric Biggers 	if (cfg->inplace_mode == INPLACE_ONE_SGLIST) {
7933f47a03dSEric Biggers 		tsgls->dst.sgl_ptr = tsgls->src.sgl;
7943f47a03dSEric Biggers 		tsgls->dst.nents = tsgls->src.nents;
7953f47a03dSEric Biggers 		return 0;
7963f47a03dSEric Biggers 	}
797f17f9e90SEric Biggers 	if (cfg->inplace_mode == INPLACE_TWO_SGLISTS) {
798f17f9e90SEric Biggers 		/*
799f17f9e90SEric Biggers 		 * For now we keep it simple and only test the case where the
800f17f9e90SEric Biggers 		 * two scatterlists have identical entries, rather than
801f17f9e90SEric Biggers 		 * different entries that split up the same memory differently.
802f17f9e90SEric Biggers 		 */
803f17f9e90SEric Biggers 		memcpy(tsgls->dst.sgl, tsgls->src.sgl,
804f17f9e90SEric Biggers 		       tsgls->src.nents * sizeof(tsgls->src.sgl[0]));
805f17f9e90SEric Biggers 		memcpy(tsgls->dst.sgl_saved, tsgls->src.sgl,
806f17f9e90SEric Biggers 		       tsgls->src.nents * sizeof(tsgls->src.sgl[0]));
807f17f9e90SEric Biggers 		tsgls->dst.sgl_ptr = tsgls->dst.sgl;
808f17f9e90SEric Biggers 		tsgls->dst.nents = tsgls->src.nents;
809f17f9e90SEric Biggers 		return 0;
810f17f9e90SEric Biggers 	}
811f17f9e90SEric Biggers 	/* Out of place */
8123f47a03dSEric Biggers 	return build_test_sglist(&tsgls->dst,
8133f47a03dSEric Biggers 				 cfg->dst_divs[0].proportion_of_total ?
8143f47a03dSEric Biggers 					cfg->dst_divs : cfg->src_divs,
8153f47a03dSEric Biggers 				 alignmask, dst_total_len, NULL, NULL);
816f8b0d4d0SHerbert Xu }
817f8b0d4d0SHerbert Xu 
818fd8c37c7SEric Biggers /*
819fd8c37c7SEric Biggers  * Support for testing passing a misaligned key to setkey():
820fd8c37c7SEric Biggers  *
821fd8c37c7SEric Biggers  * If cfg->key_offset is set, copy the key into a new buffer at that offset,
822fd8c37c7SEric Biggers  * optionally adding alignmask.  Else, just use the key directly.
823fd8c37c7SEric Biggers  */
prepare_keybuf(const u8 * key,unsigned int ksize,const struct testvec_config * cfg,unsigned int alignmask,const u8 ** keybuf_ret,const u8 ** keyptr_ret)824fd8c37c7SEric Biggers static int prepare_keybuf(const u8 *key, unsigned int ksize,
825fd8c37c7SEric Biggers 			  const struct testvec_config *cfg,
826fd8c37c7SEric Biggers 			  unsigned int alignmask,
827fd8c37c7SEric Biggers 			  const u8 **keybuf_ret, const u8 **keyptr_ret)
828fd8c37c7SEric Biggers {
829fd8c37c7SEric Biggers 	unsigned int key_offset = cfg->key_offset;
830fd8c37c7SEric Biggers 	u8 *keybuf = NULL, *keyptr = (u8 *)key;
831fd8c37c7SEric Biggers 
832fd8c37c7SEric Biggers 	if (key_offset != 0) {
833fd8c37c7SEric Biggers 		if (cfg->key_offset_relative_to_alignmask)
834fd8c37c7SEric Biggers 			key_offset += alignmask;
835fd8c37c7SEric Biggers 		keybuf = kmalloc(key_offset + ksize, GFP_KERNEL);
836fd8c37c7SEric Biggers 		if (!keybuf)
837fd8c37c7SEric Biggers 			return -ENOMEM;
838fd8c37c7SEric Biggers 		keyptr = keybuf + key_offset;
839fd8c37c7SEric Biggers 		memcpy(keyptr, key, ksize);
840fd8c37c7SEric Biggers 	}
841fd8c37c7SEric Biggers 	*keybuf_ret = keybuf;
842fd8c37c7SEric Biggers 	*keyptr_ret = keyptr;
843fd8c37c7SEric Biggers 	return 0;
844fd8c37c7SEric Biggers }
845fd8c37c7SEric Biggers 
846fd8c37c7SEric Biggers /* Like setkey_f(tfm, key, ksize), but sometimes misalign the key */
847fd8c37c7SEric Biggers #define do_setkey(setkey_f, tfm, key, ksize, cfg, alignmask)		\
848fd8c37c7SEric Biggers ({									\
849fd8c37c7SEric Biggers 	const u8 *keybuf, *keyptr;					\
850fd8c37c7SEric Biggers 	int err;							\
851fd8c37c7SEric Biggers 									\
852fd8c37c7SEric Biggers 	err = prepare_keybuf((key), (ksize), (cfg), (alignmask),	\
853fd8c37c7SEric Biggers 			     &keybuf, &keyptr);				\
854fd8c37c7SEric Biggers 	if (err == 0) {							\
855fd8c37c7SEric Biggers 		err = setkey_f((tfm), keyptr, (ksize));			\
856fd8c37c7SEric Biggers 		kfree(keybuf);						\
857fd8c37c7SEric Biggers 	}								\
858fd8c37c7SEric Biggers 	err;								\
859fd8c37c7SEric Biggers })
860fd8c37c7SEric Biggers 
86125f9dddbSEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
862f2bb770aSEric Biggers 
863f900fde2SEric Biggers /*
864f900fde2SEric Biggers  * The fuzz tests use prandom instead of the normal Linux RNG since they don't
865f900fde2SEric Biggers  * need cryptographically secure random numbers.  This greatly improves the
866f900fde2SEric Biggers  * performance of these tests, especially if they are run before the Linux RNG
867f900fde2SEric Biggers  * has been initialized or if they are run on a lockdep-enabled kernel.
868f900fde2SEric Biggers  */
869f2bb770aSEric Biggers 
init_rnd_state(struct rnd_state * rng)870f900fde2SEric Biggers static inline void init_rnd_state(struct rnd_state *rng)
871f900fde2SEric Biggers {
872f900fde2SEric Biggers 	prandom_seed_state(rng, get_random_u64());
873f900fde2SEric Biggers }
874f900fde2SEric Biggers 
prandom_u8(struct rnd_state * rng)875f900fde2SEric Biggers static inline u8 prandom_u8(struct rnd_state *rng)
876f900fde2SEric Biggers {
877f900fde2SEric Biggers 	return prandom_u32_state(rng);
878f900fde2SEric Biggers }
879f900fde2SEric Biggers 
prandom_u32_below(struct rnd_state * rng,u32 ceil)880f900fde2SEric Biggers static inline u32 prandom_u32_below(struct rnd_state *rng, u32 ceil)
881f900fde2SEric Biggers {
882f900fde2SEric Biggers 	/*
883f900fde2SEric Biggers 	 * This is slightly biased for non-power-of-2 values of 'ceil', but this
884f900fde2SEric Biggers 	 * isn't important here.
885f900fde2SEric Biggers 	 */
886f900fde2SEric Biggers 	return prandom_u32_state(rng) % ceil;
887f900fde2SEric Biggers }
888f900fde2SEric Biggers 
prandom_bool(struct rnd_state * rng)889f900fde2SEric Biggers static inline bool prandom_bool(struct rnd_state *rng)
890f900fde2SEric Biggers {
891f900fde2SEric Biggers 	return prandom_u32_below(rng, 2);
892f900fde2SEric Biggers }
893f900fde2SEric Biggers 
prandom_u32_inclusive(struct rnd_state * rng,u32 floor,u32 ceil)894f900fde2SEric Biggers static inline u32 prandom_u32_inclusive(struct rnd_state *rng,
895f900fde2SEric Biggers 					u32 floor, u32 ceil)
896f900fde2SEric Biggers {
897f900fde2SEric Biggers 	return floor + prandom_u32_below(rng, ceil - floor + 1);
898f900fde2SEric Biggers }
899f900fde2SEric Biggers 
900f900fde2SEric Biggers /* Generate a random length in range [0, max_len], but prefer smaller values */
generate_random_length(struct rnd_state * rng,unsigned int max_len)901f900fde2SEric Biggers static unsigned int generate_random_length(struct rnd_state *rng,
902f900fde2SEric Biggers 					   unsigned int max_len)
903f900fde2SEric Biggers {
904f900fde2SEric Biggers 	unsigned int len = prandom_u32_below(rng, max_len + 1);
905f900fde2SEric Biggers 
906f900fde2SEric Biggers 	switch (prandom_u32_below(rng, 4)) {
907f2bb770aSEric Biggers 	case 0:
908f2bb770aSEric Biggers 		return len % 64;
909f2bb770aSEric Biggers 	case 1:
910f2bb770aSEric Biggers 		return len % 256;
911f2bb770aSEric Biggers 	case 2:
912f2bb770aSEric Biggers 		return len % 1024;
913f2bb770aSEric Biggers 	default:
914f2bb770aSEric Biggers 		return len;
915f2bb770aSEric Biggers 	}
916f2bb770aSEric Biggers }
917f2bb770aSEric Biggers 
91849763fc6SEric Biggers /* Flip a random bit in the given nonempty data buffer */
flip_random_bit(struct rnd_state * rng,u8 * buf,size_t size)919f900fde2SEric Biggers static void flip_random_bit(struct rnd_state *rng, u8 *buf, size_t size)
92049763fc6SEric Biggers {
92149763fc6SEric Biggers 	size_t bitpos;
92249763fc6SEric Biggers 
923f900fde2SEric Biggers 	bitpos = prandom_u32_below(rng, size * 8);
92449763fc6SEric Biggers 	buf[bitpos / 8] ^= 1 << (bitpos % 8);
92549763fc6SEric Biggers }
92649763fc6SEric Biggers 
92749763fc6SEric Biggers /* Flip a random byte in the given nonempty data buffer */
flip_random_byte(struct rnd_state * rng,u8 * buf,size_t size)928f900fde2SEric Biggers static void flip_random_byte(struct rnd_state *rng, u8 *buf, size_t size)
92949763fc6SEric Biggers {
930f900fde2SEric Biggers 	buf[prandom_u32_below(rng, size)] ^= 0xff;
93149763fc6SEric Biggers }
93249763fc6SEric Biggers 
93349763fc6SEric Biggers /* Sometimes make some random changes to the given nonempty data buffer */
mutate_buffer(struct rnd_state * rng,u8 * buf,size_t size)934f900fde2SEric Biggers static void mutate_buffer(struct rnd_state *rng, u8 *buf, size_t size)
935f2bb770aSEric Biggers {
936f2bb770aSEric Biggers 	size_t num_flips;
937f2bb770aSEric Biggers 	size_t i;
938f2bb770aSEric Biggers 
939f2bb770aSEric Biggers 	/* Sometimes flip some bits */
940f900fde2SEric Biggers 	if (prandom_u32_below(rng, 4) == 0) {
941f900fde2SEric Biggers 		num_flips = min_t(size_t, 1 << prandom_u32_below(rng, 8),
942f900fde2SEric Biggers 				  size * 8);
94349763fc6SEric Biggers 		for (i = 0; i < num_flips; i++)
944f900fde2SEric Biggers 			flip_random_bit(rng, buf, size);
945f2bb770aSEric Biggers 	}
946f2bb770aSEric Biggers 
947f2bb770aSEric Biggers 	/* Sometimes flip some bytes */
948f900fde2SEric Biggers 	if (prandom_u32_below(rng, 4) == 0) {
949f900fde2SEric Biggers 		num_flips = min_t(size_t, 1 << prandom_u32_below(rng, 8), size);
950f2bb770aSEric Biggers 		for (i = 0; i < num_flips; i++)
951f900fde2SEric Biggers 			flip_random_byte(rng, buf, size);
952f2bb770aSEric Biggers 	}
953f2bb770aSEric Biggers }
954f2bb770aSEric Biggers 
955f2bb770aSEric Biggers /* Randomly generate 'count' bytes, but sometimes make them "interesting" */
generate_random_bytes(struct rnd_state * rng,u8 * buf,size_t count)956f900fde2SEric Biggers static void generate_random_bytes(struct rnd_state *rng, u8 *buf, size_t count)
957f2bb770aSEric Biggers {
958f2bb770aSEric Biggers 	u8 b;
959f2bb770aSEric Biggers 	u8 increment;
960f2bb770aSEric Biggers 	size_t i;
961f2bb770aSEric Biggers 
962f2bb770aSEric Biggers 	if (count == 0)
963f2bb770aSEric Biggers 		return;
964f2bb770aSEric Biggers 
965f900fde2SEric Biggers 	switch (prandom_u32_below(rng, 8)) { /* Choose a generation strategy */
966f2bb770aSEric Biggers 	case 0:
967f2bb770aSEric Biggers 	case 1:
968f2bb770aSEric Biggers 		/* All the same byte, plus optional mutations */
969f900fde2SEric Biggers 		switch (prandom_u32_below(rng, 4)) {
970f2bb770aSEric Biggers 		case 0:
971f2bb770aSEric Biggers 			b = 0x00;
972f2bb770aSEric Biggers 			break;
973f2bb770aSEric Biggers 		case 1:
974f2bb770aSEric Biggers 			b = 0xff;
975f2bb770aSEric Biggers 			break;
976f2bb770aSEric Biggers 		default:
977f900fde2SEric Biggers 			b = prandom_u8(rng);
978f2bb770aSEric Biggers 			break;
979f2bb770aSEric Biggers 		}
980f2bb770aSEric Biggers 		memset(buf, b, count);
981f900fde2SEric Biggers 		mutate_buffer(rng, buf, count);
982f2bb770aSEric Biggers 		break;
983f2bb770aSEric Biggers 	case 2:
984f2bb770aSEric Biggers 		/* Ascending or descending bytes, plus optional mutations */
985f900fde2SEric Biggers 		increment = prandom_u8(rng);
986f900fde2SEric Biggers 		b = prandom_u8(rng);
987f2bb770aSEric Biggers 		for (i = 0; i < count; i++, b += increment)
988f2bb770aSEric Biggers 			buf[i] = b;
989f900fde2SEric Biggers 		mutate_buffer(rng, buf, count);
990f2bb770aSEric Biggers 		break;
991f2bb770aSEric Biggers 	default:
992f2bb770aSEric Biggers 		/* Fully random bytes */
993f900fde2SEric Biggers 		prandom_bytes_state(rng, buf, count);
994f2bb770aSEric Biggers 	}
995f2bb770aSEric Biggers }
996f2bb770aSEric Biggers 
generate_random_sgl_divisions(struct rnd_state * rng,struct test_sg_division * divs,size_t max_divs,char * p,char * end,bool gen_flushes,u32 req_flags)997f900fde2SEric Biggers static char *generate_random_sgl_divisions(struct rnd_state *rng,
998f900fde2SEric Biggers 					   struct test_sg_division *divs,
99925f9dddbSEric Biggers 					   size_t max_divs, char *p, char *end,
10006570737cSEric Biggers 					   bool gen_flushes, u32 req_flags)
100125f9dddbSEric Biggers {
100225f9dddbSEric Biggers 	struct test_sg_division *div = divs;
100325f9dddbSEric Biggers 	unsigned int remaining = TEST_SG_TOTAL;
100425f9dddbSEric Biggers 
100525f9dddbSEric Biggers 	do {
100625f9dddbSEric Biggers 		unsigned int this_len;
10076570737cSEric Biggers 		const char *flushtype_str;
100825f9dddbSEric Biggers 
1009f900fde2SEric Biggers 		if (div == &divs[max_divs - 1] || prandom_bool(rng))
101025f9dddbSEric Biggers 			this_len = remaining;
101125f9dddbSEric Biggers 		else
1012f900fde2SEric Biggers 			this_len = prandom_u32_inclusive(rng, 1, remaining);
101325f9dddbSEric Biggers 		div->proportion_of_total = this_len;
101425f9dddbSEric Biggers 
1015f900fde2SEric Biggers 		if (prandom_u32_below(rng, 4) == 0)
1016f900fde2SEric Biggers 			div->offset = prandom_u32_inclusive(rng,
1017f900fde2SEric Biggers 							    PAGE_SIZE - 128,
1018f900fde2SEric Biggers 							    PAGE_SIZE - 1);
1019f900fde2SEric Biggers 		else if (prandom_bool(rng))
1020f900fde2SEric Biggers 			div->offset = prandom_u32_below(rng, 32);
102125f9dddbSEric Biggers 		else
1022f900fde2SEric Biggers 			div->offset = prandom_u32_below(rng, PAGE_SIZE);
1023f900fde2SEric Biggers 		if (prandom_u32_below(rng, 8) == 0)
102425f9dddbSEric Biggers 			div->offset_relative_to_alignmask = true;
102525f9dddbSEric Biggers 
102625f9dddbSEric Biggers 		div->flush_type = FLUSH_TYPE_NONE;
102725f9dddbSEric Biggers 		if (gen_flushes) {
1028f900fde2SEric Biggers 			switch (prandom_u32_below(rng, 4)) {
102925f9dddbSEric Biggers 			case 0:
103025f9dddbSEric Biggers 				div->flush_type = FLUSH_TYPE_REIMPORT;
103125f9dddbSEric Biggers 				break;
103225f9dddbSEric Biggers 			case 1:
103325f9dddbSEric Biggers 				div->flush_type = FLUSH_TYPE_FLUSH;
103425f9dddbSEric Biggers 				break;
103525f9dddbSEric Biggers 			}
103625f9dddbSEric Biggers 		}
103725f9dddbSEric Biggers 
10386570737cSEric Biggers 		if (div->flush_type != FLUSH_TYPE_NONE &&
10396570737cSEric Biggers 		    !(req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) &&
1040f900fde2SEric Biggers 		    prandom_bool(rng))
10416570737cSEric Biggers 			div->nosimd = true;
10426570737cSEric Biggers 
10436570737cSEric Biggers 		switch (div->flush_type) {
10446570737cSEric Biggers 		case FLUSH_TYPE_FLUSH:
10456570737cSEric Biggers 			if (div->nosimd)
10466570737cSEric Biggers 				flushtype_str = "<flush,nosimd>";
10476570737cSEric Biggers 			else
10486570737cSEric Biggers 				flushtype_str = "<flush>";
10496570737cSEric Biggers 			break;
10506570737cSEric Biggers 		case FLUSH_TYPE_REIMPORT:
10516570737cSEric Biggers 			if (div->nosimd)
10526570737cSEric Biggers 				flushtype_str = "<reimport,nosimd>";
10536570737cSEric Biggers 			else
10546570737cSEric Biggers 				flushtype_str = "<reimport>";
10556570737cSEric Biggers 			break;
10566570737cSEric Biggers 		default:
10576570737cSEric Biggers 			flushtype_str = "";
10586570737cSEric Biggers 			break;
10596570737cSEric Biggers 		}
10606570737cSEric Biggers 
106125f9dddbSEric Biggers 		BUILD_BUG_ON(TEST_SG_TOTAL != 10000); /* for "%u.%u%%" */
10626570737cSEric Biggers 		p += scnprintf(p, end - p, "%s%u.%u%%@%s+%u%s", flushtype_str,
106325f9dddbSEric Biggers 			       this_len / 100, this_len % 100,
106425f9dddbSEric Biggers 			       div->offset_relative_to_alignmask ?
106525f9dddbSEric Biggers 					"alignmask" : "",
106625f9dddbSEric Biggers 			       div->offset, this_len == remaining ? "" : ", ");
106725f9dddbSEric Biggers 		remaining -= this_len;
106825f9dddbSEric Biggers 		div++;
106925f9dddbSEric Biggers 	} while (remaining);
107025f9dddbSEric Biggers 
107125f9dddbSEric Biggers 	return p;
107225f9dddbSEric Biggers }
107325f9dddbSEric Biggers 
107425f9dddbSEric Biggers /* Generate a random testvec_config for fuzz testing */
generate_random_testvec_config(struct rnd_state * rng,struct testvec_config * cfg,char * name,size_t max_namelen)1075f900fde2SEric Biggers static void generate_random_testvec_config(struct rnd_state *rng,
1076f900fde2SEric Biggers 					   struct testvec_config *cfg,
107725f9dddbSEric Biggers 					   char *name, size_t max_namelen)
107825f9dddbSEric Biggers {
107925f9dddbSEric Biggers 	char *p = name;
108025f9dddbSEric Biggers 	char * const end = name + max_namelen;
108125f9dddbSEric Biggers 
108225f9dddbSEric Biggers 	memset(cfg, 0, sizeof(*cfg));
108325f9dddbSEric Biggers 
108425f9dddbSEric Biggers 	cfg->name = name;
108525f9dddbSEric Biggers 
108625f9dddbSEric Biggers 	p += scnprintf(p, end - p, "random:");
108725f9dddbSEric Biggers 
1088f900fde2SEric Biggers 	switch (prandom_u32_below(rng, 4)) {
1089f17f9e90SEric Biggers 	case 0:
1090f17f9e90SEric Biggers 	case 1:
1091f17f9e90SEric Biggers 		cfg->inplace_mode = OUT_OF_PLACE;
1092f17f9e90SEric Biggers 		break;
1093f17f9e90SEric Biggers 	case 2:
1094f17f9e90SEric Biggers 		cfg->inplace_mode = INPLACE_ONE_SGLIST;
1095f17f9e90SEric Biggers 		p += scnprintf(p, end - p, " inplace_one_sglist");
1096f17f9e90SEric Biggers 		break;
1097f17f9e90SEric Biggers 	default:
1098f17f9e90SEric Biggers 		cfg->inplace_mode = INPLACE_TWO_SGLISTS;
1099f17f9e90SEric Biggers 		p += scnprintf(p, end - p, " inplace_two_sglists");
1100f17f9e90SEric Biggers 		break;
110125f9dddbSEric Biggers 	}
110225f9dddbSEric Biggers 
1103f900fde2SEric Biggers 	if (prandom_bool(rng)) {
110425f9dddbSEric Biggers 		cfg->req_flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
110525f9dddbSEric Biggers 		p += scnprintf(p, end - p, " may_sleep");
110625f9dddbSEric Biggers 	}
110725f9dddbSEric Biggers 
1108f900fde2SEric Biggers 	switch (prandom_u32_below(rng, 4)) {
110925f9dddbSEric Biggers 	case 0:
111025f9dddbSEric Biggers 		cfg->finalization_type = FINALIZATION_TYPE_FINAL;
111125f9dddbSEric Biggers 		p += scnprintf(p, end - p, " use_final");
111225f9dddbSEric Biggers 		break;
111325f9dddbSEric Biggers 	case 1:
111425f9dddbSEric Biggers 		cfg->finalization_type = FINALIZATION_TYPE_FINUP;
111525f9dddbSEric Biggers 		p += scnprintf(p, end - p, " use_finup");
111625f9dddbSEric Biggers 		break;
111725f9dddbSEric Biggers 	default:
111825f9dddbSEric Biggers 		cfg->finalization_type = FINALIZATION_TYPE_DIGEST;
111925f9dddbSEric Biggers 		p += scnprintf(p, end - p, " use_digest");
112025f9dddbSEric Biggers 		break;
112125f9dddbSEric Biggers 	}
112225f9dddbSEric Biggers 
1123f900fde2SEric Biggers 	if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) && prandom_bool(rng)) {
11246570737cSEric Biggers 		cfg->nosimd = true;
11256570737cSEric Biggers 		p += scnprintf(p, end - p, " nosimd");
11266570737cSEric Biggers 	}
11276570737cSEric Biggers 
112825f9dddbSEric Biggers 	p += scnprintf(p, end - p, " src_divs=[");
1129f900fde2SEric Biggers 	p = generate_random_sgl_divisions(rng, cfg->src_divs,
113025f9dddbSEric Biggers 					  ARRAY_SIZE(cfg->src_divs), p, end,
113125f9dddbSEric Biggers 					  (cfg->finalization_type !=
11326570737cSEric Biggers 					   FINALIZATION_TYPE_DIGEST),
11336570737cSEric Biggers 					  cfg->req_flags);
113425f9dddbSEric Biggers 	p += scnprintf(p, end - p, "]");
113525f9dddbSEric Biggers 
1136f900fde2SEric Biggers 	if (cfg->inplace_mode == OUT_OF_PLACE && prandom_bool(rng)) {
113725f9dddbSEric Biggers 		p += scnprintf(p, end - p, " dst_divs=[");
1138f900fde2SEric Biggers 		p = generate_random_sgl_divisions(rng, cfg->dst_divs,
113925f9dddbSEric Biggers 						  ARRAY_SIZE(cfg->dst_divs),
11406570737cSEric Biggers 						  p, end, false,
11416570737cSEric Biggers 						  cfg->req_flags);
114225f9dddbSEric Biggers 		p += scnprintf(p, end - p, "]");
114325f9dddbSEric Biggers 	}
114425f9dddbSEric Biggers 
1145f900fde2SEric Biggers 	if (prandom_bool(rng)) {
1146f900fde2SEric Biggers 		cfg->iv_offset = prandom_u32_inclusive(rng, 1,
1147f900fde2SEric Biggers 						       MAX_ALGAPI_ALIGNMASK);
114825f9dddbSEric Biggers 		p += scnprintf(p, end - p, " iv_offset=%u", cfg->iv_offset);
114925f9dddbSEric Biggers 	}
115025f9dddbSEric Biggers 
1151f900fde2SEric Biggers 	if (prandom_bool(rng)) {
1152f900fde2SEric Biggers 		cfg->key_offset = prandom_u32_inclusive(rng, 1,
1153f900fde2SEric Biggers 							MAX_ALGAPI_ALIGNMASK);
1154fd8c37c7SEric Biggers 		p += scnprintf(p, end - p, " key_offset=%u", cfg->key_offset);
1155fd8c37c7SEric Biggers 	}
1156fd8c37c7SEric Biggers 
115725f9dddbSEric Biggers 	WARN_ON_ONCE(!valid_testvec_config(cfg));
115825f9dddbSEric Biggers }
1159b55e1a39SEric Biggers 
crypto_disable_simd_for_test(void)1160b55e1a39SEric Biggers static void crypto_disable_simd_for_test(void)
1161b55e1a39SEric Biggers {
116282e269adSSebastian Andrzej Siewior 	migrate_disable();
1163b55e1a39SEric Biggers 	__this_cpu_write(crypto_simd_disabled_for_test, true);
1164b55e1a39SEric Biggers }
1165b55e1a39SEric Biggers 
crypto_reenable_simd_for_test(void)1166b55e1a39SEric Biggers static void crypto_reenable_simd_for_test(void)
1167b55e1a39SEric Biggers {
1168b55e1a39SEric Biggers 	__this_cpu_write(crypto_simd_disabled_for_test, false);
116982e269adSSebastian Andrzej Siewior 	migrate_enable();
1170b55e1a39SEric Biggers }
1171f2bb770aSEric Biggers 
1172f2bb770aSEric Biggers /*
1173f2bb770aSEric Biggers  * Given an algorithm name, build the name of the generic implementation of that
1174f2bb770aSEric Biggers  * algorithm, assuming the usual naming convention.  Specifically, this appends
1175f2bb770aSEric Biggers  * "-generic" to every part of the name that is not a template name.  Examples:
1176f2bb770aSEric Biggers  *
1177f2bb770aSEric Biggers  *	aes => aes-generic
1178f2bb770aSEric Biggers  *	cbc(aes) => cbc(aes-generic)
1179f2bb770aSEric Biggers  *	cts(cbc(aes)) => cts(cbc(aes-generic))
1180f2bb770aSEric Biggers  *	rfc7539(chacha20,poly1305) => rfc7539(chacha20-generic,poly1305-generic)
1181f2bb770aSEric Biggers  *
1182f2bb770aSEric Biggers  * Return: 0 on success, or -ENAMETOOLONG if the generic name would be too long
1183f2bb770aSEric Biggers  */
build_generic_driver_name(const char * algname,char driver_name[CRYPTO_MAX_ALG_NAME])1184f2bb770aSEric Biggers static int build_generic_driver_name(const char *algname,
1185f2bb770aSEric Biggers 				     char driver_name[CRYPTO_MAX_ALG_NAME])
1186f2bb770aSEric Biggers {
1187f2bb770aSEric Biggers 	const char *in = algname;
1188f2bb770aSEric Biggers 	char *out = driver_name;
1189f2bb770aSEric Biggers 	size_t len = strlen(algname);
1190f2bb770aSEric Biggers 
1191f2bb770aSEric Biggers 	if (len >= CRYPTO_MAX_ALG_NAME)
1192f2bb770aSEric Biggers 		goto too_long;
1193f2bb770aSEric Biggers 	do {
1194f2bb770aSEric Biggers 		const char *in_saved = in;
1195f2bb770aSEric Biggers 
1196f2bb770aSEric Biggers 		while (*in && *in != '(' && *in != ')' && *in != ',')
1197f2bb770aSEric Biggers 			*out++ = *in++;
1198f2bb770aSEric Biggers 		if (*in != '(' && in > in_saved) {
1199f2bb770aSEric Biggers 			len += 8;
1200f2bb770aSEric Biggers 			if (len >= CRYPTO_MAX_ALG_NAME)
1201f2bb770aSEric Biggers 				goto too_long;
1202f2bb770aSEric Biggers 			memcpy(out, "-generic", 8);
1203f2bb770aSEric Biggers 			out += 8;
1204f2bb770aSEric Biggers 		}
1205f2bb770aSEric Biggers 	} while ((*out++ = *in++) != '\0');
1206f2bb770aSEric Biggers 	return 0;
1207f2bb770aSEric Biggers 
1208f2bb770aSEric Biggers too_long:
1209f2bb770aSEric Biggers 	pr_err("alg: generic driver name for \"%s\" would be too long\n",
1210f2bb770aSEric Biggers 	       algname);
1211f2bb770aSEric Biggers 	return -ENAMETOOLONG;
1212f2bb770aSEric Biggers }
1213b55e1a39SEric Biggers #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
crypto_disable_simd_for_test(void)1214b55e1a39SEric Biggers static void crypto_disable_simd_for_test(void)
1215b55e1a39SEric Biggers {
1216b55e1a39SEric Biggers }
1217b55e1a39SEric Biggers 
crypto_reenable_simd_for_test(void)1218b55e1a39SEric Biggers static void crypto_reenable_simd_for_test(void)
1219b55e1a39SEric Biggers {
1220b55e1a39SEric Biggers }
1221b55e1a39SEric Biggers #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
122225f9dddbSEric Biggers 
build_hash_sglist(struct test_sglist * tsgl,const struct hash_testvec * vec,const struct testvec_config * cfg,unsigned int alignmask,const struct test_sg_division * divs[XBUFSIZE])1223d8ea98aaSEric Biggers static int build_hash_sglist(struct test_sglist *tsgl,
1224d8ea98aaSEric Biggers 			     const struct hash_testvec *vec,
1225d8ea98aaSEric Biggers 			     const struct testvec_config *cfg,
1226d8ea98aaSEric Biggers 			     unsigned int alignmask,
1227d8ea98aaSEric Biggers 			     const struct test_sg_division *divs[XBUFSIZE])
1228d8ea98aaSEric Biggers {
1229d8ea98aaSEric Biggers 	struct kvec kv;
1230d8ea98aaSEric Biggers 	struct iov_iter input;
1231d8ea98aaSEric Biggers 
1232d8ea98aaSEric Biggers 	kv.iov_base = (void *)vec->plaintext;
1233d8ea98aaSEric Biggers 	kv.iov_len = vec->psize;
1234de4eda9dSAl Viro 	iov_iter_kvec(&input, ITER_SOURCE, &kv, 1, vec->psize);
1235d8ea98aaSEric Biggers 	return build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize,
1236d8ea98aaSEric Biggers 				 &input, divs);
1237d8ea98aaSEric Biggers }
1238d8ea98aaSEric Biggers 
check_hash_result(const char * type,const u8 * result,unsigned int digestsize,const struct hash_testvec * vec,const char * vec_name,const char * driver,const struct testvec_config * cfg)1239d8ea98aaSEric Biggers static int check_hash_result(const char *type,
1240d8ea98aaSEric Biggers 			     const u8 *result, unsigned int digestsize,
1241d8ea98aaSEric Biggers 			     const struct hash_testvec *vec,
1242d8ea98aaSEric Biggers 			     const char *vec_name,
1243d8ea98aaSEric Biggers 			     const char *driver,
1244d8ea98aaSEric Biggers 			     const struct testvec_config *cfg)
1245d8ea98aaSEric Biggers {
1246d8ea98aaSEric Biggers 	if (memcmp(result, vec->digest, digestsize) != 0) {
1247d8ea98aaSEric Biggers 		pr_err("alg: %s: %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
1248d8ea98aaSEric Biggers 		       type, driver, vec_name, cfg->name);
1249d8ea98aaSEric Biggers 		return -EINVAL;
1250d8ea98aaSEric Biggers 	}
1251d8ea98aaSEric Biggers 	if (!testmgr_is_poison(&result[digestsize], TESTMGR_POISON_LEN)) {
1252d8ea98aaSEric Biggers 		pr_err("alg: %s: %s overran result buffer on test vector %s, cfg=\"%s\"\n",
1253d8ea98aaSEric Biggers 		       type, driver, vec_name, cfg->name);
1254d8ea98aaSEric Biggers 		return -EOVERFLOW;
1255d8ea98aaSEric Biggers 	}
1256d8ea98aaSEric Biggers 	return 0;
1257d8ea98aaSEric Biggers }
1258d8ea98aaSEric Biggers 
check_shash_op(const char * op,int err,const char * driver,const char * vec_name,const struct testvec_config * cfg)1259d8ea98aaSEric Biggers static inline int check_shash_op(const char *op, int err,
1260d8ea98aaSEric Biggers 				 const char *driver, const char *vec_name,
1261d8ea98aaSEric Biggers 				 const struct testvec_config *cfg)
1262d8ea98aaSEric Biggers {
1263d8ea98aaSEric Biggers 	if (err)
1264d8ea98aaSEric Biggers 		pr_err("alg: shash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
1265d8ea98aaSEric Biggers 		       driver, op, err, vec_name, cfg->name);
1266d8ea98aaSEric Biggers 	return err;
1267d8ea98aaSEric Biggers }
1268d8ea98aaSEric Biggers 
1269d8ea98aaSEric Biggers /* Test one hash test vector in one configuration, using the shash API */
test_shash_vec_cfg(const struct hash_testvec * vec,const char * vec_name,const struct testvec_config * cfg,struct shash_desc * desc,struct test_sglist * tsgl,u8 * hashstate)127079cafe9aSEric Biggers static int test_shash_vec_cfg(const struct hash_testvec *vec,
1271d8ea98aaSEric Biggers 			      const char *vec_name,
1272d8ea98aaSEric Biggers 			      const struct testvec_config *cfg,
1273d8ea98aaSEric Biggers 			      struct shash_desc *desc,
1274d8ea98aaSEric Biggers 			      struct test_sglist *tsgl,
1275d8ea98aaSEric Biggers 			      u8 *hashstate)
1276d8ea98aaSEric Biggers {
1277d8ea98aaSEric Biggers 	struct crypto_shash *tfm = desc->tfm;
1278d8ea98aaSEric Biggers 	const unsigned int alignmask = crypto_shash_alignmask(tfm);
1279d8ea98aaSEric Biggers 	const unsigned int digestsize = crypto_shash_digestsize(tfm);
1280d8ea98aaSEric Biggers 	const unsigned int statesize = crypto_shash_statesize(tfm);
128179cafe9aSEric Biggers 	const char *driver = crypto_shash_driver_name(tfm);
1282d8ea98aaSEric Biggers 	const struct test_sg_division *divs[XBUFSIZE];
1283d8ea98aaSEric Biggers 	unsigned int i;
1284d8ea98aaSEric Biggers 	u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN];
1285d8ea98aaSEric Biggers 	int err;
1286d8ea98aaSEric Biggers 
1287d8ea98aaSEric Biggers 	/* Set the key, if specified */
1288d8ea98aaSEric Biggers 	if (vec->ksize) {
1289fd8c37c7SEric Biggers 		err = do_setkey(crypto_shash_setkey, tfm, vec->key, vec->ksize,
1290fd8c37c7SEric Biggers 				cfg, alignmask);
1291d8ea98aaSEric Biggers 		if (err) {
1292d8ea98aaSEric Biggers 			if (err == vec->setkey_error)
1293d8ea98aaSEric Biggers 				return 0;
1294d8ea98aaSEric Biggers 			pr_err("alg: shash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
1295d8ea98aaSEric Biggers 			       driver, vec_name, vec->setkey_error, err,
1296d8ea98aaSEric Biggers 			       crypto_shash_get_flags(tfm));
1297d8ea98aaSEric Biggers 			return err;
1298d8ea98aaSEric Biggers 		}
1299d8ea98aaSEric Biggers 		if (vec->setkey_error) {
1300d8ea98aaSEric Biggers 			pr_err("alg: shash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
1301d8ea98aaSEric Biggers 			       driver, vec_name, vec->setkey_error);
1302d8ea98aaSEric Biggers 			return -EINVAL;
1303d8ea98aaSEric Biggers 		}
1304d8ea98aaSEric Biggers 	}
1305d8ea98aaSEric Biggers 
1306d8ea98aaSEric Biggers 	/* Build the scatterlist for the source data */
1307d8ea98aaSEric Biggers 	err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
1308d8ea98aaSEric Biggers 	if (err) {
1309d8ea98aaSEric Biggers 		pr_err("alg: shash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
1310d8ea98aaSEric Biggers 		       driver, vec_name, cfg->name);
1311d8ea98aaSEric Biggers 		return err;
1312d8ea98aaSEric Biggers 	}
1313d8ea98aaSEric Biggers 
1314d8ea98aaSEric Biggers 	/* Do the actual hashing */
1315d8ea98aaSEric Biggers 
1316d8ea98aaSEric Biggers 	testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm));
1317d8ea98aaSEric Biggers 	testmgr_poison(result, digestsize + TESTMGR_POISON_LEN);
1318d8ea98aaSEric Biggers 
1319d8ea98aaSEric Biggers 	if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST ||
1320d8ea98aaSEric Biggers 	    vec->digest_error) {
1321d8ea98aaSEric Biggers 		/* Just using digest() */
1322d8ea98aaSEric Biggers 		if (tsgl->nents != 1)
1323d8ea98aaSEric Biggers 			return 0;
1324d8ea98aaSEric Biggers 		if (cfg->nosimd)
1325d8ea98aaSEric Biggers 			crypto_disable_simd_for_test();
1326e40ff6f3SKai Ye 		err = crypto_shash_digest(desc, sg_virt(&tsgl->sgl[0]),
1327d8ea98aaSEric Biggers 					  tsgl->sgl[0].length, result);
1328d8ea98aaSEric Biggers 		if (cfg->nosimd)
1329d8ea98aaSEric Biggers 			crypto_reenable_simd_for_test();
1330d8ea98aaSEric Biggers 		if (err) {
1331d8ea98aaSEric Biggers 			if (err == vec->digest_error)
1332d8ea98aaSEric Biggers 				return 0;
1333d8ea98aaSEric Biggers 			pr_err("alg: shash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
1334d8ea98aaSEric Biggers 			       driver, vec_name, vec->digest_error, err,
1335d8ea98aaSEric Biggers 			       cfg->name);
1336d8ea98aaSEric Biggers 			return err;
1337d8ea98aaSEric Biggers 		}
1338d8ea98aaSEric Biggers 		if (vec->digest_error) {
1339d8ea98aaSEric Biggers 			pr_err("alg: shash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
1340d8ea98aaSEric Biggers 			       driver, vec_name, vec->digest_error, cfg->name);
1341d8ea98aaSEric Biggers 			return -EINVAL;
1342d8ea98aaSEric Biggers 		}
1343d8ea98aaSEric Biggers 		goto result_ready;
1344d8ea98aaSEric Biggers 	}
1345d8ea98aaSEric Biggers 
1346d8ea98aaSEric Biggers 	/* Using init(), zero or more update(), then final() or finup() */
1347d8ea98aaSEric Biggers 
1348d8ea98aaSEric Biggers 	if (cfg->nosimd)
1349d8ea98aaSEric Biggers 		crypto_disable_simd_for_test();
1350d8ea98aaSEric Biggers 	err = crypto_shash_init(desc);
1351d8ea98aaSEric Biggers 	if (cfg->nosimd)
1352d8ea98aaSEric Biggers 		crypto_reenable_simd_for_test();
1353d8ea98aaSEric Biggers 	err = check_shash_op("init", err, driver, vec_name, cfg);
1354d8ea98aaSEric Biggers 	if (err)
1355d8ea98aaSEric Biggers 		return err;
1356d8ea98aaSEric Biggers 
1357d8ea98aaSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
1358d8ea98aaSEric Biggers 		if (i + 1 == tsgl->nents &&
1359d8ea98aaSEric Biggers 		    cfg->finalization_type == FINALIZATION_TYPE_FINUP) {
1360d8ea98aaSEric Biggers 			if (divs[i]->nosimd)
1361d8ea98aaSEric Biggers 				crypto_disable_simd_for_test();
1362e40ff6f3SKai Ye 			err = crypto_shash_finup(desc, sg_virt(&tsgl->sgl[i]),
1363d8ea98aaSEric Biggers 						 tsgl->sgl[i].length, result);
1364d8ea98aaSEric Biggers 			if (divs[i]->nosimd)
1365d8ea98aaSEric Biggers 				crypto_reenable_simd_for_test();
1366d8ea98aaSEric Biggers 			err = check_shash_op("finup", err, driver, vec_name,
1367d8ea98aaSEric Biggers 					     cfg);
1368d8ea98aaSEric Biggers 			if (err)
1369d8ea98aaSEric Biggers 				return err;
1370d8ea98aaSEric Biggers 			goto result_ready;
1371d8ea98aaSEric Biggers 		}
1372d8ea98aaSEric Biggers 		if (divs[i]->nosimd)
1373d8ea98aaSEric Biggers 			crypto_disable_simd_for_test();
1374e40ff6f3SKai Ye 		err = crypto_shash_update(desc, sg_virt(&tsgl->sgl[i]),
1375d8ea98aaSEric Biggers 					  tsgl->sgl[i].length);
1376d8ea98aaSEric Biggers 		if (divs[i]->nosimd)
1377d8ea98aaSEric Biggers 			crypto_reenable_simd_for_test();
1378d8ea98aaSEric Biggers 		err = check_shash_op("update", err, driver, vec_name, cfg);
1379d8ea98aaSEric Biggers 		if (err)
1380d8ea98aaSEric Biggers 			return err;
1381d8ea98aaSEric Biggers 		if (divs[i]->flush_type == FLUSH_TYPE_REIMPORT) {
1382d8ea98aaSEric Biggers 			/* Test ->export() and ->import() */
1383d8ea98aaSEric Biggers 			testmgr_poison(hashstate + statesize,
1384d8ea98aaSEric Biggers 				       TESTMGR_POISON_LEN);
1385d8ea98aaSEric Biggers 			err = crypto_shash_export(desc, hashstate);
1386d8ea98aaSEric Biggers 			err = check_shash_op("export", err, driver, vec_name,
1387d8ea98aaSEric Biggers 					     cfg);
1388d8ea98aaSEric Biggers 			if (err)
1389d8ea98aaSEric Biggers 				return err;
1390d8ea98aaSEric Biggers 			if (!testmgr_is_poison(hashstate + statesize,
1391d8ea98aaSEric Biggers 					       TESTMGR_POISON_LEN)) {
1392d8ea98aaSEric Biggers 				pr_err("alg: shash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
1393d8ea98aaSEric Biggers 				       driver, vec_name, cfg->name);
1394d8ea98aaSEric Biggers 				return -EOVERFLOW;
1395d8ea98aaSEric Biggers 			}
1396d8ea98aaSEric Biggers 			testmgr_poison(desc->__ctx, crypto_shash_descsize(tfm));
1397d8ea98aaSEric Biggers 			err = crypto_shash_import(desc, hashstate);
1398d8ea98aaSEric Biggers 			err = check_shash_op("import", err, driver, vec_name,
1399d8ea98aaSEric Biggers 					     cfg);
1400d8ea98aaSEric Biggers 			if (err)
1401d8ea98aaSEric Biggers 				return err;
1402d8ea98aaSEric Biggers 		}
1403d8ea98aaSEric Biggers 	}
1404d8ea98aaSEric Biggers 
1405d8ea98aaSEric Biggers 	if (cfg->nosimd)
1406d8ea98aaSEric Biggers 		crypto_disable_simd_for_test();
1407d8ea98aaSEric Biggers 	err = crypto_shash_final(desc, result);
1408d8ea98aaSEric Biggers 	if (cfg->nosimd)
1409d8ea98aaSEric Biggers 		crypto_reenable_simd_for_test();
1410d8ea98aaSEric Biggers 	err = check_shash_op("final", err, driver, vec_name, cfg);
1411d8ea98aaSEric Biggers 	if (err)
1412d8ea98aaSEric Biggers 		return err;
1413d8ea98aaSEric Biggers result_ready:
1414d8ea98aaSEric Biggers 	return check_hash_result("shash", result, digestsize, vec, vec_name,
1415d8ea98aaSEric Biggers 				 driver, cfg);
1416d8ea98aaSEric Biggers }
1417d8ea98aaSEric Biggers 
do_ahash_op(int (* op)(struct ahash_request * req),struct ahash_request * req,struct crypto_wait * wait,bool nosimd)14186570737cSEric Biggers static int do_ahash_op(int (*op)(struct ahash_request *req),
14196570737cSEric Biggers 		       struct ahash_request *req,
14206570737cSEric Biggers 		       struct crypto_wait *wait, bool nosimd)
14216570737cSEric Biggers {
14226570737cSEric Biggers 	int err;
14236570737cSEric Biggers 
14246570737cSEric Biggers 	if (nosimd)
14256570737cSEric Biggers 		crypto_disable_simd_for_test();
14266570737cSEric Biggers 
14276570737cSEric Biggers 	err = op(req);
14286570737cSEric Biggers 
14296570737cSEric Biggers 	if (nosimd)
14306570737cSEric Biggers 		crypto_reenable_simd_for_test();
14316570737cSEric Biggers 
14326570737cSEric Biggers 	return crypto_wait_req(err, wait);
14336570737cSEric Biggers }
14346570737cSEric Biggers 
check_nonfinal_ahash_op(const char * op,int err,u8 * result,unsigned int digestsize,const char * driver,const char * vec_name,const struct testvec_config * cfg)1435d8ea98aaSEric Biggers static int check_nonfinal_ahash_op(const char *op, int err,
14364cc2dcf9SEric Biggers 				   u8 *result, unsigned int digestsize,
1437951d1332SEric Biggers 				   const char *driver, const char *vec_name,
14384cc2dcf9SEric Biggers 				   const struct testvec_config *cfg)
1439466d7b9fSKamil Konieczny {
14404cc2dcf9SEric Biggers 	if (err) {
1441d8ea98aaSEric Biggers 		pr_err("alg: ahash: %s %s() failed with err %d on test vector %s, cfg=\"%s\"\n",
1442951d1332SEric Biggers 		       driver, op, err, vec_name, cfg->name);
14434cc2dcf9SEric Biggers 		return err;
14444cc2dcf9SEric Biggers 	}
14454cc2dcf9SEric Biggers 	if (!testmgr_is_poison(result, digestsize)) {
1446d8ea98aaSEric Biggers 		pr_err("alg: ahash: %s %s() used result buffer on test vector %s, cfg=\"%s\"\n",
1447951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
1448466d7b9fSKamil Konieczny 		return -EINVAL;
1449466d7b9fSKamil Konieczny 	}
1450466d7b9fSKamil Konieczny 	return 0;
1451466d7b9fSKamil Konieczny }
1452466d7b9fSKamil Konieczny 
1453d8ea98aaSEric Biggers /* Test one hash test vector in one configuration, using the ahash API */
test_ahash_vec_cfg(const struct hash_testvec * vec,const char * vec_name,const struct testvec_config * cfg,struct ahash_request * req,struct test_sglist * tsgl,u8 * hashstate)145479cafe9aSEric Biggers static int test_ahash_vec_cfg(const struct hash_testvec *vec,
1455951d1332SEric Biggers 			      const char *vec_name,
14564cc2dcf9SEric Biggers 			      const struct testvec_config *cfg,
14574cc2dcf9SEric Biggers 			      struct ahash_request *req,
14584cc2dcf9SEric Biggers 			      struct test_sglist *tsgl,
14594cc2dcf9SEric Biggers 			      u8 *hashstate)
1460018ba95cSWang, Rui Y {
14614cc2dcf9SEric Biggers 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
14624cc2dcf9SEric Biggers 	const unsigned int alignmask = crypto_ahash_alignmask(tfm);
14634cc2dcf9SEric Biggers 	const unsigned int digestsize = crypto_ahash_digestsize(tfm);
14644cc2dcf9SEric Biggers 	const unsigned int statesize = crypto_ahash_statesize(tfm);
146579cafe9aSEric Biggers 	const char *driver = crypto_ahash_driver_name(tfm);
14664cc2dcf9SEric Biggers 	const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags;
14674cc2dcf9SEric Biggers 	const struct test_sg_division *divs[XBUFSIZE];
14684cc2dcf9SEric Biggers 	DECLARE_CRYPTO_WAIT(wait);
14694cc2dcf9SEric Biggers 	unsigned int i;
14704cc2dcf9SEric Biggers 	struct scatterlist *pending_sgl;
14714cc2dcf9SEric Biggers 	unsigned int pending_len;
14724cc2dcf9SEric Biggers 	u8 result[HASH_MAX_DIGESTSIZE + TESTMGR_POISON_LEN];
14734cc2dcf9SEric Biggers 	int err;
1474018ba95cSWang, Rui Y 
14754cc2dcf9SEric Biggers 	/* Set the key, if specified */
14764cc2dcf9SEric Biggers 	if (vec->ksize) {
1477fd8c37c7SEric Biggers 		err = do_setkey(crypto_ahash_setkey, tfm, vec->key, vec->ksize,
1478fd8c37c7SEric Biggers 				cfg, alignmask);
14794cc2dcf9SEric Biggers 		if (err) {
14805283a8eeSEric Biggers 			if (err == vec->setkey_error)
14815283a8eeSEric Biggers 				return 0;
1482d8ea98aaSEric Biggers 			pr_err("alg: ahash: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
1483951d1332SEric Biggers 			       driver, vec_name, vec->setkey_error, err,
14844cc2dcf9SEric Biggers 			       crypto_ahash_get_flags(tfm));
14854cc2dcf9SEric Biggers 			return err;
1486da7f033dSHerbert Xu 		}
14875283a8eeSEric Biggers 		if (vec->setkey_error) {
1488d8ea98aaSEric Biggers 			pr_err("alg: ahash: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
1489951d1332SEric Biggers 			       driver, vec_name, vec->setkey_error);
14905283a8eeSEric Biggers 			return -EINVAL;
14915283a8eeSEric Biggers 		}
1492da7f033dSHerbert Xu 	}
1493da7f033dSHerbert Xu 
14944cc2dcf9SEric Biggers 	/* Build the scatterlist for the source data */
1495d8ea98aaSEric Biggers 	err = build_hash_sglist(tsgl, vec, cfg, alignmask, divs);
14964cc2dcf9SEric Biggers 	if (err) {
1497d8ea98aaSEric Biggers 		pr_err("alg: ahash: %s: error preparing scatterlist for test vector %s, cfg=\"%s\"\n",
1498951d1332SEric Biggers 		       driver, vec_name, cfg->name);
14994cc2dcf9SEric Biggers 		return err;
1500a8f1a052SDavid S. Miller 	}
1501da7f033dSHerbert Xu 
15024cc2dcf9SEric Biggers 	/* Do the actual hashing */
1503da7f033dSHerbert Xu 
15044cc2dcf9SEric Biggers 	testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
15054cc2dcf9SEric Biggers 	testmgr_poison(result, digestsize + TESTMGR_POISON_LEN);
150676715095SGilad Ben-Yossef 
15075283a8eeSEric Biggers 	if (cfg->finalization_type == FINALIZATION_TYPE_DIGEST ||
15085283a8eeSEric Biggers 	    vec->digest_error) {
15094cc2dcf9SEric Biggers 		/* Just using digest() */
15104cc2dcf9SEric Biggers 		ahash_request_set_callback(req, req_flags, crypto_req_done,
15117f397136SGilad Ben-Yossef 					   &wait);
15124cc2dcf9SEric Biggers 		ahash_request_set_crypt(req, tsgl->sgl, result, vec->psize);
15136570737cSEric Biggers 		err = do_ahash_op(crypto_ahash_digest, req, &wait, cfg->nosimd);
15144cc2dcf9SEric Biggers 		if (err) {
15155283a8eeSEric Biggers 			if (err == vec->digest_error)
15165283a8eeSEric Biggers 				return 0;
1517d8ea98aaSEric Biggers 			pr_err("alg: ahash: %s digest() failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
1518951d1332SEric Biggers 			       driver, vec_name, vec->digest_error, err,
15195283a8eeSEric Biggers 			       cfg->name);
15204cc2dcf9SEric Biggers 			return err;
1521018ba95cSWang, Rui Y 		}
15225283a8eeSEric Biggers 		if (vec->digest_error) {
1523d8ea98aaSEric Biggers 			pr_err("alg: ahash: %s digest() unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
1524951d1332SEric Biggers 			       driver, vec_name, vec->digest_error, cfg->name);
15255283a8eeSEric Biggers 			return -EINVAL;
15265283a8eeSEric Biggers 		}
15274cc2dcf9SEric Biggers 		goto result_ready;
1528018ba95cSWang, Rui Y 	}
15294cc2dcf9SEric Biggers 
15304cc2dcf9SEric Biggers 	/* Using init(), zero or more update(), then final() or finup() */
15314cc2dcf9SEric Biggers 
15324cc2dcf9SEric Biggers 	ahash_request_set_callback(req, req_flags, crypto_req_done, &wait);
15334cc2dcf9SEric Biggers 	ahash_request_set_crypt(req, NULL, result, 0);
15346570737cSEric Biggers 	err = do_ahash_op(crypto_ahash_init, req, &wait, cfg->nosimd);
1535d8ea98aaSEric Biggers 	err = check_nonfinal_ahash_op("init", err, result, digestsize,
1536951d1332SEric Biggers 				      driver, vec_name, cfg);
15374cc2dcf9SEric Biggers 	if (err)
15384cc2dcf9SEric Biggers 		return err;
15394cc2dcf9SEric Biggers 
15404cc2dcf9SEric Biggers 	pending_sgl = NULL;
15414cc2dcf9SEric Biggers 	pending_len = 0;
15424cc2dcf9SEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
15434cc2dcf9SEric Biggers 		if (divs[i]->flush_type != FLUSH_TYPE_NONE &&
15444cc2dcf9SEric Biggers 		    pending_sgl != NULL) {
15454cc2dcf9SEric Biggers 			/* update() with the pending data */
15464cc2dcf9SEric Biggers 			ahash_request_set_callback(req, req_flags,
15474cc2dcf9SEric Biggers 						   crypto_req_done, &wait);
15484cc2dcf9SEric Biggers 			ahash_request_set_crypt(req, pending_sgl, result,
15494cc2dcf9SEric Biggers 						pending_len);
15506570737cSEric Biggers 			err = do_ahash_op(crypto_ahash_update, req, &wait,
15516570737cSEric Biggers 					  divs[i]->nosimd);
1552d8ea98aaSEric Biggers 			err = check_nonfinal_ahash_op("update", err,
15534cc2dcf9SEric Biggers 						      result, digestsize,
1554951d1332SEric Biggers 						      driver, vec_name, cfg);
15554cc2dcf9SEric Biggers 			if (err)
15564cc2dcf9SEric Biggers 				return err;
15574cc2dcf9SEric Biggers 			pending_sgl = NULL;
15584cc2dcf9SEric Biggers 			pending_len = 0;
1559018ba95cSWang, Rui Y 		}
15604cc2dcf9SEric Biggers 		if (divs[i]->flush_type == FLUSH_TYPE_REIMPORT) {
15614cc2dcf9SEric Biggers 			/* Test ->export() and ->import() */
15624cc2dcf9SEric Biggers 			testmgr_poison(hashstate + statesize,
15634cc2dcf9SEric Biggers 				       TESTMGR_POISON_LEN);
15644cc2dcf9SEric Biggers 			err = crypto_ahash_export(req, hashstate);
1565d8ea98aaSEric Biggers 			err = check_nonfinal_ahash_op("export", err,
15664cc2dcf9SEric Biggers 						      result, digestsize,
1567951d1332SEric Biggers 						      driver, vec_name, cfg);
15684cc2dcf9SEric Biggers 			if (err)
15694cc2dcf9SEric Biggers 				return err;
15704cc2dcf9SEric Biggers 			if (!testmgr_is_poison(hashstate + statesize,
15714cc2dcf9SEric Biggers 					       TESTMGR_POISON_LEN)) {
1572d8ea98aaSEric Biggers 				pr_err("alg: ahash: %s export() overran state buffer on test vector %s, cfg=\"%s\"\n",
1573951d1332SEric Biggers 				       driver, vec_name, cfg->name);
15744cc2dcf9SEric Biggers 				return -EOVERFLOW;
15754cc2dcf9SEric Biggers 			}
15764cc2dcf9SEric Biggers 
15774cc2dcf9SEric Biggers 			testmgr_poison(req->__ctx, crypto_ahash_reqsize(tfm));
15784cc2dcf9SEric Biggers 			err = crypto_ahash_import(req, hashstate);
1579d8ea98aaSEric Biggers 			err = check_nonfinal_ahash_op("import", err,
15804cc2dcf9SEric Biggers 						      result, digestsize,
1581951d1332SEric Biggers 						      driver, vec_name, cfg);
15824cc2dcf9SEric Biggers 			if (err)
15834cc2dcf9SEric Biggers 				return err;
15844cc2dcf9SEric Biggers 		}
15854cc2dcf9SEric Biggers 		if (pending_sgl == NULL)
15864cc2dcf9SEric Biggers 			pending_sgl = &tsgl->sgl[i];
15874cc2dcf9SEric Biggers 		pending_len += tsgl->sgl[i].length;
15884cc2dcf9SEric Biggers 	}
15894cc2dcf9SEric Biggers 
15904cc2dcf9SEric Biggers 	ahash_request_set_callback(req, req_flags, crypto_req_done, &wait);
15914cc2dcf9SEric Biggers 	ahash_request_set_crypt(req, pending_sgl, result, pending_len);
15924cc2dcf9SEric Biggers 	if (cfg->finalization_type == FINALIZATION_TYPE_FINAL) {
15934cc2dcf9SEric Biggers 		/* finish with update() and final() */
15946570737cSEric Biggers 		err = do_ahash_op(crypto_ahash_update, req, &wait, cfg->nosimd);
1595d8ea98aaSEric Biggers 		err = check_nonfinal_ahash_op("update", err, result, digestsize,
1596951d1332SEric Biggers 					      driver, vec_name, cfg);
15974cc2dcf9SEric Biggers 		if (err)
15984cc2dcf9SEric Biggers 			return err;
15996570737cSEric Biggers 		err = do_ahash_op(crypto_ahash_final, req, &wait, cfg->nosimd);
16004cc2dcf9SEric Biggers 		if (err) {
1601d8ea98aaSEric Biggers 			pr_err("alg: ahash: %s final() failed with err %d on test vector %s, cfg=\"%s\"\n",
1602951d1332SEric Biggers 			       driver, err, vec_name, cfg->name);
16034cc2dcf9SEric Biggers 			return err;
16044cc2dcf9SEric Biggers 		}
16054cc2dcf9SEric Biggers 	} else {
16064cc2dcf9SEric Biggers 		/* finish with finup() */
16076570737cSEric Biggers 		err = do_ahash_op(crypto_ahash_finup, req, &wait, cfg->nosimd);
16084cc2dcf9SEric Biggers 		if (err) {
1609d8ea98aaSEric Biggers 			pr_err("alg: ahash: %s finup() failed with err %d on test vector %s, cfg=\"%s\"\n",
1610951d1332SEric Biggers 			       driver, err, vec_name, cfg->name);
16114cc2dcf9SEric Biggers 			return err;
1612018ba95cSWang, Rui Y 		}
1613018ba95cSWang, Rui Y 	}
1614018ba95cSWang, Rui Y 
16154cc2dcf9SEric Biggers result_ready:
1616d8ea98aaSEric Biggers 	return check_hash_result("ahash", result, digestsize, vec, vec_name,
1617d8ea98aaSEric Biggers 				 driver, cfg);
1618da5ffe11SJussi Kivilinna }
1619da5ffe11SJussi Kivilinna 
test_hash_vec_cfg(const struct hash_testvec * vec,const char * vec_name,const struct testvec_config * cfg,struct ahash_request * req,struct shash_desc * desc,struct test_sglist * tsgl,u8 * hashstate)162079cafe9aSEric Biggers static int test_hash_vec_cfg(const struct hash_testvec *vec,
1621d8ea98aaSEric Biggers 			     const char *vec_name,
1622d8ea98aaSEric Biggers 			     const struct testvec_config *cfg,
1623d8ea98aaSEric Biggers 			     struct ahash_request *req,
1624d8ea98aaSEric Biggers 			     struct shash_desc *desc,
1625d8ea98aaSEric Biggers 			     struct test_sglist *tsgl,
1626d8ea98aaSEric Biggers 			     u8 *hashstate)
1627d8ea98aaSEric Biggers {
1628d8ea98aaSEric Biggers 	int err;
1629d8ea98aaSEric Biggers 
1630d8ea98aaSEric Biggers 	/*
1631d8ea98aaSEric Biggers 	 * For algorithms implemented as "shash", most bugs will be detected by
1632d8ea98aaSEric Biggers 	 * both the shash and ahash tests.  Test the shash API first so that the
1633d8ea98aaSEric Biggers 	 * failures involve less indirection, so are easier to debug.
1634d8ea98aaSEric Biggers 	 */
1635d8ea98aaSEric Biggers 
1636d8ea98aaSEric Biggers 	if (desc) {
163779cafe9aSEric Biggers 		err = test_shash_vec_cfg(vec, vec_name, cfg, desc, tsgl,
1638d8ea98aaSEric Biggers 					 hashstate);
1639d8ea98aaSEric Biggers 		if (err)
1640d8ea98aaSEric Biggers 			return err;
1641d8ea98aaSEric Biggers 	}
1642d8ea98aaSEric Biggers 
164379cafe9aSEric Biggers 	return test_ahash_vec_cfg(vec, vec_name, cfg, req, tsgl, hashstate);
1644da5ffe11SJussi Kivilinna }
1645da5ffe11SJussi Kivilinna 
test_hash_vec(const struct hash_testvec * vec,unsigned int vec_num,struct ahash_request * req,struct shash_desc * desc,struct test_sglist * tsgl,u8 * hashstate)164679cafe9aSEric Biggers static int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num,
164779cafe9aSEric Biggers 			 struct ahash_request *req, struct shash_desc *desc,
164879cafe9aSEric Biggers 			 struct test_sglist *tsgl, u8 *hashstate)
16494cc2dcf9SEric Biggers {
1650951d1332SEric Biggers 	char vec_name[16];
16514cc2dcf9SEric Biggers 	unsigned int i;
16524cc2dcf9SEric Biggers 	int err;
16534cc2dcf9SEric Biggers 
1654951d1332SEric Biggers 	sprintf(vec_name, "%u", vec_num);
1655951d1332SEric Biggers 
16564cc2dcf9SEric Biggers 	for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++) {
165779cafe9aSEric Biggers 		err = test_hash_vec_cfg(vec, vec_name,
16584cc2dcf9SEric Biggers 					&default_hash_testvec_configs[i],
1659d8ea98aaSEric Biggers 					req, desc, tsgl, hashstate);
16604cc2dcf9SEric Biggers 		if (err)
16614cc2dcf9SEric Biggers 			return err;
16624cc2dcf9SEric Biggers 	}
16634cc2dcf9SEric Biggers 
16644cc2dcf9SEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
16654cc2dcf9SEric Biggers 	if (!noextratests) {
1666f900fde2SEric Biggers 		struct rnd_state rng;
16674cc2dcf9SEric Biggers 		struct testvec_config cfg;
16684cc2dcf9SEric Biggers 		char cfgname[TESTVEC_CONFIG_NAMELEN];
16694cc2dcf9SEric Biggers 
1670f900fde2SEric Biggers 		init_rnd_state(&rng);
1671f900fde2SEric Biggers 
16724cc2dcf9SEric Biggers 		for (i = 0; i < fuzz_iterations; i++) {
1673f900fde2SEric Biggers 			generate_random_testvec_config(&rng, &cfg, cfgname,
16744cc2dcf9SEric Biggers 						       sizeof(cfgname));
167579cafe9aSEric Biggers 			err = test_hash_vec_cfg(vec, vec_name, &cfg,
1676d8ea98aaSEric Biggers 						req, desc, tsgl, hashstate);
16774cc2dcf9SEric Biggers 			if (err)
16784cc2dcf9SEric Biggers 				return err;
1679e63e1b0dSEric Biggers 			cond_resched();
16804cc2dcf9SEric Biggers 		}
16814cc2dcf9SEric Biggers 	}
16824cc2dcf9SEric Biggers #endif
16834cc2dcf9SEric Biggers 	return 0;
16844cc2dcf9SEric Biggers }
16854cc2dcf9SEric Biggers 
16869a8a6b3fSEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
16879a8a6b3fSEric Biggers /*
16889a8a6b3fSEric Biggers  * Generate a hash test vector from the given implementation.
16899a8a6b3fSEric Biggers  * Assumes the buffers in 'vec' were already allocated.
16909a8a6b3fSEric Biggers  */
generate_random_hash_testvec(struct rnd_state * rng,struct shash_desc * desc,struct hash_testvec * vec,unsigned int maxkeysize,unsigned int maxdatasize,char * name,size_t max_namelen)1691f900fde2SEric Biggers static void generate_random_hash_testvec(struct rnd_state *rng,
1692f900fde2SEric Biggers 					 struct shash_desc *desc,
16939a8a6b3fSEric Biggers 					 struct hash_testvec *vec,
16949a8a6b3fSEric Biggers 					 unsigned int maxkeysize,
16959a8a6b3fSEric Biggers 					 unsigned int maxdatasize,
16969a8a6b3fSEric Biggers 					 char *name, size_t max_namelen)
16979a8a6b3fSEric Biggers {
16989a8a6b3fSEric Biggers 	/* Data */
1699f900fde2SEric Biggers 	vec->psize = generate_random_length(rng, maxdatasize);
1700f900fde2SEric Biggers 	generate_random_bytes(rng, (u8 *)vec->plaintext, vec->psize);
17019a8a6b3fSEric Biggers 
17029a8a6b3fSEric Biggers 	/*
17039a8a6b3fSEric Biggers 	 * Key: length in range [1, maxkeysize], but usually choose maxkeysize.
17049a8a6b3fSEric Biggers 	 * If algorithm is unkeyed, then maxkeysize == 0 and set ksize = 0.
17059a8a6b3fSEric Biggers 	 */
17069a8a6b3fSEric Biggers 	vec->setkey_error = 0;
17079a8a6b3fSEric Biggers 	vec->ksize = 0;
17089a8a6b3fSEric Biggers 	if (maxkeysize) {
17099a8a6b3fSEric Biggers 		vec->ksize = maxkeysize;
1710f900fde2SEric Biggers 		if (prandom_u32_below(rng, 4) == 0)
1711f900fde2SEric Biggers 			vec->ksize = prandom_u32_inclusive(rng, 1, maxkeysize);
1712f900fde2SEric Biggers 		generate_random_bytes(rng, (u8 *)vec->key, vec->ksize);
17139a8a6b3fSEric Biggers 
1714149c4e6eSArnd Bergmann 		vec->setkey_error = crypto_shash_setkey(desc->tfm, vec->key,
17159a8a6b3fSEric Biggers 							vec->ksize);
17169a8a6b3fSEric Biggers 		/* If the key couldn't be set, no need to continue to digest. */
17179a8a6b3fSEric Biggers 		if (vec->setkey_error)
17189a8a6b3fSEric Biggers 			goto done;
17199a8a6b3fSEric Biggers 	}
17209a8a6b3fSEric Biggers 
17219a8a6b3fSEric Biggers 	/* Digest */
17229a8a6b3fSEric Biggers 	vec->digest_error = crypto_shash_digest(desc, vec->plaintext,
17239a8a6b3fSEric Biggers 						vec->psize, (u8 *)vec->digest);
17249a8a6b3fSEric Biggers done:
17259a8a6b3fSEric Biggers 	snprintf(name, max_namelen, "\"random: psize=%u ksize=%u\"",
17269a8a6b3fSEric Biggers 		 vec->psize, vec->ksize);
17279a8a6b3fSEric Biggers }
17289a8a6b3fSEric Biggers 
17299a8a6b3fSEric Biggers /*
17309a8a6b3fSEric Biggers  * Test the hash algorithm represented by @req against the corresponding generic
17319a8a6b3fSEric Biggers  * implementation, if one is available.
17329a8a6b3fSEric Biggers  */
test_hash_vs_generic_impl(const char * generic_driver,unsigned int maxkeysize,struct ahash_request * req,struct shash_desc * desc,struct test_sglist * tsgl,u8 * hashstate)173379cafe9aSEric Biggers static int test_hash_vs_generic_impl(const char *generic_driver,
17349a8a6b3fSEric Biggers 				     unsigned int maxkeysize,
17359a8a6b3fSEric Biggers 				     struct ahash_request *req,
1736d8ea98aaSEric Biggers 				     struct shash_desc *desc,
17379a8a6b3fSEric Biggers 				     struct test_sglist *tsgl,
17389a8a6b3fSEric Biggers 				     u8 *hashstate)
17399a8a6b3fSEric Biggers {
17409a8a6b3fSEric Biggers 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
17419a8a6b3fSEric Biggers 	const unsigned int digestsize = crypto_ahash_digestsize(tfm);
17429a8a6b3fSEric Biggers 	const unsigned int blocksize = crypto_ahash_blocksize(tfm);
17439a8a6b3fSEric Biggers 	const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
17449a8a6b3fSEric Biggers 	const char *algname = crypto_hash_alg_common(tfm)->base.cra_name;
174579cafe9aSEric Biggers 	const char *driver = crypto_ahash_driver_name(tfm);
1746f900fde2SEric Biggers 	struct rnd_state rng;
17479a8a6b3fSEric Biggers 	char _generic_driver[CRYPTO_MAX_ALG_NAME];
17489a8a6b3fSEric Biggers 	struct crypto_shash *generic_tfm = NULL;
1749149c4e6eSArnd Bergmann 	struct shash_desc *generic_desc = NULL;
17509a8a6b3fSEric Biggers 	unsigned int i;
17519a8a6b3fSEric Biggers 	struct hash_testvec vec = { 0 };
17529a8a6b3fSEric Biggers 	char vec_name[64];
17536b5ca646SArnd Bergmann 	struct testvec_config *cfg;
17549a8a6b3fSEric Biggers 	char cfgname[TESTVEC_CONFIG_NAMELEN];
17559a8a6b3fSEric Biggers 	int err;
17569a8a6b3fSEric Biggers 
17579a8a6b3fSEric Biggers 	if (noextratests)
17589a8a6b3fSEric Biggers 		return 0;
17599a8a6b3fSEric Biggers 
1760f900fde2SEric Biggers 	init_rnd_state(&rng);
1761f900fde2SEric Biggers 
17629a8a6b3fSEric Biggers 	if (!generic_driver) { /* Use default naming convention? */
17639a8a6b3fSEric Biggers 		err = build_generic_driver_name(algname, _generic_driver);
17649a8a6b3fSEric Biggers 		if (err)
17659a8a6b3fSEric Biggers 			return err;
17669a8a6b3fSEric Biggers 		generic_driver = _generic_driver;
17679a8a6b3fSEric Biggers 	}
17689a8a6b3fSEric Biggers 
17699a8a6b3fSEric Biggers 	if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */
17709a8a6b3fSEric Biggers 		return 0;
17719a8a6b3fSEric Biggers 
17729a8a6b3fSEric Biggers 	generic_tfm = crypto_alloc_shash(generic_driver, 0, 0);
17739a8a6b3fSEric Biggers 	if (IS_ERR(generic_tfm)) {
17749a8a6b3fSEric Biggers 		err = PTR_ERR(generic_tfm);
17759a8a6b3fSEric Biggers 		if (err == -ENOENT) {
17769a8a6b3fSEric Biggers 			pr_warn("alg: hash: skipping comparison tests for %s because %s is unavailable\n",
17779a8a6b3fSEric Biggers 				driver, generic_driver);
17789a8a6b3fSEric Biggers 			return 0;
17799a8a6b3fSEric Biggers 		}
17809a8a6b3fSEric Biggers 		pr_err("alg: hash: error allocating %s (generic impl of %s): %d\n",
17819a8a6b3fSEric Biggers 		       generic_driver, algname, err);
17829a8a6b3fSEric Biggers 		return err;
17839a8a6b3fSEric Biggers 	}
17849a8a6b3fSEric Biggers 
17856b5ca646SArnd Bergmann 	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
17866b5ca646SArnd Bergmann 	if (!cfg) {
17876b5ca646SArnd Bergmann 		err = -ENOMEM;
17886b5ca646SArnd Bergmann 		goto out;
17896b5ca646SArnd Bergmann 	}
17906b5ca646SArnd Bergmann 
1791149c4e6eSArnd Bergmann 	generic_desc = kzalloc(sizeof(*desc) +
1792149c4e6eSArnd Bergmann 			       crypto_shash_descsize(generic_tfm), GFP_KERNEL);
1793149c4e6eSArnd Bergmann 	if (!generic_desc) {
1794149c4e6eSArnd Bergmann 		err = -ENOMEM;
1795149c4e6eSArnd Bergmann 		goto out;
1796149c4e6eSArnd Bergmann 	}
1797149c4e6eSArnd Bergmann 	generic_desc->tfm = generic_tfm;
1798149c4e6eSArnd Bergmann 
17999a8a6b3fSEric Biggers 	/* Check the algorithm properties for consistency. */
18009a8a6b3fSEric Biggers 
18019a8a6b3fSEric Biggers 	if (digestsize != crypto_shash_digestsize(generic_tfm)) {
18029a8a6b3fSEric Biggers 		pr_err("alg: hash: digestsize for %s (%u) doesn't match generic impl (%u)\n",
18039a8a6b3fSEric Biggers 		       driver, digestsize,
18049a8a6b3fSEric Biggers 		       crypto_shash_digestsize(generic_tfm));
18059a8a6b3fSEric Biggers 		err = -EINVAL;
18069a8a6b3fSEric Biggers 		goto out;
18079a8a6b3fSEric Biggers 	}
18089a8a6b3fSEric Biggers 
18099a8a6b3fSEric Biggers 	if (blocksize != crypto_shash_blocksize(generic_tfm)) {
18109a8a6b3fSEric Biggers 		pr_err("alg: hash: blocksize for %s (%u) doesn't match generic impl (%u)\n",
18119a8a6b3fSEric Biggers 		       driver, blocksize, crypto_shash_blocksize(generic_tfm));
18129a8a6b3fSEric Biggers 		err = -EINVAL;
18139a8a6b3fSEric Biggers 		goto out;
18149a8a6b3fSEric Biggers 	}
18159a8a6b3fSEric Biggers 
18169a8a6b3fSEric Biggers 	/*
18179a8a6b3fSEric Biggers 	 * Now generate test vectors using the generic implementation, and test
18189a8a6b3fSEric Biggers 	 * the other implementation against them.
18199a8a6b3fSEric Biggers 	 */
18209a8a6b3fSEric Biggers 
18219a8a6b3fSEric Biggers 	vec.key = kmalloc(maxkeysize, GFP_KERNEL);
18229a8a6b3fSEric Biggers 	vec.plaintext = kmalloc(maxdatasize, GFP_KERNEL);
18239a8a6b3fSEric Biggers 	vec.digest = kmalloc(digestsize, GFP_KERNEL);
18249a8a6b3fSEric Biggers 	if (!vec.key || !vec.plaintext || !vec.digest) {
18259a8a6b3fSEric Biggers 		err = -ENOMEM;
18269a8a6b3fSEric Biggers 		goto out;
18279a8a6b3fSEric Biggers 	}
18289a8a6b3fSEric Biggers 
18299a8a6b3fSEric Biggers 	for (i = 0; i < fuzz_iterations * 8; i++) {
1830f900fde2SEric Biggers 		generate_random_hash_testvec(&rng, generic_desc, &vec,
18319a8a6b3fSEric Biggers 					     maxkeysize, maxdatasize,
18329a8a6b3fSEric Biggers 					     vec_name, sizeof(vec_name));
1833f900fde2SEric Biggers 		generate_random_testvec_config(&rng, cfg, cfgname,
1834f900fde2SEric Biggers 					       sizeof(cfgname));
18359a8a6b3fSEric Biggers 
183679cafe9aSEric Biggers 		err = test_hash_vec_cfg(&vec, vec_name, cfg,
1837d8ea98aaSEric Biggers 					req, desc, tsgl, hashstate);
18389a8a6b3fSEric Biggers 		if (err)
18399a8a6b3fSEric Biggers 			goto out;
18409a8a6b3fSEric Biggers 		cond_resched();
18419a8a6b3fSEric Biggers 	}
18429a8a6b3fSEric Biggers 	err = 0;
18439a8a6b3fSEric Biggers out:
18446b5ca646SArnd Bergmann 	kfree(cfg);
18459a8a6b3fSEric Biggers 	kfree(vec.key);
18469a8a6b3fSEric Biggers 	kfree(vec.plaintext);
18479a8a6b3fSEric Biggers 	kfree(vec.digest);
18489a8a6b3fSEric Biggers 	crypto_free_shash(generic_tfm);
1849453431a5SWaiman Long 	kfree_sensitive(generic_desc);
18509a8a6b3fSEric Biggers 	return err;
18519a8a6b3fSEric Biggers }
18529a8a6b3fSEric Biggers #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
test_hash_vs_generic_impl(const char * generic_driver,unsigned int maxkeysize,struct ahash_request * req,struct shash_desc * desc,struct test_sglist * tsgl,u8 * hashstate)185379cafe9aSEric Biggers static int test_hash_vs_generic_impl(const char *generic_driver,
18549a8a6b3fSEric Biggers 				     unsigned int maxkeysize,
18559a8a6b3fSEric Biggers 				     struct ahash_request *req,
1856d8ea98aaSEric Biggers 				     struct shash_desc *desc,
18579a8a6b3fSEric Biggers 				     struct test_sglist *tsgl,
18589a8a6b3fSEric Biggers 				     u8 *hashstate)
18599a8a6b3fSEric Biggers {
18609a8a6b3fSEric Biggers 	return 0;
18619a8a6b3fSEric Biggers }
18629a8a6b3fSEric Biggers #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
18639a8a6b3fSEric Biggers 
alloc_shash(const char * driver,u32 type,u32 mask,struct crypto_shash ** tfm_ret,struct shash_desc ** desc_ret)1864d8ea98aaSEric Biggers static int alloc_shash(const char *driver, u32 type, u32 mask,
1865d8ea98aaSEric Biggers 		       struct crypto_shash **tfm_ret,
1866d8ea98aaSEric Biggers 		       struct shash_desc **desc_ret)
1867d8ea98aaSEric Biggers {
1868d8ea98aaSEric Biggers 	struct crypto_shash *tfm;
1869d8ea98aaSEric Biggers 	struct shash_desc *desc;
1870d8ea98aaSEric Biggers 
1871d8ea98aaSEric Biggers 	tfm = crypto_alloc_shash(driver, type, mask);
1872d8ea98aaSEric Biggers 	if (IS_ERR(tfm)) {
1873d8ea98aaSEric Biggers 		if (PTR_ERR(tfm) == -ENOENT) {
1874d8ea98aaSEric Biggers 			/*
1875d8ea98aaSEric Biggers 			 * This algorithm is only available through the ahash
1876d8ea98aaSEric Biggers 			 * API, not the shash API, so skip the shash tests.
1877d8ea98aaSEric Biggers 			 */
1878d8ea98aaSEric Biggers 			return 0;
1879d8ea98aaSEric Biggers 		}
1880d8ea98aaSEric Biggers 		pr_err("alg: hash: failed to allocate shash transform for %s: %ld\n",
1881d8ea98aaSEric Biggers 		       driver, PTR_ERR(tfm));
1882d8ea98aaSEric Biggers 		return PTR_ERR(tfm);
1883d8ea98aaSEric Biggers 	}
1884d8ea98aaSEric Biggers 
1885d8ea98aaSEric Biggers 	desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
1886d8ea98aaSEric Biggers 	if (!desc) {
1887d8ea98aaSEric Biggers 		crypto_free_shash(tfm);
1888d8ea98aaSEric Biggers 		return -ENOMEM;
1889d8ea98aaSEric Biggers 	}
1890d8ea98aaSEric Biggers 	desc->tfm = tfm;
1891d8ea98aaSEric Biggers 
1892d8ea98aaSEric Biggers 	*tfm_ret = tfm;
1893d8ea98aaSEric Biggers 	*desc_ret = desc;
1894d8ea98aaSEric Biggers 	return 0;
1895d8ea98aaSEric Biggers }
1896d8ea98aaSEric Biggers 
__alg_test_hash(const struct hash_testvec * vecs,unsigned int num_vecs,const char * driver,u32 type,u32 mask,const char * generic_driver,unsigned int maxkeysize)18974cc2dcf9SEric Biggers static int __alg_test_hash(const struct hash_testvec *vecs,
18984cc2dcf9SEric Biggers 			   unsigned int num_vecs, const char *driver,
18999a8a6b3fSEric Biggers 			   u32 type, u32 mask,
19009a8a6b3fSEric Biggers 			   const char *generic_driver, unsigned int maxkeysize)
19014cc2dcf9SEric Biggers {
1902d8ea98aaSEric Biggers 	struct crypto_ahash *atfm = NULL;
19034cc2dcf9SEric Biggers 	struct ahash_request *req = NULL;
1904d8ea98aaSEric Biggers 	struct crypto_shash *stfm = NULL;
1905d8ea98aaSEric Biggers 	struct shash_desc *desc = NULL;
19064cc2dcf9SEric Biggers 	struct test_sglist *tsgl = NULL;
19074cc2dcf9SEric Biggers 	u8 *hashstate = NULL;
1908d8ea98aaSEric Biggers 	unsigned int statesize;
19094cc2dcf9SEric Biggers 	unsigned int i;
19104cc2dcf9SEric Biggers 	int err;
19114cc2dcf9SEric Biggers 
1912d8ea98aaSEric Biggers 	/*
1913d8ea98aaSEric Biggers 	 * Always test the ahash API.  This works regardless of whether the
1914d8ea98aaSEric Biggers 	 * algorithm is implemented as ahash or shash.
1915d8ea98aaSEric Biggers 	 */
1916d8ea98aaSEric Biggers 
1917d8ea98aaSEric Biggers 	atfm = crypto_alloc_ahash(driver, type, mask);
1918d8ea98aaSEric Biggers 	if (IS_ERR(atfm)) {
19194cc2dcf9SEric Biggers 		pr_err("alg: hash: failed to allocate transform for %s: %ld\n",
1920d8ea98aaSEric Biggers 		       driver, PTR_ERR(atfm));
1921d8ea98aaSEric Biggers 		return PTR_ERR(atfm);
19224cc2dcf9SEric Biggers 	}
192379cafe9aSEric Biggers 	driver = crypto_ahash_driver_name(atfm);
19244cc2dcf9SEric Biggers 
1925d8ea98aaSEric Biggers 	req = ahash_request_alloc(atfm, GFP_KERNEL);
19264cc2dcf9SEric Biggers 	if (!req) {
19274cc2dcf9SEric Biggers 		pr_err("alg: hash: failed to allocate request for %s\n",
19284cc2dcf9SEric Biggers 		       driver);
19294cc2dcf9SEric Biggers 		err = -ENOMEM;
19304cc2dcf9SEric Biggers 		goto out;
19314cc2dcf9SEric Biggers 	}
19324cc2dcf9SEric Biggers 
1933d8ea98aaSEric Biggers 	/*
1934d8ea98aaSEric Biggers 	 * If available also test the shash API, to cover corner cases that may
1935d8ea98aaSEric Biggers 	 * be missed by testing the ahash API only.
1936d8ea98aaSEric Biggers 	 */
1937d8ea98aaSEric Biggers 	err = alloc_shash(driver, type, mask, &stfm, &desc);
1938d8ea98aaSEric Biggers 	if (err)
1939d8ea98aaSEric Biggers 		goto out;
1940d8ea98aaSEric Biggers 
19414cc2dcf9SEric Biggers 	tsgl = kmalloc(sizeof(*tsgl), GFP_KERNEL);
19424cc2dcf9SEric Biggers 	if (!tsgl || init_test_sglist(tsgl) != 0) {
19434cc2dcf9SEric Biggers 		pr_err("alg: hash: failed to allocate test buffers for %s\n",
19444cc2dcf9SEric Biggers 		       driver);
19454cc2dcf9SEric Biggers 		kfree(tsgl);
19464cc2dcf9SEric Biggers 		tsgl = NULL;
19474cc2dcf9SEric Biggers 		err = -ENOMEM;
19484cc2dcf9SEric Biggers 		goto out;
19494cc2dcf9SEric Biggers 	}
19504cc2dcf9SEric Biggers 
1951d8ea98aaSEric Biggers 	statesize = crypto_ahash_statesize(atfm);
1952d8ea98aaSEric Biggers 	if (stfm)
1953d8ea98aaSEric Biggers 		statesize = max(statesize, crypto_shash_statesize(stfm));
1954d8ea98aaSEric Biggers 	hashstate = kmalloc(statesize + TESTMGR_POISON_LEN, GFP_KERNEL);
19554cc2dcf9SEric Biggers 	if (!hashstate) {
19564cc2dcf9SEric Biggers 		pr_err("alg: hash: failed to allocate hash state buffer for %s\n",
19574cc2dcf9SEric Biggers 		       driver);
19584cc2dcf9SEric Biggers 		err = -ENOMEM;
19594cc2dcf9SEric Biggers 		goto out;
19604cc2dcf9SEric Biggers 	}
19614cc2dcf9SEric Biggers 
19624cc2dcf9SEric Biggers 	for (i = 0; i < num_vecs; i++) {
1963c9c28ed0SStephan Müller 		if (fips_enabled && vecs[i].fips_skip)
1964c9c28ed0SStephan Müller 			continue;
1965c9c28ed0SStephan Müller 
196679cafe9aSEric Biggers 		err = test_hash_vec(&vecs[i], i, req, desc, tsgl, hashstate);
19674cc2dcf9SEric Biggers 		if (err)
19684cc2dcf9SEric Biggers 			goto out;
1969e63e1b0dSEric Biggers 		cond_resched();
19704cc2dcf9SEric Biggers 	}
197179cafe9aSEric Biggers 	err = test_hash_vs_generic_impl(generic_driver, maxkeysize, req,
1972d8ea98aaSEric Biggers 					desc, tsgl, hashstate);
19734cc2dcf9SEric Biggers out:
19744cc2dcf9SEric Biggers 	kfree(hashstate);
19754cc2dcf9SEric Biggers 	if (tsgl) {
19764cc2dcf9SEric Biggers 		destroy_test_sglist(tsgl);
19774cc2dcf9SEric Biggers 		kfree(tsgl);
19784cc2dcf9SEric Biggers 	}
1979d8ea98aaSEric Biggers 	kfree(desc);
1980d8ea98aaSEric Biggers 	crypto_free_shash(stfm);
19814cc2dcf9SEric Biggers 	ahash_request_free(req);
1982d8ea98aaSEric Biggers 	crypto_free_ahash(atfm);
19834cc2dcf9SEric Biggers 	return err;
19844cc2dcf9SEric Biggers }
19854cc2dcf9SEric Biggers 
alg_test_hash(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)19864cc2dcf9SEric Biggers static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
19874cc2dcf9SEric Biggers 			 u32 type, u32 mask)
19884cc2dcf9SEric Biggers {
19894cc2dcf9SEric Biggers 	const struct hash_testvec *template = desc->suite.hash.vecs;
19904cc2dcf9SEric Biggers 	unsigned int tcount = desc->suite.hash.count;
19914cc2dcf9SEric Biggers 	unsigned int nr_unkeyed, nr_keyed;
19929a8a6b3fSEric Biggers 	unsigned int maxkeysize = 0;
19934cc2dcf9SEric Biggers 	int err;
19944cc2dcf9SEric Biggers 
19954cc2dcf9SEric Biggers 	/*
19964cc2dcf9SEric Biggers 	 * For OPTIONAL_KEY algorithms, we have to do all the unkeyed tests
19974cc2dcf9SEric Biggers 	 * first, before setting a key on the tfm.  To make this easier, we
19984cc2dcf9SEric Biggers 	 * require that the unkeyed test vectors (if any) are listed first.
19994cc2dcf9SEric Biggers 	 */
20004cc2dcf9SEric Biggers 
20014cc2dcf9SEric Biggers 	for (nr_unkeyed = 0; nr_unkeyed < tcount; nr_unkeyed++) {
20024cc2dcf9SEric Biggers 		if (template[nr_unkeyed].ksize)
20034cc2dcf9SEric Biggers 			break;
20044cc2dcf9SEric Biggers 	}
20054cc2dcf9SEric Biggers 	for (nr_keyed = 0; nr_unkeyed + nr_keyed < tcount; nr_keyed++) {
20064cc2dcf9SEric Biggers 		if (!template[nr_unkeyed + nr_keyed].ksize) {
20074cc2dcf9SEric Biggers 			pr_err("alg: hash: test vectors for %s out of order, "
20084cc2dcf9SEric Biggers 			       "unkeyed ones must come first\n", desc->alg);
20094cc2dcf9SEric Biggers 			return -EINVAL;
20104cc2dcf9SEric Biggers 		}
20119a8a6b3fSEric Biggers 		maxkeysize = max_t(unsigned int, maxkeysize,
20129a8a6b3fSEric Biggers 				   template[nr_unkeyed + nr_keyed].ksize);
20134cc2dcf9SEric Biggers 	}
20144cc2dcf9SEric Biggers 
20154cc2dcf9SEric Biggers 	err = 0;
20164cc2dcf9SEric Biggers 	if (nr_unkeyed) {
20179a8a6b3fSEric Biggers 		err = __alg_test_hash(template, nr_unkeyed, driver, type, mask,
20189a8a6b3fSEric Biggers 				      desc->generic_driver, maxkeysize);
20194cc2dcf9SEric Biggers 		template += nr_unkeyed;
20204cc2dcf9SEric Biggers 	}
20214cc2dcf9SEric Biggers 
20224cc2dcf9SEric Biggers 	if (!err && nr_keyed)
20239a8a6b3fSEric Biggers 		err = __alg_test_hash(template, nr_keyed, driver, type, mask,
20249a8a6b3fSEric Biggers 				      desc->generic_driver, maxkeysize);
20254cc2dcf9SEric Biggers 
20264cc2dcf9SEric Biggers 	return err;
20274cc2dcf9SEric Biggers }
20284cc2dcf9SEric Biggers 
test_aead_vec_cfg(int enc,const struct aead_testvec * vec,const char * vec_name,const struct testvec_config * cfg,struct aead_request * req,struct cipher_test_sglists * tsgls)20292257f471SEric Biggers static int test_aead_vec_cfg(int enc, const struct aead_testvec *vec,
2030951d1332SEric Biggers 			     const char *vec_name,
2031ed96804fSEric Biggers 			     const struct testvec_config *cfg,
2032ed96804fSEric Biggers 			     struct aead_request *req,
2033ed96804fSEric Biggers 			     struct cipher_test_sglists *tsgls)
2034da7f033dSHerbert Xu {
2035ed96804fSEric Biggers 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
2036ed96804fSEric Biggers 	const unsigned int alignmask = crypto_aead_alignmask(tfm);
2037ed96804fSEric Biggers 	const unsigned int ivsize = crypto_aead_ivsize(tfm);
2038ed96804fSEric Biggers 	const unsigned int authsize = vec->clen - vec->plen;
20392257f471SEric Biggers 	const char *driver = crypto_aead_driver_name(tfm);
2040ed96804fSEric Biggers 	const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags;
2041ed96804fSEric Biggers 	const char *op = enc ? "encryption" : "decryption";
2042ed96804fSEric Biggers 	DECLARE_CRYPTO_WAIT(wait);
2043ed96804fSEric Biggers 	u8 _iv[3 * (MAX_ALGAPI_ALIGNMASK + 1) + MAX_IVLEN];
2044ed96804fSEric Biggers 	u8 *iv = PTR_ALIGN(&_iv[0], 2 * (MAX_ALGAPI_ALIGNMASK + 1)) +
2045ed96804fSEric Biggers 		 cfg->iv_offset +
2046ed96804fSEric Biggers 		 (cfg->iv_offset_relative_to_alignmask ? alignmask : 0);
2047ed96804fSEric Biggers 	struct kvec input[2];
2048ed96804fSEric Biggers 	int err;
2049f8b0d4d0SHerbert Xu 
2050ed96804fSEric Biggers 	/* Set the key */
2051ed96804fSEric Biggers 	if (vec->wk)
2052ed96804fSEric Biggers 		crypto_aead_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
2053d8a32ac2SJussi Kivilinna 	else
2054ed96804fSEric Biggers 		crypto_aead_clear_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
2055fd8c37c7SEric Biggers 
2056fd8c37c7SEric Biggers 	err = do_setkey(crypto_aead_setkey, tfm, vec->key, vec->klen,
2057fd8c37c7SEric Biggers 			cfg, alignmask);
20585283a8eeSEric Biggers 	if (err && err != vec->setkey_error) {
2059951d1332SEric Biggers 		pr_err("alg: aead: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
2060951d1332SEric Biggers 		       driver, vec_name, vec->setkey_error, err,
20615283a8eeSEric Biggers 		       crypto_aead_get_flags(tfm));
2062ed96804fSEric Biggers 		return err;
2063ed96804fSEric Biggers 	}
20645283a8eeSEric Biggers 	if (!err && vec->setkey_error) {
2065951d1332SEric Biggers 		pr_err("alg: aead: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
2066951d1332SEric Biggers 		       driver, vec_name, vec->setkey_error);
2067ed96804fSEric Biggers 		return -EINVAL;
2068ed96804fSEric Biggers 	}
2069d8a32ac2SJussi Kivilinna 
2070ed96804fSEric Biggers 	/* Set the authentication tag size */
2071ed96804fSEric Biggers 	err = crypto_aead_setauthsize(tfm, authsize);
20725283a8eeSEric Biggers 	if (err && err != vec->setauthsize_error) {
2073951d1332SEric Biggers 		pr_err("alg: aead: %s setauthsize failed on test vector %s; expected_error=%d, actual_error=%d\n",
2074951d1332SEric Biggers 		       driver, vec_name, vec->setauthsize_error, err);
2075ed96804fSEric Biggers 		return err;
2076ed96804fSEric Biggers 	}
20775283a8eeSEric Biggers 	if (!err && vec->setauthsize_error) {
2078951d1332SEric Biggers 		pr_err("alg: aead: %s setauthsize unexpectedly succeeded on test vector %s; expected_error=%d\n",
2079951d1332SEric Biggers 		       driver, vec_name, vec->setauthsize_error);
20805283a8eeSEric Biggers 		return -EINVAL;
20815283a8eeSEric Biggers 	}
20825283a8eeSEric Biggers 
20835283a8eeSEric Biggers 	if (vec->setkey_error || vec->setauthsize_error)
20845283a8eeSEric Biggers 		return 0;
2085ed96804fSEric Biggers 
2086ed96804fSEric Biggers 	/* The IV must be copied to a buffer, as the algorithm may modify it */
2087ed96804fSEric Biggers 	if (WARN_ON(ivsize > MAX_IVLEN))
2088ed96804fSEric Biggers 		return -EINVAL;
2089ed96804fSEric Biggers 	if (vec->iv)
2090ed96804fSEric Biggers 		memcpy(iv, vec->iv, ivsize);
2091da7f033dSHerbert Xu 	else
2092ed96804fSEric Biggers 		memset(iv, 0, ivsize);
2093da7f033dSHerbert Xu 
2094ed96804fSEric Biggers 	/* Build the src/dst scatterlists */
2095ed96804fSEric Biggers 	input[0].iov_base = (void *)vec->assoc;
2096ed96804fSEric Biggers 	input[0].iov_len = vec->alen;
2097ed96804fSEric Biggers 	input[1].iov_base = enc ? (void *)vec->ptext : (void *)vec->ctext;
2098ed96804fSEric Biggers 	input[1].iov_len = enc ? vec->plen : vec->clen;
2099ed96804fSEric Biggers 	err = build_cipher_test_sglists(tsgls, cfg, alignmask,
2100ed96804fSEric Biggers 					vec->alen + (enc ? vec->plen :
2101ed96804fSEric Biggers 						     vec->clen),
2102ed96804fSEric Biggers 					vec->alen + (enc ? vec->clen :
2103ed96804fSEric Biggers 						     vec->plen),
2104ed96804fSEric Biggers 					input, 2);
2105ed96804fSEric Biggers 	if (err) {
2106951d1332SEric Biggers 		pr_err("alg: aead: %s %s: error preparing scatterlists for test vector %s, cfg=\"%s\"\n",
2107951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
2108ed96804fSEric Biggers 		return err;
2109da7f033dSHerbert Xu 	}
2110da7f033dSHerbert Xu 
2111ed96804fSEric Biggers 	/* Do the actual encryption or decryption */
2112ed96804fSEric Biggers 	testmgr_poison(req->__ctx, crypto_aead_reqsize(tfm));
2113ed96804fSEric Biggers 	aead_request_set_callback(req, req_flags, crypto_req_done, &wait);
2114ed96804fSEric Biggers 	aead_request_set_crypt(req, tsgls->src.sgl_ptr, tsgls->dst.sgl_ptr,
2115ed96804fSEric Biggers 			       enc ? vec->plen : vec->clen, iv);
2116ed96804fSEric Biggers 	aead_request_set_ad(req, vec->alen);
21176570737cSEric Biggers 	if (cfg->nosimd)
21186570737cSEric Biggers 		crypto_disable_simd_for_test();
21196570737cSEric Biggers 	err = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
21206570737cSEric Biggers 	if (cfg->nosimd)
21216570737cSEric Biggers 		crypto_reenable_simd_for_test();
21226570737cSEric Biggers 	err = crypto_wait_req(err, &wait);
212305b1d338SCristian Stoica 
2124a6e5ef9bSEric Biggers 	/* Check that the algorithm didn't overwrite things it shouldn't have */
2125a6e5ef9bSEric Biggers 	if (req->cryptlen != (enc ? vec->plen : vec->clen) ||
2126a6e5ef9bSEric Biggers 	    req->assoclen != vec->alen ||
2127a6e5ef9bSEric Biggers 	    req->iv != iv ||
2128a6e5ef9bSEric Biggers 	    req->src != tsgls->src.sgl_ptr ||
2129a6e5ef9bSEric Biggers 	    req->dst != tsgls->dst.sgl_ptr ||
2130a6e5ef9bSEric Biggers 	    crypto_aead_reqtfm(req) != tfm ||
2131a6e5ef9bSEric Biggers 	    req->base.complete != crypto_req_done ||
2132a6e5ef9bSEric Biggers 	    req->base.flags != req_flags ||
2133a6e5ef9bSEric Biggers 	    req->base.data != &wait) {
2134951d1332SEric Biggers 		pr_err("alg: aead: %s %s corrupted request struct on test vector %s, cfg=\"%s\"\n",
2135951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
2136a6e5ef9bSEric Biggers 		if (req->cryptlen != (enc ? vec->plen : vec->clen))
2137a6e5ef9bSEric Biggers 			pr_err("alg: aead: changed 'req->cryptlen'\n");
2138a6e5ef9bSEric Biggers 		if (req->assoclen != vec->alen)
2139a6e5ef9bSEric Biggers 			pr_err("alg: aead: changed 'req->assoclen'\n");
2140a6e5ef9bSEric Biggers 		if (req->iv != iv)
2141a6e5ef9bSEric Biggers 			pr_err("alg: aead: changed 'req->iv'\n");
2142a6e5ef9bSEric Biggers 		if (req->src != tsgls->src.sgl_ptr)
2143a6e5ef9bSEric Biggers 			pr_err("alg: aead: changed 'req->src'\n");
2144a6e5ef9bSEric Biggers 		if (req->dst != tsgls->dst.sgl_ptr)
2145a6e5ef9bSEric Biggers 			pr_err("alg: aead: changed 'req->dst'\n");
2146a6e5ef9bSEric Biggers 		if (crypto_aead_reqtfm(req) != tfm)
2147a6e5ef9bSEric Biggers 			pr_err("alg: aead: changed 'req->base.tfm'\n");
2148a6e5ef9bSEric Biggers 		if (req->base.complete != crypto_req_done)
2149a6e5ef9bSEric Biggers 			pr_err("alg: aead: changed 'req->base.complete'\n");
2150a6e5ef9bSEric Biggers 		if (req->base.flags != req_flags)
2151a6e5ef9bSEric Biggers 			pr_err("alg: aead: changed 'req->base.flags'\n");
2152a6e5ef9bSEric Biggers 		if (req->base.data != &wait)
2153a6e5ef9bSEric Biggers 			pr_err("alg: aead: changed 'req->base.data'\n");
2154a6e5ef9bSEric Biggers 		return -EINVAL;
2155a6e5ef9bSEric Biggers 	}
2156a6e5ef9bSEric Biggers 	if (is_test_sglist_corrupted(&tsgls->src)) {
2157951d1332SEric Biggers 		pr_err("alg: aead: %s %s corrupted src sgl on test vector %s, cfg=\"%s\"\n",
2158951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
2159a6e5ef9bSEric Biggers 		return -EINVAL;
2160a6e5ef9bSEric Biggers 	}
2161a6e5ef9bSEric Biggers 	if (tsgls->dst.sgl_ptr != tsgls->src.sgl &&
2162a6e5ef9bSEric Biggers 	    is_test_sglist_corrupted(&tsgls->dst)) {
2163951d1332SEric Biggers 		pr_err("alg: aead: %s %s corrupted dst sgl on test vector %s, cfg=\"%s\"\n",
2164951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
2165a6e5ef9bSEric Biggers 		return -EINVAL;
2166a6e5ef9bSEric Biggers 	}
2167a6e5ef9bSEric Biggers 
216849763fc6SEric Biggers 	/* Check for unexpected success or failure, or wrong error code */
216949763fc6SEric Biggers 	if ((err == 0 && vec->novrfy) ||
217049763fc6SEric Biggers 	    (err != vec->crypt_error && !(err == -EBADMSG && vec->novrfy))) {
217149763fc6SEric Biggers 		char expected_error[32];
217249763fc6SEric Biggers 
217349763fc6SEric Biggers 		if (vec->novrfy &&
217449763fc6SEric Biggers 		    vec->crypt_error != 0 && vec->crypt_error != -EBADMSG)
217549763fc6SEric Biggers 			sprintf(expected_error, "-EBADMSG or %d",
217649763fc6SEric Biggers 				vec->crypt_error);
217749763fc6SEric Biggers 		else if (vec->novrfy)
217849763fc6SEric Biggers 			sprintf(expected_error, "-EBADMSG");
217949763fc6SEric Biggers 		else
218049763fc6SEric Biggers 			sprintf(expected_error, "%d", vec->crypt_error);
21815283a8eeSEric Biggers 		if (err) {
218249763fc6SEric Biggers 			pr_err("alg: aead: %s %s failed on test vector %s; expected_error=%s, actual_error=%d, cfg=\"%s\"\n",
218349763fc6SEric Biggers 			       driver, op, vec_name, expected_error, err,
218449763fc6SEric Biggers 			       cfg->name);
21855283a8eeSEric Biggers 			return err;
21865283a8eeSEric Biggers 		}
218749763fc6SEric Biggers 		pr_err("alg: aead: %s %s unexpectedly succeeded on test vector %s; expected_error=%s, cfg=\"%s\"\n",
2188951d1332SEric Biggers 		       driver, op, vec_name, expected_error, cfg->name);
21895283a8eeSEric Biggers 		return -EINVAL;
21905283a8eeSEric Biggers 	}
219149763fc6SEric Biggers 	if (err) /* Expectedly failed. */
219249763fc6SEric Biggers 		return 0;
21935283a8eeSEric Biggers 
2194ed96804fSEric Biggers 	/* Check for the correct output (ciphertext or plaintext) */
2195ed96804fSEric Biggers 	err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext,
2196ed96804fSEric Biggers 				    enc ? vec->clen : vec->plen,
2197f17f9e90SEric Biggers 				    vec->alen,
2198f17f9e90SEric Biggers 				    enc || cfg->inplace_mode == OUT_OF_PLACE);
2199ed96804fSEric Biggers 	if (err == -EOVERFLOW) {
2200951d1332SEric Biggers 		pr_err("alg: aead: %s %s overran dst buffer on test vector %s, cfg=\"%s\"\n",
2201951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
2202ed96804fSEric Biggers 		return err;
220329b77e5dSHoria Geanta 	}
2204ed96804fSEric Biggers 	if (err) {
2205951d1332SEric Biggers 		pr_err("alg: aead: %s %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
2206951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
2207ed96804fSEric Biggers 		return err;
220858dcf548SJussi Kivilinna 	}
220958dcf548SJussi Kivilinna 
221058dcf548SJussi Kivilinna 	return 0;
2211d8a32ac2SJussi Kivilinna }
2212d8a32ac2SJussi Kivilinna 
test_aead_vec(int enc,const struct aead_testvec * vec,unsigned int vec_num,struct aead_request * req,struct cipher_test_sglists * tsgls)22132257f471SEric Biggers static int test_aead_vec(int enc, const struct aead_testvec *vec,
22142257f471SEric Biggers 			 unsigned int vec_num, struct aead_request *req,
2215ed96804fSEric Biggers 			 struct cipher_test_sglists *tsgls)
2216ed96804fSEric Biggers {
2217951d1332SEric Biggers 	char vec_name[16];
2218ed96804fSEric Biggers 	unsigned int i;
2219ed96804fSEric Biggers 	int err;
2220ed96804fSEric Biggers 
2221ed96804fSEric Biggers 	if (enc && vec->novrfy)
2222ed96804fSEric Biggers 		return 0;
2223ed96804fSEric Biggers 
2224951d1332SEric Biggers 	sprintf(vec_name, "%u", vec_num);
2225951d1332SEric Biggers 
2226ed96804fSEric Biggers 	for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) {
22272257f471SEric Biggers 		err = test_aead_vec_cfg(enc, vec, vec_name,
2228ed96804fSEric Biggers 					&default_cipher_testvec_configs[i],
2229ed96804fSEric Biggers 					req, tsgls);
2230ed96804fSEric Biggers 		if (err)
2231ed96804fSEric Biggers 			return err;
2232ed96804fSEric Biggers 	}
2233ed96804fSEric Biggers 
2234ed96804fSEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
2235ed96804fSEric Biggers 	if (!noextratests) {
2236f900fde2SEric Biggers 		struct rnd_state rng;
2237ed96804fSEric Biggers 		struct testvec_config cfg;
2238ed96804fSEric Biggers 		char cfgname[TESTVEC_CONFIG_NAMELEN];
2239ed96804fSEric Biggers 
2240f900fde2SEric Biggers 		init_rnd_state(&rng);
2241f900fde2SEric Biggers 
2242ed96804fSEric Biggers 		for (i = 0; i < fuzz_iterations; i++) {
2243f900fde2SEric Biggers 			generate_random_testvec_config(&rng, &cfg, cfgname,
2244ed96804fSEric Biggers 						       sizeof(cfgname));
22452257f471SEric Biggers 			err = test_aead_vec_cfg(enc, vec, vec_name,
2246ed96804fSEric Biggers 						&cfg, req, tsgls);
2247ed96804fSEric Biggers 			if (err)
2248ed96804fSEric Biggers 				return err;
2249e63e1b0dSEric Biggers 			cond_resched();
2250ed96804fSEric Biggers 		}
2251ed96804fSEric Biggers 	}
2252ed96804fSEric Biggers #endif
2253ed96804fSEric Biggers 	return 0;
2254ed96804fSEric Biggers }
2255ed96804fSEric Biggers 
225640153b10SEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
22572ea91505SEric Biggers 
22582ea91505SEric Biggers struct aead_extra_tests_ctx {
2259f900fde2SEric Biggers 	struct rnd_state rng;
22602ea91505SEric Biggers 	struct aead_request *req;
22612ea91505SEric Biggers 	struct crypto_aead *tfm;
22622ea91505SEric Biggers 	const struct alg_test_desc *test_desc;
22632ea91505SEric Biggers 	struct cipher_test_sglists *tsgls;
22642ea91505SEric Biggers 	unsigned int maxdatasize;
22652ea91505SEric Biggers 	unsigned int maxkeysize;
22662ea91505SEric Biggers 
22672ea91505SEric Biggers 	struct aead_testvec vec;
22682ea91505SEric Biggers 	char vec_name[64];
22692ea91505SEric Biggers 	char cfgname[TESTVEC_CONFIG_NAMELEN];
22702ea91505SEric Biggers 	struct testvec_config cfg;
22712ea91505SEric Biggers };
22722ea91505SEric Biggers 
227340153b10SEric Biggers /*
227449763fc6SEric Biggers  * Make at least one random change to a (ciphertext, AAD) pair.  "Ciphertext"
227549763fc6SEric Biggers  * here means the full ciphertext including the authentication tag.  The
227649763fc6SEric Biggers  * authentication tag (and hence also the ciphertext) is assumed to be nonempty.
227749763fc6SEric Biggers  */
mutate_aead_message(struct rnd_state * rng,struct aead_testvec * vec,bool aad_iv,unsigned int ivsize)2278f900fde2SEric Biggers static void mutate_aead_message(struct rnd_state *rng,
2279f900fde2SEric Biggers 				struct aead_testvec *vec, bool aad_iv,
22806f3a06d9SEric Biggers 				unsigned int ivsize)
228149763fc6SEric Biggers {
22826f3a06d9SEric Biggers 	const unsigned int aad_tail_size = aad_iv ? ivsize : 0;
228349763fc6SEric Biggers 	const unsigned int authsize = vec->clen - vec->plen;
228449763fc6SEric Biggers 
2285f900fde2SEric Biggers 	if (prandom_bool(rng) && vec->alen > aad_tail_size) {
228649763fc6SEric Biggers 		 /* Mutate the AAD */
2287f900fde2SEric Biggers 		flip_random_bit(rng, (u8 *)vec->assoc,
2288f900fde2SEric Biggers 				vec->alen - aad_tail_size);
2289f900fde2SEric Biggers 		if (prandom_bool(rng))
229049763fc6SEric Biggers 			return;
229149763fc6SEric Biggers 	}
2292f900fde2SEric Biggers 	if (prandom_bool(rng)) {
229349763fc6SEric Biggers 		/* Mutate auth tag (assuming it's at the end of ciphertext) */
2294f900fde2SEric Biggers 		flip_random_bit(rng, (u8 *)vec->ctext + vec->plen, authsize);
229549763fc6SEric Biggers 	} else {
229649763fc6SEric Biggers 		/* Mutate any part of the ciphertext */
2297f900fde2SEric Biggers 		flip_random_bit(rng, (u8 *)vec->ctext, vec->clen);
229849763fc6SEric Biggers 	}
229949763fc6SEric Biggers }
230049763fc6SEric Biggers 
230149763fc6SEric Biggers /*
230249763fc6SEric Biggers  * Minimum authentication tag size in bytes at which we assume that we can
230349763fc6SEric Biggers  * reliably generate inauthentic messages, i.e. not generate an authentic
230449763fc6SEric Biggers  * message by chance.
230549763fc6SEric Biggers  */
230649763fc6SEric Biggers #define MIN_COLLISION_FREE_AUTHSIZE 8
230749763fc6SEric Biggers 
generate_aead_message(struct rnd_state * rng,struct aead_request * req,const struct aead_test_suite * suite,struct aead_testvec * vec,bool prefer_inauthentic)2308f900fde2SEric Biggers static void generate_aead_message(struct rnd_state *rng,
2309f900fde2SEric Biggers 				  struct aead_request *req,
231049763fc6SEric Biggers 				  const struct aead_test_suite *suite,
231149763fc6SEric Biggers 				  struct aead_testvec *vec,
231249763fc6SEric Biggers 				  bool prefer_inauthentic)
231349763fc6SEric Biggers {
231449763fc6SEric Biggers 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
231549763fc6SEric Biggers 	const unsigned int ivsize = crypto_aead_ivsize(tfm);
231649763fc6SEric Biggers 	const unsigned int authsize = vec->clen - vec->plen;
231749763fc6SEric Biggers 	const bool inauthentic = (authsize >= MIN_COLLISION_FREE_AUTHSIZE) &&
2318f900fde2SEric Biggers 				 (prefer_inauthentic ||
2319f900fde2SEric Biggers 				  prandom_u32_below(rng, 4) == 0);
232049763fc6SEric Biggers 
232149763fc6SEric Biggers 	/* Generate the AAD. */
2322f900fde2SEric Biggers 	generate_random_bytes(rng, (u8 *)vec->assoc, vec->alen);
23236f3a06d9SEric Biggers 	if (suite->aad_iv && vec->alen >= ivsize)
23246f3a06d9SEric Biggers 		/* Avoid implementation-defined behavior. */
23256f3a06d9SEric Biggers 		memcpy((u8 *)vec->assoc + vec->alen - ivsize, vec->iv, ivsize);
232649763fc6SEric Biggers 
2327f900fde2SEric Biggers 	if (inauthentic && prandom_bool(rng)) {
232849763fc6SEric Biggers 		/* Generate a random ciphertext. */
2329f900fde2SEric Biggers 		generate_random_bytes(rng, (u8 *)vec->ctext, vec->clen);
233049763fc6SEric Biggers 	} else {
233149763fc6SEric Biggers 		int i = 0;
233249763fc6SEric Biggers 		struct scatterlist src[2], dst;
233349763fc6SEric Biggers 		u8 iv[MAX_IVLEN];
233449763fc6SEric Biggers 		DECLARE_CRYPTO_WAIT(wait);
233549763fc6SEric Biggers 
233649763fc6SEric Biggers 		/* Generate a random plaintext and encrypt it. */
233749763fc6SEric Biggers 		sg_init_table(src, 2);
233849763fc6SEric Biggers 		if (vec->alen)
233949763fc6SEric Biggers 			sg_set_buf(&src[i++], vec->assoc, vec->alen);
234049763fc6SEric Biggers 		if (vec->plen) {
2341f900fde2SEric Biggers 			generate_random_bytes(rng, (u8 *)vec->ptext, vec->plen);
234249763fc6SEric Biggers 			sg_set_buf(&src[i++], vec->ptext, vec->plen);
234349763fc6SEric Biggers 		}
234449763fc6SEric Biggers 		sg_init_one(&dst, vec->ctext, vec->alen + vec->clen);
234549763fc6SEric Biggers 		memcpy(iv, vec->iv, ivsize);
234649763fc6SEric Biggers 		aead_request_set_callback(req, 0, crypto_req_done, &wait);
234749763fc6SEric Biggers 		aead_request_set_crypt(req, src, &dst, vec->plen, iv);
234849763fc6SEric Biggers 		aead_request_set_ad(req, vec->alen);
234949763fc6SEric Biggers 		vec->crypt_error = crypto_wait_req(crypto_aead_encrypt(req),
235049763fc6SEric Biggers 						   &wait);
235149763fc6SEric Biggers 		/* If encryption failed, we're done. */
235249763fc6SEric Biggers 		if (vec->crypt_error != 0)
235349763fc6SEric Biggers 			return;
235449763fc6SEric Biggers 		memmove((u8 *)vec->ctext, vec->ctext + vec->alen, vec->clen);
235549763fc6SEric Biggers 		if (!inauthentic)
235649763fc6SEric Biggers 			return;
235749763fc6SEric Biggers 		/*
235849763fc6SEric Biggers 		 * Mutate the authentic (ciphertext, AAD) pair to get an
235949763fc6SEric Biggers 		 * inauthentic one.
236049763fc6SEric Biggers 		 */
2361f900fde2SEric Biggers 		mutate_aead_message(rng, vec, suite->aad_iv, ivsize);
236249763fc6SEric Biggers 	}
236349763fc6SEric Biggers 	vec->novrfy = 1;
236449763fc6SEric Biggers 	if (suite->einval_allowed)
236549763fc6SEric Biggers 		vec->crypt_error = -EINVAL;
236649763fc6SEric Biggers }
236749763fc6SEric Biggers 
236849763fc6SEric Biggers /*
236949763fc6SEric Biggers  * Generate an AEAD test vector 'vec' using the implementation specified by
237049763fc6SEric Biggers  * 'req'.  The buffers in 'vec' must already be allocated.
237149763fc6SEric Biggers  *
237249763fc6SEric Biggers  * If 'prefer_inauthentic' is true, then this function will generate inauthentic
237349763fc6SEric Biggers  * test vectors (i.e. vectors with 'vec->novrfy=1') more often.
237440153b10SEric Biggers  */
generate_random_aead_testvec(struct rnd_state * rng,struct aead_request * req,struct aead_testvec * vec,const struct aead_test_suite * suite,unsigned int maxkeysize,unsigned int maxdatasize,char * name,size_t max_namelen,bool prefer_inauthentic)2375f900fde2SEric Biggers static void generate_random_aead_testvec(struct rnd_state *rng,
2376f900fde2SEric Biggers 					 struct aead_request *req,
237740153b10SEric Biggers 					 struct aead_testvec *vec,
237849763fc6SEric Biggers 					 const struct aead_test_suite *suite,
237940153b10SEric Biggers 					 unsigned int maxkeysize,
238040153b10SEric Biggers 					 unsigned int maxdatasize,
238149763fc6SEric Biggers 					 char *name, size_t max_namelen,
238249763fc6SEric Biggers 					 bool prefer_inauthentic)
238340153b10SEric Biggers {
238440153b10SEric Biggers 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
238540153b10SEric Biggers 	const unsigned int ivsize = crypto_aead_ivsize(tfm);
23862ea91505SEric Biggers 	const unsigned int maxauthsize = crypto_aead_maxauthsize(tfm);
238740153b10SEric Biggers 	unsigned int authsize;
238840153b10SEric Biggers 	unsigned int total_len;
238940153b10SEric Biggers 
239040153b10SEric Biggers 	/* Key: length in [0, maxkeysize], but usually choose maxkeysize */
239140153b10SEric Biggers 	vec->klen = maxkeysize;
2392f900fde2SEric Biggers 	if (prandom_u32_below(rng, 4) == 0)
2393f900fde2SEric Biggers 		vec->klen = prandom_u32_below(rng, maxkeysize + 1);
2394f900fde2SEric Biggers 	generate_random_bytes(rng, (u8 *)vec->key, vec->klen);
239540153b10SEric Biggers 	vec->setkey_error = crypto_aead_setkey(tfm, vec->key, vec->klen);
239640153b10SEric Biggers 
239740153b10SEric Biggers 	/* IV */
2398f900fde2SEric Biggers 	generate_random_bytes(rng, (u8 *)vec->iv, ivsize);
239940153b10SEric Biggers 
240040153b10SEric Biggers 	/* Tag length: in [0, maxauthsize], but usually choose maxauthsize */
240140153b10SEric Biggers 	authsize = maxauthsize;
2402f900fde2SEric Biggers 	if (prandom_u32_below(rng, 4) == 0)
2403f900fde2SEric Biggers 		authsize = prandom_u32_below(rng, maxauthsize + 1);
240449763fc6SEric Biggers 	if (prefer_inauthentic && authsize < MIN_COLLISION_FREE_AUTHSIZE)
240549763fc6SEric Biggers 		authsize = MIN_COLLISION_FREE_AUTHSIZE;
240640153b10SEric Biggers 	if (WARN_ON(authsize > maxdatasize))
240740153b10SEric Biggers 		authsize = maxdatasize;
240840153b10SEric Biggers 	maxdatasize -= authsize;
240940153b10SEric Biggers 	vec->setauthsize_error = crypto_aead_setauthsize(tfm, authsize);
241040153b10SEric Biggers 
241149763fc6SEric Biggers 	/* AAD, plaintext, and ciphertext lengths */
2412f900fde2SEric Biggers 	total_len = generate_random_length(rng, maxdatasize);
2413f900fde2SEric Biggers 	if (prandom_u32_below(rng, 4) == 0)
241440153b10SEric Biggers 		vec->alen = 0;
241540153b10SEric Biggers 	else
2416f900fde2SEric Biggers 		vec->alen = generate_random_length(rng, total_len);
241740153b10SEric Biggers 	vec->plen = total_len - vec->alen;
241840153b10SEric Biggers 	vec->clen = vec->plen + authsize;
241940153b10SEric Biggers 
242040153b10SEric Biggers 	/*
242149763fc6SEric Biggers 	 * Generate the AAD, plaintext, and ciphertext.  Not applicable if the
242249763fc6SEric Biggers 	 * key or the authentication tag size couldn't be set.
242340153b10SEric Biggers 	 */
242449763fc6SEric Biggers 	vec->novrfy = 0;
2425eb455dbdSEric Biggers 	vec->crypt_error = 0;
242649763fc6SEric Biggers 	if (vec->setkey_error == 0 && vec->setauthsize_error == 0)
2427f900fde2SEric Biggers 		generate_aead_message(rng, req, suite, vec, prefer_inauthentic);
242840153b10SEric Biggers 	snprintf(name, max_namelen,
242949763fc6SEric Biggers 		 "\"random: alen=%u plen=%u authsize=%u klen=%u novrfy=%d\"",
243049763fc6SEric Biggers 		 vec->alen, vec->plen, authsize, vec->klen, vec->novrfy);
243149763fc6SEric Biggers }
243249763fc6SEric Biggers 
try_to_generate_inauthentic_testvec(struct aead_extra_tests_ctx * ctx)243349763fc6SEric Biggers static void try_to_generate_inauthentic_testvec(
243449763fc6SEric Biggers 					struct aead_extra_tests_ctx *ctx)
243549763fc6SEric Biggers {
243649763fc6SEric Biggers 	int i;
243749763fc6SEric Biggers 
243849763fc6SEric Biggers 	for (i = 0; i < 10; i++) {
2439f900fde2SEric Biggers 		generate_random_aead_testvec(&ctx->rng, ctx->req, &ctx->vec,
244049763fc6SEric Biggers 					     &ctx->test_desc->suite.aead,
244149763fc6SEric Biggers 					     ctx->maxkeysize, ctx->maxdatasize,
244249763fc6SEric Biggers 					     ctx->vec_name,
244349763fc6SEric Biggers 					     sizeof(ctx->vec_name), true);
244449763fc6SEric Biggers 		if (ctx->vec.novrfy)
244549763fc6SEric Biggers 			return;
244649763fc6SEric Biggers 	}
244749763fc6SEric Biggers }
244849763fc6SEric Biggers 
244949763fc6SEric Biggers /*
245049763fc6SEric Biggers  * Generate inauthentic test vectors (i.e. ciphertext, AAD pairs that aren't the
245149763fc6SEric Biggers  * result of an encryption with the key) and verify that decryption fails.
245249763fc6SEric Biggers  */
test_aead_inauthentic_inputs(struct aead_extra_tests_ctx * ctx)245349763fc6SEric Biggers static int test_aead_inauthentic_inputs(struct aead_extra_tests_ctx *ctx)
245449763fc6SEric Biggers {
245549763fc6SEric Biggers 	unsigned int i;
245649763fc6SEric Biggers 	int err;
245749763fc6SEric Biggers 
245849763fc6SEric Biggers 	for (i = 0; i < fuzz_iterations * 8; i++) {
245949763fc6SEric Biggers 		/*
246049763fc6SEric Biggers 		 * Since this part of the tests isn't comparing the
246149763fc6SEric Biggers 		 * implementation to another, there's no point in testing any
246249763fc6SEric Biggers 		 * test vectors other than inauthentic ones (vec.novrfy=1) here.
246349763fc6SEric Biggers 		 *
246449763fc6SEric Biggers 		 * If we're having trouble generating such a test vector, e.g.
246549763fc6SEric Biggers 		 * if the algorithm keeps rejecting the generated keys, don't
246649763fc6SEric Biggers 		 * retry forever; just continue on.
246749763fc6SEric Biggers 		 */
246849763fc6SEric Biggers 		try_to_generate_inauthentic_testvec(ctx);
246949763fc6SEric Biggers 		if (ctx->vec.novrfy) {
2470f900fde2SEric Biggers 			generate_random_testvec_config(&ctx->rng, &ctx->cfg,
2471f900fde2SEric Biggers 						       ctx->cfgname,
247249763fc6SEric Biggers 						       sizeof(ctx->cfgname));
24732257f471SEric Biggers 			err = test_aead_vec_cfg(DECRYPT, &ctx->vec,
247449763fc6SEric Biggers 						ctx->vec_name, &ctx->cfg,
247549763fc6SEric Biggers 						ctx->req, ctx->tsgls);
247649763fc6SEric Biggers 			if (err)
247749763fc6SEric Biggers 				return err;
247849763fc6SEric Biggers 		}
247949763fc6SEric Biggers 		cond_resched();
248049763fc6SEric Biggers 	}
248149763fc6SEric Biggers 	return 0;
248240153b10SEric Biggers }
248340153b10SEric Biggers 
248440153b10SEric Biggers /*
24852ea91505SEric Biggers  * Test the AEAD algorithm against the corresponding generic implementation, if
24862ea91505SEric Biggers  * one is available.
248740153b10SEric Biggers  */
test_aead_vs_generic_impl(struct aead_extra_tests_ctx * ctx)24882ea91505SEric Biggers static int test_aead_vs_generic_impl(struct aead_extra_tests_ctx *ctx)
248940153b10SEric Biggers {
24902ea91505SEric Biggers 	struct crypto_aead *tfm = ctx->tfm;
249140153b10SEric Biggers 	const char *algname = crypto_aead_alg(tfm)->base.cra_name;
24922257f471SEric Biggers 	const char *driver = crypto_aead_driver_name(tfm);
24932ea91505SEric Biggers 	const char *generic_driver = ctx->test_desc->generic_driver;
249440153b10SEric Biggers 	char _generic_driver[CRYPTO_MAX_ALG_NAME];
249540153b10SEric Biggers 	struct crypto_aead *generic_tfm = NULL;
249640153b10SEric Biggers 	struct aead_request *generic_req = NULL;
249740153b10SEric Biggers 	unsigned int i;
249840153b10SEric Biggers 	int err;
249940153b10SEric Biggers 
250040153b10SEric Biggers 	if (!generic_driver) { /* Use default naming convention? */
250140153b10SEric Biggers 		err = build_generic_driver_name(algname, _generic_driver);
250240153b10SEric Biggers 		if (err)
250340153b10SEric Biggers 			return err;
250440153b10SEric Biggers 		generic_driver = _generic_driver;
250540153b10SEric Biggers 	}
250640153b10SEric Biggers 
250740153b10SEric Biggers 	if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */
250840153b10SEric Biggers 		return 0;
250940153b10SEric Biggers 
251040153b10SEric Biggers 	generic_tfm = crypto_alloc_aead(generic_driver, 0, 0);
251140153b10SEric Biggers 	if (IS_ERR(generic_tfm)) {
251240153b10SEric Biggers 		err = PTR_ERR(generic_tfm);
251340153b10SEric Biggers 		if (err == -ENOENT) {
251440153b10SEric Biggers 			pr_warn("alg: aead: skipping comparison tests for %s because %s is unavailable\n",
251540153b10SEric Biggers 				driver, generic_driver);
251640153b10SEric Biggers 			return 0;
251740153b10SEric Biggers 		}
251840153b10SEric Biggers 		pr_err("alg: aead: error allocating %s (generic impl of %s): %d\n",
251940153b10SEric Biggers 		       generic_driver, algname, err);
252040153b10SEric Biggers 		return err;
252140153b10SEric Biggers 	}
252240153b10SEric Biggers 
252340153b10SEric Biggers 	generic_req = aead_request_alloc(generic_tfm, GFP_KERNEL);
252440153b10SEric Biggers 	if (!generic_req) {
252540153b10SEric Biggers 		err = -ENOMEM;
252640153b10SEric Biggers 		goto out;
252740153b10SEric Biggers 	}
252840153b10SEric Biggers 
252940153b10SEric Biggers 	/* Check the algorithm properties for consistency. */
253040153b10SEric Biggers 
25312ea91505SEric Biggers 	if (crypto_aead_maxauthsize(tfm) !=
25322ea91505SEric Biggers 	    crypto_aead_maxauthsize(generic_tfm)) {
253340153b10SEric Biggers 		pr_err("alg: aead: maxauthsize for %s (%u) doesn't match generic impl (%u)\n",
25342ea91505SEric Biggers 		       driver, crypto_aead_maxauthsize(tfm),
25352ea91505SEric Biggers 		       crypto_aead_maxauthsize(generic_tfm));
253640153b10SEric Biggers 		err = -EINVAL;
253740153b10SEric Biggers 		goto out;
253840153b10SEric Biggers 	}
253940153b10SEric Biggers 
25402ea91505SEric Biggers 	if (crypto_aead_ivsize(tfm) != crypto_aead_ivsize(generic_tfm)) {
254140153b10SEric Biggers 		pr_err("alg: aead: ivsize for %s (%u) doesn't match generic impl (%u)\n",
25422ea91505SEric Biggers 		       driver, crypto_aead_ivsize(tfm),
25432ea91505SEric Biggers 		       crypto_aead_ivsize(generic_tfm));
254440153b10SEric Biggers 		err = -EINVAL;
254540153b10SEric Biggers 		goto out;
254640153b10SEric Biggers 	}
254740153b10SEric Biggers 
25482ea91505SEric Biggers 	if (crypto_aead_blocksize(tfm) != crypto_aead_blocksize(generic_tfm)) {
254940153b10SEric Biggers 		pr_err("alg: aead: blocksize for %s (%u) doesn't match generic impl (%u)\n",
25502ea91505SEric Biggers 		       driver, crypto_aead_blocksize(tfm),
25512ea91505SEric Biggers 		       crypto_aead_blocksize(generic_tfm));
255240153b10SEric Biggers 		err = -EINVAL;
255340153b10SEric Biggers 		goto out;
255440153b10SEric Biggers 	}
255540153b10SEric Biggers 
255640153b10SEric Biggers 	/*
255740153b10SEric Biggers 	 * Now generate test vectors using the generic implementation, and test
255840153b10SEric Biggers 	 * the other implementation against them.
255940153b10SEric Biggers 	 */
256040153b10SEric Biggers 	for (i = 0; i < fuzz_iterations * 8; i++) {
2561f900fde2SEric Biggers 		generate_random_aead_testvec(&ctx->rng, generic_req, &ctx->vec,
256249763fc6SEric Biggers 					     &ctx->test_desc->suite.aead,
25632ea91505SEric Biggers 					     ctx->maxkeysize, ctx->maxdatasize,
25642ea91505SEric Biggers 					     ctx->vec_name,
256549763fc6SEric Biggers 					     sizeof(ctx->vec_name), false);
2566f900fde2SEric Biggers 		generate_random_testvec_config(&ctx->rng, &ctx->cfg,
2567f900fde2SEric Biggers 					       ctx->cfgname,
25682ea91505SEric Biggers 					       sizeof(ctx->cfgname));
256949763fc6SEric Biggers 		if (!ctx->vec.novrfy) {
25702257f471SEric Biggers 			err = test_aead_vec_cfg(ENCRYPT, &ctx->vec,
25712ea91505SEric Biggers 						ctx->vec_name, &ctx->cfg,
25722ea91505SEric Biggers 						ctx->req, ctx->tsgls);
257340153b10SEric Biggers 			if (err)
257440153b10SEric Biggers 				goto out;
257549763fc6SEric Biggers 		}
257649763fc6SEric Biggers 		if (ctx->vec.crypt_error == 0 || ctx->vec.novrfy) {
25772257f471SEric Biggers 			err = test_aead_vec_cfg(DECRYPT, &ctx->vec,
25782ea91505SEric Biggers 						ctx->vec_name, &ctx->cfg,
25792ea91505SEric Biggers 						ctx->req, ctx->tsgls);
258040153b10SEric Biggers 			if (err)
258140153b10SEric Biggers 				goto out;
2582eb455dbdSEric Biggers 		}
258340153b10SEric Biggers 		cond_resched();
258440153b10SEric Biggers 	}
258540153b10SEric Biggers 	err = 0;
258640153b10SEric Biggers out:
258740153b10SEric Biggers 	crypto_free_aead(generic_tfm);
258840153b10SEric Biggers 	aead_request_free(generic_req);
258940153b10SEric Biggers 	return err;
259040153b10SEric Biggers }
25912ea91505SEric Biggers 
test_aead_extra(const struct alg_test_desc * test_desc,struct aead_request * req,struct cipher_test_sglists * tsgls)25922257f471SEric Biggers static int test_aead_extra(const struct alg_test_desc *test_desc,
25932ea91505SEric Biggers 			   struct aead_request *req,
25942ea91505SEric Biggers 			   struct cipher_test_sglists *tsgls)
25952ea91505SEric Biggers {
25962ea91505SEric Biggers 	struct aead_extra_tests_ctx *ctx;
25972ea91505SEric Biggers 	unsigned int i;
25982ea91505SEric Biggers 	int err;
25992ea91505SEric Biggers 
26002ea91505SEric Biggers 	if (noextratests)
26012ea91505SEric Biggers 		return 0;
26022ea91505SEric Biggers 
26032ea91505SEric Biggers 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
26042ea91505SEric Biggers 	if (!ctx)
26052ea91505SEric Biggers 		return -ENOMEM;
2606f900fde2SEric Biggers 	init_rnd_state(&ctx->rng);
26072ea91505SEric Biggers 	ctx->req = req;
26082ea91505SEric Biggers 	ctx->tfm = crypto_aead_reqtfm(req);
26092ea91505SEric Biggers 	ctx->test_desc = test_desc;
26102ea91505SEric Biggers 	ctx->tsgls = tsgls;
26112ea91505SEric Biggers 	ctx->maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
26122ea91505SEric Biggers 	ctx->maxkeysize = 0;
26132ea91505SEric Biggers 	for (i = 0; i < test_desc->suite.aead.count; i++)
26142ea91505SEric Biggers 		ctx->maxkeysize = max_t(unsigned int, ctx->maxkeysize,
26152ea91505SEric Biggers 					test_desc->suite.aead.vecs[i].klen);
26162ea91505SEric Biggers 
26172ea91505SEric Biggers 	ctx->vec.key = kmalloc(ctx->maxkeysize, GFP_KERNEL);
26182ea91505SEric Biggers 	ctx->vec.iv = kmalloc(crypto_aead_ivsize(ctx->tfm), GFP_KERNEL);
26192ea91505SEric Biggers 	ctx->vec.assoc = kmalloc(ctx->maxdatasize, GFP_KERNEL);
26202ea91505SEric Biggers 	ctx->vec.ptext = kmalloc(ctx->maxdatasize, GFP_KERNEL);
26212ea91505SEric Biggers 	ctx->vec.ctext = kmalloc(ctx->maxdatasize, GFP_KERNEL);
26222ea91505SEric Biggers 	if (!ctx->vec.key || !ctx->vec.iv || !ctx->vec.assoc ||
26232ea91505SEric Biggers 	    !ctx->vec.ptext || !ctx->vec.ctext) {
26242ea91505SEric Biggers 		err = -ENOMEM;
26252ea91505SEric Biggers 		goto out;
26262ea91505SEric Biggers 	}
26272ea91505SEric Biggers 
26288ff357a9SEric Biggers 	err = test_aead_vs_generic_impl(ctx);
262949763fc6SEric Biggers 	if (err)
263049763fc6SEric Biggers 		goto out;
263149763fc6SEric Biggers 
26328ff357a9SEric Biggers 	err = test_aead_inauthentic_inputs(ctx);
26332ea91505SEric Biggers out:
26342ea91505SEric Biggers 	kfree(ctx->vec.key);
26352ea91505SEric Biggers 	kfree(ctx->vec.iv);
26362ea91505SEric Biggers 	kfree(ctx->vec.assoc);
26372ea91505SEric Biggers 	kfree(ctx->vec.ptext);
26382ea91505SEric Biggers 	kfree(ctx->vec.ctext);
26392ea91505SEric Biggers 	kfree(ctx);
26402ea91505SEric Biggers 	return err;
26412ea91505SEric Biggers }
264240153b10SEric Biggers #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
test_aead_extra(const struct alg_test_desc * test_desc,struct aead_request * req,struct cipher_test_sglists * tsgls)26432257f471SEric Biggers static int test_aead_extra(const struct alg_test_desc *test_desc,
264440153b10SEric Biggers 			   struct aead_request *req,
264540153b10SEric Biggers 			   struct cipher_test_sglists *tsgls)
264640153b10SEric Biggers {
264740153b10SEric Biggers 	return 0;
264840153b10SEric Biggers }
264940153b10SEric Biggers #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
265040153b10SEric Biggers 
test_aead(int enc,const struct aead_test_suite * suite,struct aead_request * req,struct cipher_test_sglists * tsgls)26512257f471SEric Biggers static int test_aead(int enc, const struct aead_test_suite *suite,
2652ed96804fSEric Biggers 		     struct aead_request *req,
2653ed96804fSEric Biggers 		     struct cipher_test_sglists *tsgls)
2654ed96804fSEric Biggers {
2655ed96804fSEric Biggers 	unsigned int i;
2656ed96804fSEric Biggers 	int err;
2657ed96804fSEric Biggers 
2658ed96804fSEric Biggers 	for (i = 0; i < suite->count; i++) {
26592257f471SEric Biggers 		err = test_aead_vec(enc, &suite->vecs[i], i, req, tsgls);
2660ed96804fSEric Biggers 		if (err)
2661ed96804fSEric Biggers 			return err;
2662e63e1b0dSEric Biggers 		cond_resched();
2663ed96804fSEric Biggers 	}
2664ed96804fSEric Biggers 	return 0;
2665ed96804fSEric Biggers }
2666ed96804fSEric Biggers 
alg_test_aead(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)2667ed96804fSEric Biggers static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
2668ed96804fSEric Biggers 			 u32 type, u32 mask)
2669ed96804fSEric Biggers {
2670ed96804fSEric Biggers 	const struct aead_test_suite *suite = &desc->suite.aead;
2671ed96804fSEric Biggers 	struct crypto_aead *tfm;
2672ed96804fSEric Biggers 	struct aead_request *req = NULL;
2673ed96804fSEric Biggers 	struct cipher_test_sglists *tsgls = NULL;
2674ed96804fSEric Biggers 	int err;
2675ed96804fSEric Biggers 
2676ed96804fSEric Biggers 	if (suite->count <= 0) {
2677ed96804fSEric Biggers 		pr_err("alg: aead: empty test suite for %s\n", driver);
2678ed96804fSEric Biggers 		return -EINVAL;
2679ed96804fSEric Biggers 	}
2680ed96804fSEric Biggers 
2681ed96804fSEric Biggers 	tfm = crypto_alloc_aead(driver, type, mask);
2682ed96804fSEric Biggers 	if (IS_ERR(tfm)) {
2683ed96804fSEric Biggers 		pr_err("alg: aead: failed to allocate transform for %s: %ld\n",
2684ed96804fSEric Biggers 		       driver, PTR_ERR(tfm));
2685ed96804fSEric Biggers 		return PTR_ERR(tfm);
2686ed96804fSEric Biggers 	}
26872257f471SEric Biggers 	driver = crypto_aead_driver_name(tfm);
2688ed96804fSEric Biggers 
2689ed96804fSEric Biggers 	req = aead_request_alloc(tfm, GFP_KERNEL);
2690ed96804fSEric Biggers 	if (!req) {
2691ed96804fSEric Biggers 		pr_err("alg: aead: failed to allocate request for %s\n",
2692ed96804fSEric Biggers 		       driver);
2693ed96804fSEric Biggers 		err = -ENOMEM;
2694ed96804fSEric Biggers 		goto out;
2695ed96804fSEric Biggers 	}
2696ed96804fSEric Biggers 
2697ed96804fSEric Biggers 	tsgls = alloc_cipher_test_sglists();
2698ed96804fSEric Biggers 	if (!tsgls) {
2699ed96804fSEric Biggers 		pr_err("alg: aead: failed to allocate test buffers for %s\n",
2700ed96804fSEric Biggers 		       driver);
2701ed96804fSEric Biggers 		err = -ENOMEM;
2702ed96804fSEric Biggers 		goto out;
2703ed96804fSEric Biggers 	}
2704ed96804fSEric Biggers 
27052257f471SEric Biggers 	err = test_aead(ENCRYPT, suite, req, tsgls);
2706ed96804fSEric Biggers 	if (err)
2707ed96804fSEric Biggers 		goto out;
2708ed96804fSEric Biggers 
27092257f471SEric Biggers 	err = test_aead(DECRYPT, suite, req, tsgls);
271040153b10SEric Biggers 	if (err)
271140153b10SEric Biggers 		goto out;
271240153b10SEric Biggers 
27132257f471SEric Biggers 	err = test_aead_extra(desc, req, tsgls);
2714ed96804fSEric Biggers out:
2715ed96804fSEric Biggers 	free_cipher_test_sglists(tsgls);
2716ed96804fSEric Biggers 	aead_request_free(req);
2717ed96804fSEric Biggers 	crypto_free_aead(tfm);
2718ed96804fSEric Biggers 	return err;
2719ed96804fSEric Biggers }
2720ed96804fSEric Biggers 
test_cipher(struct crypto_cipher * tfm,int enc,const struct cipher_testvec * template,unsigned int tcount)27211aa4ecd9SHerbert Xu static int test_cipher(struct crypto_cipher *tfm, int enc,
2722b13b1e0cSEric Biggers 		       const struct cipher_testvec *template,
2723b13b1e0cSEric Biggers 		       unsigned int tcount)
27241aa4ecd9SHerbert Xu {
27251aa4ecd9SHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
27261aa4ecd9SHerbert Xu 	unsigned int i, j, k;
27271aa4ecd9SHerbert Xu 	char *q;
27281aa4ecd9SHerbert Xu 	const char *e;
272992a4c9feSEric Biggers 	const char *input, *result;
27301aa4ecd9SHerbert Xu 	void *data;
2731f8b0d4d0SHerbert Xu 	char *xbuf[XBUFSIZE];
2732f8b0d4d0SHerbert Xu 	int ret = -ENOMEM;
2733f8b0d4d0SHerbert Xu 
2734f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(xbuf))
2735f8b0d4d0SHerbert Xu 		goto out_nobuf;
27361aa4ecd9SHerbert Xu 
27371aa4ecd9SHerbert Xu 	if (enc == ENCRYPT)
27381aa4ecd9SHerbert Xu 	        e = "encryption";
27391aa4ecd9SHerbert Xu 	else
27401aa4ecd9SHerbert Xu 		e = "decryption";
27411aa4ecd9SHerbert Xu 
27421aa4ecd9SHerbert Xu 	j = 0;
27431aa4ecd9SHerbert Xu 	for (i = 0; i < tcount; i++) {
27441aa4ecd9SHerbert Xu 
274510faa8c0SStephan Mueller 		if (fips_enabled && template[i].fips_skip)
274610faa8c0SStephan Mueller 			continue;
274710faa8c0SStephan Mueller 
274892a4c9feSEric Biggers 		input  = enc ? template[i].ptext : template[i].ctext;
274992a4c9feSEric Biggers 		result = enc ? template[i].ctext : template[i].ptext;
27501aa4ecd9SHerbert Xu 		j++;
27511aa4ecd9SHerbert Xu 
2752fd57f22aSHerbert Xu 		ret = -EINVAL;
275392a4c9feSEric Biggers 		if (WARN_ON(template[i].len > PAGE_SIZE))
2754fd57f22aSHerbert Xu 			goto out;
2755fd57f22aSHerbert Xu 
27561aa4ecd9SHerbert Xu 		data = xbuf[0];
275792a4c9feSEric Biggers 		memcpy(data, input, template[i].len);
27581aa4ecd9SHerbert Xu 
27591aa4ecd9SHerbert Xu 		crypto_cipher_clear_flags(tfm, ~0);
27601aa4ecd9SHerbert Xu 		if (template[i].wk)
2761231baecdSEric Biggers 			crypto_cipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
27621aa4ecd9SHerbert Xu 
27631aa4ecd9SHerbert Xu 		ret = crypto_cipher_setkey(tfm, template[i].key,
27641aa4ecd9SHerbert Xu 					   template[i].klen);
27655283a8eeSEric Biggers 		if (ret) {
27665283a8eeSEric Biggers 			if (ret == template[i].setkey_error)
27671aa4ecd9SHerbert Xu 				continue;
27685283a8eeSEric Biggers 			pr_err("alg: cipher: %s setkey failed on test vector %u; expected_error=%d, actual_error=%d, flags=%#x\n",
27695283a8eeSEric Biggers 			       algo, j, template[i].setkey_error, ret,
27705283a8eeSEric Biggers 			       crypto_cipher_get_flags(tfm));
27715283a8eeSEric Biggers 			goto out;
27725283a8eeSEric Biggers 		}
27735283a8eeSEric Biggers 		if (template[i].setkey_error) {
27745283a8eeSEric Biggers 			pr_err("alg: cipher: %s setkey unexpectedly succeeded on test vector %u; expected_error=%d\n",
27755283a8eeSEric Biggers 			       algo, j, template[i].setkey_error);
27765283a8eeSEric Biggers 			ret = -EINVAL;
27775283a8eeSEric Biggers 			goto out;
27785283a8eeSEric Biggers 		}
27791aa4ecd9SHerbert Xu 
278092a4c9feSEric Biggers 		for (k = 0; k < template[i].len;
27811aa4ecd9SHerbert Xu 		     k += crypto_cipher_blocksize(tfm)) {
27821aa4ecd9SHerbert Xu 			if (enc)
27831aa4ecd9SHerbert Xu 				crypto_cipher_encrypt_one(tfm, data + k,
27841aa4ecd9SHerbert Xu 							  data + k);
27851aa4ecd9SHerbert Xu 			else
27861aa4ecd9SHerbert Xu 				crypto_cipher_decrypt_one(tfm, data + k,
27871aa4ecd9SHerbert Xu 							  data + k);
27881aa4ecd9SHerbert Xu 		}
27891aa4ecd9SHerbert Xu 
27901aa4ecd9SHerbert Xu 		q = data;
279192a4c9feSEric Biggers 		if (memcmp(q, result, template[i].len)) {
27921aa4ecd9SHerbert Xu 			printk(KERN_ERR "alg: cipher: Test %d failed "
27931aa4ecd9SHerbert Xu 			       "on %s for %s\n", j, e, algo);
279492a4c9feSEric Biggers 			hexdump(q, template[i].len);
27951aa4ecd9SHerbert Xu 			ret = -EINVAL;
27961aa4ecd9SHerbert Xu 			goto out;
27971aa4ecd9SHerbert Xu 		}
27981aa4ecd9SHerbert Xu 	}
27991aa4ecd9SHerbert Xu 
28001aa4ecd9SHerbert Xu 	ret = 0;
28011aa4ecd9SHerbert Xu 
28021aa4ecd9SHerbert Xu out:
2803f8b0d4d0SHerbert Xu 	testmgr_free_buf(xbuf);
2804f8b0d4d0SHerbert Xu out_nobuf:
28051aa4ecd9SHerbert Xu 	return ret;
28061aa4ecd9SHerbert Xu }
28071aa4ecd9SHerbert Xu 
test_skcipher_vec_cfg(int enc,const struct cipher_testvec * vec,const char * vec_name,const struct testvec_config * cfg,struct skcipher_request * req,struct cipher_test_sglists * tsgls)28086e5972faSEric Biggers static int test_skcipher_vec_cfg(int enc, const struct cipher_testvec *vec,
2809951d1332SEric Biggers 				 const char *vec_name,
28104e7babbaSEric Biggers 				 const struct testvec_config *cfg,
28114e7babbaSEric Biggers 				 struct skcipher_request *req,
28124e7babbaSEric Biggers 				 struct cipher_test_sglists *tsgls)
2813da7f033dSHerbert Xu {
28144e7babbaSEric Biggers 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
28154e7babbaSEric Biggers 	const unsigned int alignmask = crypto_skcipher_alignmask(tfm);
28164e7babbaSEric Biggers 	const unsigned int ivsize = crypto_skcipher_ivsize(tfm);
28176e5972faSEric Biggers 	const char *driver = crypto_skcipher_driver_name(tfm);
28184e7babbaSEric Biggers 	const u32 req_flags = CRYPTO_TFM_REQ_MAY_BACKLOG | cfg->req_flags;
28194e7babbaSEric Biggers 	const char *op = enc ? "encryption" : "decryption";
28204e7babbaSEric Biggers 	DECLARE_CRYPTO_WAIT(wait);
28214e7babbaSEric Biggers 	u8 _iv[3 * (MAX_ALGAPI_ALIGNMASK + 1) + MAX_IVLEN];
28224e7babbaSEric Biggers 	u8 *iv = PTR_ALIGN(&_iv[0], 2 * (MAX_ALGAPI_ALIGNMASK + 1)) +
28234e7babbaSEric Biggers 		 cfg->iv_offset +
28244e7babbaSEric Biggers 		 (cfg->iv_offset_relative_to_alignmask ? alignmask : 0);
28254e7babbaSEric Biggers 	struct kvec input;
28264e7babbaSEric Biggers 	int err;
2827f8b0d4d0SHerbert Xu 
28284e7babbaSEric Biggers 	/* Set the key */
28294e7babbaSEric Biggers 	if (vec->wk)
2830231baecdSEric Biggers 		crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
2831da7f033dSHerbert Xu 	else
28324e7babbaSEric Biggers 		crypto_skcipher_clear_flags(tfm,
28334e7babbaSEric Biggers 					    CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
2834fd8c37c7SEric Biggers 	err = do_setkey(crypto_skcipher_setkey, tfm, vec->key, vec->klen,
2835fd8c37c7SEric Biggers 			cfg, alignmask);
28364e7babbaSEric Biggers 	if (err) {
28375283a8eeSEric Biggers 		if (err == vec->setkey_error)
28384e7babbaSEric Biggers 			return 0;
2839951d1332SEric Biggers 		pr_err("alg: skcipher: %s setkey failed on test vector %s; expected_error=%d, actual_error=%d, flags=%#x\n",
2840951d1332SEric Biggers 		       driver, vec_name, vec->setkey_error, err,
28415283a8eeSEric Biggers 		       crypto_skcipher_get_flags(tfm));
28424e7babbaSEric Biggers 		return err;
28434e7babbaSEric Biggers 	}
28445283a8eeSEric Biggers 	if (vec->setkey_error) {
2845951d1332SEric Biggers 		pr_err("alg: skcipher: %s setkey unexpectedly succeeded on test vector %s; expected_error=%d\n",
2846951d1332SEric Biggers 		       driver, vec_name, vec->setkey_error);
28474e7babbaSEric Biggers 		return -EINVAL;
284808d6af8cSJussi Kivilinna 	}
2849da7f033dSHerbert Xu 
28504e7babbaSEric Biggers 	/* The IV must be copied to a buffer, as the algorithm may modify it */
28514e7babbaSEric Biggers 	if (ivsize) {
28524e7babbaSEric Biggers 		if (WARN_ON(ivsize > MAX_IVLEN))
28534e7babbaSEric Biggers 			return -EINVAL;
28548efd972eSEric Biggers 		if (vec->generates_iv && !enc)
28558efd972eSEric Biggers 			memcpy(iv, vec->iv_out, ivsize);
28568efd972eSEric Biggers 		else if (vec->iv)
28574e7babbaSEric Biggers 			memcpy(iv, vec->iv, ivsize);
285808d6af8cSJussi Kivilinna 		else
28594e7babbaSEric Biggers 			memset(iv, 0, ivsize);
28604e7babbaSEric Biggers 	} else {
28614e7babbaSEric Biggers 		if (vec->generates_iv) {
2862951d1332SEric Biggers 			pr_err("alg: skcipher: %s has ivsize=0 but test vector %s generates IV!\n",
2863951d1332SEric Biggers 			       driver, vec_name);
28644e7babbaSEric Biggers 			return -EINVAL;
28654e7babbaSEric Biggers 		}
28664e7babbaSEric Biggers 		iv = NULL;
2867da7f033dSHerbert Xu 	}
2868da7f033dSHerbert Xu 
28694e7babbaSEric Biggers 	/* Build the src/dst scatterlists */
28704e7babbaSEric Biggers 	input.iov_base = enc ? (void *)vec->ptext : (void *)vec->ctext;
28714e7babbaSEric Biggers 	input.iov_len = vec->len;
28724e7babbaSEric Biggers 	err = build_cipher_test_sglists(tsgls, cfg, alignmask,
28734e7babbaSEric Biggers 					vec->len, vec->len, &input, 1);
28744e7babbaSEric Biggers 	if (err) {
2875951d1332SEric Biggers 		pr_err("alg: skcipher: %s %s: error preparing scatterlists for test vector %s, cfg=\"%s\"\n",
2876951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
28774e7babbaSEric Biggers 		return err;
2878da7f033dSHerbert Xu 	}
2879da7f033dSHerbert Xu 
28804e7babbaSEric Biggers 	/* Do the actual encryption or decryption */
28814e7babbaSEric Biggers 	testmgr_poison(req->__ctx, crypto_skcipher_reqsize(tfm));
28824e7babbaSEric Biggers 	skcipher_request_set_callback(req, req_flags, crypto_req_done, &wait);
28834e7babbaSEric Biggers 	skcipher_request_set_crypt(req, tsgls->src.sgl_ptr, tsgls->dst.sgl_ptr,
28844e7babbaSEric Biggers 				   vec->len, iv);
28856570737cSEric Biggers 	if (cfg->nosimd)
28866570737cSEric Biggers 		crypto_disable_simd_for_test();
28876570737cSEric Biggers 	err = enc ? crypto_skcipher_encrypt(req) : crypto_skcipher_decrypt(req);
28886570737cSEric Biggers 	if (cfg->nosimd)
28896570737cSEric Biggers 		crypto_reenable_simd_for_test();
28906570737cSEric Biggers 	err = crypto_wait_req(err, &wait);
2891da7f033dSHerbert Xu 
2892fa353c99SEric Biggers 	/* Check that the algorithm didn't overwrite things it shouldn't have */
2893fa353c99SEric Biggers 	if (req->cryptlen != vec->len ||
2894fa353c99SEric Biggers 	    req->iv != iv ||
2895fa353c99SEric Biggers 	    req->src != tsgls->src.sgl_ptr ||
2896fa353c99SEric Biggers 	    req->dst != tsgls->dst.sgl_ptr ||
2897fa353c99SEric Biggers 	    crypto_skcipher_reqtfm(req) != tfm ||
2898fa353c99SEric Biggers 	    req->base.complete != crypto_req_done ||
2899fa353c99SEric Biggers 	    req->base.flags != req_flags ||
2900fa353c99SEric Biggers 	    req->base.data != &wait) {
2901951d1332SEric Biggers 		pr_err("alg: skcipher: %s %s corrupted request struct on test vector %s, cfg=\"%s\"\n",
2902951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
2903fa353c99SEric Biggers 		if (req->cryptlen != vec->len)
2904fa353c99SEric Biggers 			pr_err("alg: skcipher: changed 'req->cryptlen'\n");
2905fa353c99SEric Biggers 		if (req->iv != iv)
2906fa353c99SEric Biggers 			pr_err("alg: skcipher: changed 'req->iv'\n");
2907fa353c99SEric Biggers 		if (req->src != tsgls->src.sgl_ptr)
2908fa353c99SEric Biggers 			pr_err("alg: skcipher: changed 'req->src'\n");
2909fa353c99SEric Biggers 		if (req->dst != tsgls->dst.sgl_ptr)
2910fa353c99SEric Biggers 			pr_err("alg: skcipher: changed 'req->dst'\n");
2911fa353c99SEric Biggers 		if (crypto_skcipher_reqtfm(req) != tfm)
2912fa353c99SEric Biggers 			pr_err("alg: skcipher: changed 'req->base.tfm'\n");
2913fa353c99SEric Biggers 		if (req->base.complete != crypto_req_done)
2914fa353c99SEric Biggers 			pr_err("alg: skcipher: changed 'req->base.complete'\n");
2915fa353c99SEric Biggers 		if (req->base.flags != req_flags)
2916fa353c99SEric Biggers 			pr_err("alg: skcipher: changed 'req->base.flags'\n");
2917fa353c99SEric Biggers 		if (req->base.data != &wait)
2918fa353c99SEric Biggers 			pr_err("alg: skcipher: changed 'req->base.data'\n");
2919fa353c99SEric Biggers 		return -EINVAL;
2920fa353c99SEric Biggers 	}
2921fa353c99SEric Biggers 	if (is_test_sglist_corrupted(&tsgls->src)) {
2922951d1332SEric Biggers 		pr_err("alg: skcipher: %s %s corrupted src sgl on test vector %s, cfg=\"%s\"\n",
2923951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
2924fa353c99SEric Biggers 		return -EINVAL;
2925fa353c99SEric Biggers 	}
2926fa353c99SEric Biggers 	if (tsgls->dst.sgl_ptr != tsgls->src.sgl &&
2927fa353c99SEric Biggers 	    is_test_sglist_corrupted(&tsgls->dst)) {
2928951d1332SEric Biggers 		pr_err("alg: skcipher: %s %s corrupted dst sgl on test vector %s, cfg=\"%s\"\n",
2929951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
2930fa353c99SEric Biggers 		return -EINVAL;
2931fa353c99SEric Biggers 	}
2932fa353c99SEric Biggers 
29335283a8eeSEric Biggers 	/* Check for success or failure */
29345283a8eeSEric Biggers 	if (err) {
29355283a8eeSEric Biggers 		if (err == vec->crypt_error)
29365283a8eeSEric Biggers 			return 0;
2937951d1332SEric Biggers 		pr_err("alg: skcipher: %s %s failed on test vector %s; expected_error=%d, actual_error=%d, cfg=\"%s\"\n",
2938951d1332SEric Biggers 		       driver, op, vec_name, vec->crypt_error, err, cfg->name);
29395283a8eeSEric Biggers 		return err;
29405283a8eeSEric Biggers 	}
29415283a8eeSEric Biggers 	if (vec->crypt_error) {
2942951d1332SEric Biggers 		pr_err("alg: skcipher: %s %s unexpectedly succeeded on test vector %s; expected_error=%d, cfg=\"%s\"\n",
2943951d1332SEric Biggers 		       driver, op, vec_name, vec->crypt_error, cfg->name);
29445283a8eeSEric Biggers 		return -EINVAL;
29455283a8eeSEric Biggers 	}
29465283a8eeSEric Biggers 
29474e7babbaSEric Biggers 	/* Check for the correct output (ciphertext or plaintext) */
29484e7babbaSEric Biggers 	err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext,
29494e7babbaSEric Biggers 				    vec->len, 0, true);
29504e7babbaSEric Biggers 	if (err == -EOVERFLOW) {
2951951d1332SEric Biggers 		pr_err("alg: skcipher: %s %s overran dst buffer on test vector %s, cfg=\"%s\"\n",
2952951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
29534e7babbaSEric Biggers 		return err;
29544e7babbaSEric Biggers 	}
29554e7babbaSEric Biggers 	if (err) {
2956951d1332SEric Biggers 		pr_err("alg: skcipher: %s %s test failed (wrong result) on test vector %s, cfg=\"%s\"\n",
2957951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
29584e7babbaSEric Biggers 		return err;
29594e7babbaSEric Biggers 	}
296008d6af8cSJussi Kivilinna 
29614e7babbaSEric Biggers 	/* If applicable, check that the algorithm generated the correct IV */
29628efd972eSEric Biggers 	if (vec->iv_out && memcmp(iv, vec->iv_out, ivsize) != 0) {
2963951d1332SEric Biggers 		pr_err("alg: skcipher: %s %s test failed (wrong output IV) on test vector %s, cfg=\"%s\"\n",
2964951d1332SEric Biggers 		       driver, op, vec_name, cfg->name);
29654e7babbaSEric Biggers 		hexdump(iv, ivsize);
29664e7babbaSEric Biggers 		return -EINVAL;
29673a338f20SJussi Kivilinna 	}
29683a338f20SJussi Kivilinna 
29693a338f20SJussi Kivilinna 	return 0;
297008d6af8cSJussi Kivilinna }
297108d6af8cSJussi Kivilinna 
test_skcipher_vec(int enc,const struct cipher_testvec * vec,unsigned int vec_num,struct skcipher_request * req,struct cipher_test_sglists * tsgls)29726e5972faSEric Biggers static int test_skcipher_vec(int enc, const struct cipher_testvec *vec,
29734e7babbaSEric Biggers 			     unsigned int vec_num,
29744e7babbaSEric Biggers 			     struct skcipher_request *req,
29754e7babbaSEric Biggers 			     struct cipher_test_sglists *tsgls)
29764e7babbaSEric Biggers {
2977951d1332SEric Biggers 	char vec_name[16];
29784e7babbaSEric Biggers 	unsigned int i;
29794e7babbaSEric Biggers 	int err;
29804e7babbaSEric Biggers 
29814e7babbaSEric Biggers 	if (fips_enabled && vec->fips_skip)
29824e7babbaSEric Biggers 		return 0;
29834e7babbaSEric Biggers 
2984951d1332SEric Biggers 	sprintf(vec_name, "%u", vec_num);
2985951d1332SEric Biggers 
29864e7babbaSEric Biggers 	for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++) {
29876e5972faSEric Biggers 		err = test_skcipher_vec_cfg(enc, vec, vec_name,
29884e7babbaSEric Biggers 					    &default_cipher_testvec_configs[i],
29894e7babbaSEric Biggers 					    req, tsgls);
29904e7babbaSEric Biggers 		if (err)
29914e7babbaSEric Biggers 			return err;
29924e7babbaSEric Biggers 	}
29934e7babbaSEric Biggers 
29944e7babbaSEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
29954e7babbaSEric Biggers 	if (!noextratests) {
2996f900fde2SEric Biggers 		struct rnd_state rng;
29974e7babbaSEric Biggers 		struct testvec_config cfg;
29984e7babbaSEric Biggers 		char cfgname[TESTVEC_CONFIG_NAMELEN];
29994e7babbaSEric Biggers 
3000f900fde2SEric Biggers 		init_rnd_state(&rng);
3001f900fde2SEric Biggers 
30024e7babbaSEric Biggers 		for (i = 0; i < fuzz_iterations; i++) {
3003f900fde2SEric Biggers 			generate_random_testvec_config(&rng, &cfg, cfgname,
30044e7babbaSEric Biggers 						       sizeof(cfgname));
30056e5972faSEric Biggers 			err = test_skcipher_vec_cfg(enc, vec, vec_name,
30064e7babbaSEric Biggers 						    &cfg, req, tsgls);
30074e7babbaSEric Biggers 			if (err)
30084e7babbaSEric Biggers 				return err;
3009e63e1b0dSEric Biggers 			cond_resched();
30104e7babbaSEric Biggers 		}
30114e7babbaSEric Biggers 	}
30124e7babbaSEric Biggers #endif
30134e7babbaSEric Biggers 	return 0;
30144e7babbaSEric Biggers }
30154e7babbaSEric Biggers 
3016d435e10eSEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
3017d435e10eSEric Biggers /*
3018d435e10eSEric Biggers  * Generate a symmetric cipher test vector from the given implementation.
3019d435e10eSEric Biggers  * Assumes the buffers in 'vec' were already allocated.
3020d435e10eSEric Biggers  */
generate_random_cipher_testvec(struct rnd_state * rng,struct skcipher_request * req,struct cipher_testvec * vec,unsigned int maxdatasize,char * name,size_t max_namelen)3021f900fde2SEric Biggers static void generate_random_cipher_testvec(struct rnd_state *rng,
3022f900fde2SEric Biggers 					   struct skcipher_request *req,
3023d435e10eSEric Biggers 					   struct cipher_testvec *vec,
3024d435e10eSEric Biggers 					   unsigned int maxdatasize,
3025d435e10eSEric Biggers 					   char *name, size_t max_namelen)
3026d435e10eSEric Biggers {
3027d435e10eSEric Biggers 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
30289ac0d136SEric Biggers 	const unsigned int maxkeysize = crypto_skcipher_max_keysize(tfm);
3029d435e10eSEric Biggers 	const unsigned int ivsize = crypto_skcipher_ivsize(tfm);
3030d435e10eSEric Biggers 	struct scatterlist src, dst;
3031d435e10eSEric Biggers 	u8 iv[MAX_IVLEN];
3032d435e10eSEric Biggers 	DECLARE_CRYPTO_WAIT(wait);
3033d435e10eSEric Biggers 
3034d435e10eSEric Biggers 	/* Key: length in [0, maxkeysize], but usually choose maxkeysize */
3035d435e10eSEric Biggers 	vec->klen = maxkeysize;
3036f900fde2SEric Biggers 	if (prandom_u32_below(rng, 4) == 0)
3037f900fde2SEric Biggers 		vec->klen = prandom_u32_below(rng, maxkeysize + 1);
3038f900fde2SEric Biggers 	generate_random_bytes(rng, (u8 *)vec->key, vec->klen);
3039d435e10eSEric Biggers 	vec->setkey_error = crypto_skcipher_setkey(tfm, vec->key, vec->klen);
3040d435e10eSEric Biggers 
3041d435e10eSEric Biggers 	/* IV */
3042f900fde2SEric Biggers 	generate_random_bytes(rng, (u8 *)vec->iv, ivsize);
3043d435e10eSEric Biggers 
3044d435e10eSEric Biggers 	/* Plaintext */
3045f900fde2SEric Biggers 	vec->len = generate_random_length(rng, maxdatasize);
3046f900fde2SEric Biggers 	generate_random_bytes(rng, (u8 *)vec->ptext, vec->len);
3047d435e10eSEric Biggers 
3048d435e10eSEric Biggers 	/* If the key couldn't be set, no need to continue to encrypt. */
3049d435e10eSEric Biggers 	if (vec->setkey_error)
3050d435e10eSEric Biggers 		goto done;
3051d435e10eSEric Biggers 
3052d435e10eSEric Biggers 	/* Ciphertext */
3053d435e10eSEric Biggers 	sg_init_one(&src, vec->ptext, vec->len);
3054d435e10eSEric Biggers 	sg_init_one(&dst, vec->ctext, vec->len);
3055d435e10eSEric Biggers 	memcpy(iv, vec->iv, ivsize);
3056d435e10eSEric Biggers 	skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
3057d435e10eSEric Biggers 	skcipher_request_set_crypt(req, &src, &dst, vec->len, iv);
3058d435e10eSEric Biggers 	vec->crypt_error = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
3059eb455dbdSEric Biggers 	if (vec->crypt_error != 0) {
3060eb455dbdSEric Biggers 		/*
3061eb455dbdSEric Biggers 		 * The only acceptable error here is for an invalid length, so
3062eb455dbdSEric Biggers 		 * skcipher decryption should fail with the same error too.
3063eb455dbdSEric Biggers 		 * We'll test for this.  But to keep the API usage well-defined,
3064eb455dbdSEric Biggers 		 * explicitly initialize the ciphertext buffer too.
3065eb455dbdSEric Biggers 		 */
3066eb455dbdSEric Biggers 		memset((u8 *)vec->ctext, 0, vec->len);
3067eb455dbdSEric Biggers 	}
3068d435e10eSEric Biggers done:
3069d435e10eSEric Biggers 	snprintf(name, max_namelen, "\"random: len=%u klen=%u\"",
3070d435e10eSEric Biggers 		 vec->len, vec->klen);
3071d435e10eSEric Biggers }
3072d435e10eSEric Biggers 
3073d435e10eSEric Biggers /*
3074d435e10eSEric Biggers  * Test the skcipher algorithm represented by @req against the corresponding
3075d435e10eSEric Biggers  * generic implementation, if one is available.
3076d435e10eSEric Biggers  */
test_skcipher_vs_generic_impl(const char * generic_driver,struct skcipher_request * req,struct cipher_test_sglists * tsgls)30776e5972faSEric Biggers static int test_skcipher_vs_generic_impl(const char *generic_driver,
3078d435e10eSEric Biggers 					 struct skcipher_request *req,
3079d435e10eSEric Biggers 					 struct cipher_test_sglists *tsgls)
3080d435e10eSEric Biggers {
3081d435e10eSEric Biggers 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
30829ac0d136SEric Biggers 	const unsigned int maxkeysize = crypto_skcipher_max_keysize(tfm);
3083d435e10eSEric Biggers 	const unsigned int ivsize = crypto_skcipher_ivsize(tfm);
3084d435e10eSEric Biggers 	const unsigned int blocksize = crypto_skcipher_blocksize(tfm);
3085d435e10eSEric Biggers 	const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
3086d435e10eSEric Biggers 	const char *algname = crypto_skcipher_alg(tfm)->base.cra_name;
30876e5972faSEric Biggers 	const char *driver = crypto_skcipher_driver_name(tfm);
3088f900fde2SEric Biggers 	struct rnd_state rng;
3089d435e10eSEric Biggers 	char _generic_driver[CRYPTO_MAX_ALG_NAME];
3090d435e10eSEric Biggers 	struct crypto_skcipher *generic_tfm = NULL;
3091d435e10eSEric Biggers 	struct skcipher_request *generic_req = NULL;
3092d435e10eSEric Biggers 	unsigned int i;
3093d435e10eSEric Biggers 	struct cipher_testvec vec = { 0 };
3094d435e10eSEric Biggers 	char vec_name[64];
30956b5ca646SArnd Bergmann 	struct testvec_config *cfg;
3096d435e10eSEric Biggers 	char cfgname[TESTVEC_CONFIG_NAMELEN];
3097d435e10eSEric Biggers 	int err;
3098d435e10eSEric Biggers 
3099d435e10eSEric Biggers 	if (noextratests)
3100d435e10eSEric Biggers 		return 0;
3101d435e10eSEric Biggers 
3102d435e10eSEric Biggers 	/* Keywrap isn't supported here yet as it handles its IV differently. */
3103d435e10eSEric Biggers 	if (strncmp(algname, "kw(", 3) == 0)
3104d435e10eSEric Biggers 		return 0;
3105d435e10eSEric Biggers 
3106f900fde2SEric Biggers 	init_rnd_state(&rng);
3107f900fde2SEric Biggers 
3108d435e10eSEric Biggers 	if (!generic_driver) { /* Use default naming convention? */
3109d435e10eSEric Biggers 		err = build_generic_driver_name(algname, _generic_driver);
3110d435e10eSEric Biggers 		if (err)
3111d435e10eSEric Biggers 			return err;
3112d435e10eSEric Biggers 		generic_driver = _generic_driver;
3113d435e10eSEric Biggers 	}
3114d435e10eSEric Biggers 
3115d435e10eSEric Biggers 	if (strcmp(generic_driver, driver) == 0) /* Already the generic impl? */
3116d435e10eSEric Biggers 		return 0;
3117d435e10eSEric Biggers 
3118d435e10eSEric Biggers 	generic_tfm = crypto_alloc_skcipher(generic_driver, 0, 0);
3119d435e10eSEric Biggers 	if (IS_ERR(generic_tfm)) {
3120d435e10eSEric Biggers 		err = PTR_ERR(generic_tfm);
3121d435e10eSEric Biggers 		if (err == -ENOENT) {
3122d435e10eSEric Biggers 			pr_warn("alg: skcipher: skipping comparison tests for %s because %s is unavailable\n",
3123d435e10eSEric Biggers 				driver, generic_driver);
3124d435e10eSEric Biggers 			return 0;
3125d435e10eSEric Biggers 		}
3126d435e10eSEric Biggers 		pr_err("alg: skcipher: error allocating %s (generic impl of %s): %d\n",
3127d435e10eSEric Biggers 		       generic_driver, algname, err);
3128d435e10eSEric Biggers 		return err;
3129d435e10eSEric Biggers 	}
3130d435e10eSEric Biggers 
31316b5ca646SArnd Bergmann 	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
31326b5ca646SArnd Bergmann 	if (!cfg) {
31336b5ca646SArnd Bergmann 		err = -ENOMEM;
31346b5ca646SArnd Bergmann 		goto out;
31356b5ca646SArnd Bergmann 	}
31366b5ca646SArnd Bergmann 
3137d435e10eSEric Biggers 	generic_req = skcipher_request_alloc(generic_tfm, GFP_KERNEL);
3138d435e10eSEric Biggers 	if (!generic_req) {
3139d435e10eSEric Biggers 		err = -ENOMEM;
3140d435e10eSEric Biggers 		goto out;
3141d435e10eSEric Biggers 	}
3142d435e10eSEric Biggers 
3143d435e10eSEric Biggers 	/* Check the algorithm properties for consistency. */
3144d435e10eSEric Biggers 
3145fd60f727SEric Biggers 	if (crypto_skcipher_min_keysize(tfm) !=
3146fd60f727SEric Biggers 	    crypto_skcipher_min_keysize(generic_tfm)) {
3147fd60f727SEric Biggers 		pr_err("alg: skcipher: min keysize for %s (%u) doesn't match generic impl (%u)\n",
3148fd60f727SEric Biggers 		       driver, crypto_skcipher_min_keysize(tfm),
3149fd60f727SEric Biggers 		       crypto_skcipher_min_keysize(generic_tfm));
3150fd60f727SEric Biggers 		err = -EINVAL;
3151fd60f727SEric Biggers 		goto out;
3152fd60f727SEric Biggers 	}
3153fd60f727SEric Biggers 
31549ac0d136SEric Biggers 	if (maxkeysize != crypto_skcipher_max_keysize(generic_tfm)) {
3155d435e10eSEric Biggers 		pr_err("alg: skcipher: max keysize for %s (%u) doesn't match generic impl (%u)\n",
31569ac0d136SEric Biggers 		       driver, maxkeysize,
31579ac0d136SEric Biggers 		       crypto_skcipher_max_keysize(generic_tfm));
3158d435e10eSEric Biggers 		err = -EINVAL;
3159d435e10eSEric Biggers 		goto out;
3160d435e10eSEric Biggers 	}
3161d435e10eSEric Biggers 
3162d435e10eSEric Biggers 	if (ivsize != crypto_skcipher_ivsize(generic_tfm)) {
3163d435e10eSEric Biggers 		pr_err("alg: skcipher: ivsize for %s (%u) doesn't match generic impl (%u)\n",
3164d435e10eSEric Biggers 		       driver, ivsize, crypto_skcipher_ivsize(generic_tfm));
3165d435e10eSEric Biggers 		err = -EINVAL;
3166d435e10eSEric Biggers 		goto out;
3167d435e10eSEric Biggers 	}
3168d435e10eSEric Biggers 
3169d435e10eSEric Biggers 	if (blocksize != crypto_skcipher_blocksize(generic_tfm)) {
3170d435e10eSEric Biggers 		pr_err("alg: skcipher: blocksize for %s (%u) doesn't match generic impl (%u)\n",
3171d435e10eSEric Biggers 		       driver, blocksize,
3172d435e10eSEric Biggers 		       crypto_skcipher_blocksize(generic_tfm));
3173d435e10eSEric Biggers 		err = -EINVAL;
3174d435e10eSEric Biggers 		goto out;
3175d435e10eSEric Biggers 	}
3176d435e10eSEric Biggers 
3177d435e10eSEric Biggers 	/*
3178d435e10eSEric Biggers 	 * Now generate test vectors using the generic implementation, and test
3179d435e10eSEric Biggers 	 * the other implementation against them.
3180d435e10eSEric Biggers 	 */
3181d435e10eSEric Biggers 
31829ac0d136SEric Biggers 	vec.key = kmalloc(maxkeysize, GFP_KERNEL);
3183d435e10eSEric Biggers 	vec.iv = kmalloc(ivsize, GFP_KERNEL);
3184d435e10eSEric Biggers 	vec.ptext = kmalloc(maxdatasize, GFP_KERNEL);
3185d435e10eSEric Biggers 	vec.ctext = kmalloc(maxdatasize, GFP_KERNEL);
3186d435e10eSEric Biggers 	if (!vec.key || !vec.iv || !vec.ptext || !vec.ctext) {
3187d435e10eSEric Biggers 		err = -ENOMEM;
3188d435e10eSEric Biggers 		goto out;
3189d435e10eSEric Biggers 	}
3190d435e10eSEric Biggers 
3191d435e10eSEric Biggers 	for (i = 0; i < fuzz_iterations * 8; i++) {
3192f900fde2SEric Biggers 		generate_random_cipher_testvec(&rng, generic_req, &vec,
3193f900fde2SEric Biggers 					       maxdatasize,
3194d435e10eSEric Biggers 					       vec_name, sizeof(vec_name));
3195f900fde2SEric Biggers 		generate_random_testvec_config(&rng, cfg, cfgname,
3196f900fde2SEric Biggers 					       sizeof(cfgname));
3197d435e10eSEric Biggers 
31986e5972faSEric Biggers 		err = test_skcipher_vec_cfg(ENCRYPT, &vec, vec_name,
31996b5ca646SArnd Bergmann 					    cfg, req, tsgls);
3200d435e10eSEric Biggers 		if (err)
3201d435e10eSEric Biggers 			goto out;
32026e5972faSEric Biggers 		err = test_skcipher_vec_cfg(DECRYPT, &vec, vec_name,
32036b5ca646SArnd Bergmann 					    cfg, req, tsgls);
3204d435e10eSEric Biggers 		if (err)
3205d435e10eSEric Biggers 			goto out;
3206d435e10eSEric Biggers 		cond_resched();
3207d435e10eSEric Biggers 	}
3208d435e10eSEric Biggers 	err = 0;
3209d435e10eSEric Biggers out:
32106b5ca646SArnd Bergmann 	kfree(cfg);
3211d435e10eSEric Biggers 	kfree(vec.key);
3212d435e10eSEric Biggers 	kfree(vec.iv);
3213d435e10eSEric Biggers 	kfree(vec.ptext);
3214d435e10eSEric Biggers 	kfree(vec.ctext);
3215d435e10eSEric Biggers 	crypto_free_skcipher(generic_tfm);
3216d435e10eSEric Biggers 	skcipher_request_free(generic_req);
3217d435e10eSEric Biggers 	return err;
3218d435e10eSEric Biggers }
3219d435e10eSEric Biggers #else /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
test_skcipher_vs_generic_impl(const char * generic_driver,struct skcipher_request * req,struct cipher_test_sglists * tsgls)32206e5972faSEric Biggers static int test_skcipher_vs_generic_impl(const char *generic_driver,
3221d435e10eSEric Biggers 					 struct skcipher_request *req,
3222d435e10eSEric Biggers 					 struct cipher_test_sglists *tsgls)
3223d435e10eSEric Biggers {
3224d435e10eSEric Biggers 	return 0;
3225d435e10eSEric Biggers }
3226d435e10eSEric Biggers #endif /* !CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
3227d435e10eSEric Biggers 
test_skcipher(int enc,const struct cipher_test_suite * suite,struct skcipher_request * req,struct cipher_test_sglists * tsgls)32286e5972faSEric Biggers static int test_skcipher(int enc, const struct cipher_test_suite *suite,
32294e7babbaSEric Biggers 			 struct skcipher_request *req,
32304e7babbaSEric Biggers 			 struct cipher_test_sglists *tsgls)
32314e7babbaSEric Biggers {
32324e7babbaSEric Biggers 	unsigned int i;
32334e7babbaSEric Biggers 	int err;
32344e7babbaSEric Biggers 
32354e7babbaSEric Biggers 	for (i = 0; i < suite->count; i++) {
32366e5972faSEric Biggers 		err = test_skcipher_vec(enc, &suite->vecs[i], i, req, tsgls);
32374e7babbaSEric Biggers 		if (err)
32384e7babbaSEric Biggers 			return err;
3239e63e1b0dSEric Biggers 		cond_resched();
32404e7babbaSEric Biggers 	}
32414e7babbaSEric Biggers 	return 0;
32424e7babbaSEric Biggers }
32434e7babbaSEric Biggers 
alg_test_skcipher(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)32444e7babbaSEric Biggers static int alg_test_skcipher(const struct alg_test_desc *desc,
32454e7babbaSEric Biggers 			     const char *driver, u32 type, u32 mask)
32464e7babbaSEric Biggers {
32474e7babbaSEric Biggers 	const struct cipher_test_suite *suite = &desc->suite.cipher;
32484e7babbaSEric Biggers 	struct crypto_skcipher *tfm;
32494e7babbaSEric Biggers 	struct skcipher_request *req = NULL;
32504e7babbaSEric Biggers 	struct cipher_test_sglists *tsgls = NULL;
32514e7babbaSEric Biggers 	int err;
32524e7babbaSEric Biggers 
32534e7babbaSEric Biggers 	if (suite->count <= 0) {
32544e7babbaSEric Biggers 		pr_err("alg: skcipher: empty test suite for %s\n", driver);
32554e7babbaSEric Biggers 		return -EINVAL;
32564e7babbaSEric Biggers 	}
32574e7babbaSEric Biggers 
32584e7babbaSEric Biggers 	tfm = crypto_alloc_skcipher(driver, type, mask);
32594e7babbaSEric Biggers 	if (IS_ERR(tfm)) {
32604e7babbaSEric Biggers 		pr_err("alg: skcipher: failed to allocate transform for %s: %ld\n",
32614e7babbaSEric Biggers 		       driver, PTR_ERR(tfm));
32624e7babbaSEric Biggers 		return PTR_ERR(tfm);
32634e7babbaSEric Biggers 	}
32646e5972faSEric Biggers 	driver = crypto_skcipher_driver_name(tfm);
32654e7babbaSEric Biggers 
32664e7babbaSEric Biggers 	req = skcipher_request_alloc(tfm, GFP_KERNEL);
32674e7babbaSEric Biggers 	if (!req) {
32684e7babbaSEric Biggers 		pr_err("alg: skcipher: failed to allocate request for %s\n",
32694e7babbaSEric Biggers 		       driver);
32704e7babbaSEric Biggers 		err = -ENOMEM;
32714e7babbaSEric Biggers 		goto out;
32724e7babbaSEric Biggers 	}
32734e7babbaSEric Biggers 
32744e7babbaSEric Biggers 	tsgls = alloc_cipher_test_sglists();
32754e7babbaSEric Biggers 	if (!tsgls) {
32764e7babbaSEric Biggers 		pr_err("alg: skcipher: failed to allocate test buffers for %s\n",
32774e7babbaSEric Biggers 		       driver);
32784e7babbaSEric Biggers 		err = -ENOMEM;
32794e7babbaSEric Biggers 		goto out;
32804e7babbaSEric Biggers 	}
32814e7babbaSEric Biggers 
32826e5972faSEric Biggers 	err = test_skcipher(ENCRYPT, suite, req, tsgls);
32834e7babbaSEric Biggers 	if (err)
32844e7babbaSEric Biggers 		goto out;
32854e7babbaSEric Biggers 
32866e5972faSEric Biggers 	err = test_skcipher(DECRYPT, suite, req, tsgls);
3287d435e10eSEric Biggers 	if (err)
3288d435e10eSEric Biggers 		goto out;
3289d435e10eSEric Biggers 
32906e5972faSEric Biggers 	err = test_skcipher_vs_generic_impl(desc->generic_driver, req, tsgls);
32914e7babbaSEric Biggers out:
32924e7babbaSEric Biggers 	free_cipher_test_sglists(tsgls);
32934e7babbaSEric Biggers 	skcipher_request_free(req);
32944e7babbaSEric Biggers 	crypto_free_skcipher(tfm);
32954e7babbaSEric Biggers 	return err;
32964e7babbaSEric Biggers }
32974e7babbaSEric Biggers 
test_comp(struct crypto_comp * tfm,const struct comp_testvec * ctemplate,const struct comp_testvec * dtemplate,int ctcount,int dtcount)3298b13b1e0cSEric Biggers static int test_comp(struct crypto_comp *tfm,
3299b13b1e0cSEric Biggers 		     const struct comp_testvec *ctemplate,
3300b13b1e0cSEric Biggers 		     const struct comp_testvec *dtemplate,
3301b13b1e0cSEric Biggers 		     int ctcount, int dtcount)
3302da7f033dSHerbert Xu {
3303da7f033dSHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_comp_tfm(tfm));
330433607384SMahipal Challa 	char *output, *decomp_output;
3305da7f033dSHerbert Xu 	unsigned int i;
3306da7f033dSHerbert Xu 	int ret;
3307da7f033dSHerbert Xu 
330833607384SMahipal Challa 	output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
330933607384SMahipal Challa 	if (!output)
331033607384SMahipal Challa 		return -ENOMEM;
331133607384SMahipal Challa 
331233607384SMahipal Challa 	decomp_output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
331333607384SMahipal Challa 	if (!decomp_output) {
331433607384SMahipal Challa 		kfree(output);
331533607384SMahipal Challa 		return -ENOMEM;
331633607384SMahipal Challa 	}
331733607384SMahipal Challa 
3318da7f033dSHerbert Xu 	for (i = 0; i < ctcount; i++) {
3319c79cf910SGeert Uytterhoeven 		int ilen;
3320c79cf910SGeert Uytterhoeven 		unsigned int dlen = COMP_BUF_SIZE;
3321da7f033dSHerbert Xu 
332222a8118dSMichael Schupikov 		memset(output, 0, COMP_BUF_SIZE);
332322a8118dSMichael Schupikov 		memset(decomp_output, 0, COMP_BUF_SIZE);
3324da7f033dSHerbert Xu 
3325da7f033dSHerbert Xu 		ilen = ctemplate[i].inlen;
3326da7f033dSHerbert Xu 		ret = crypto_comp_compress(tfm, ctemplate[i].input,
332733607384SMahipal Challa 					   ilen, output, &dlen);
3328da7f033dSHerbert Xu 		if (ret) {
3329da7f033dSHerbert Xu 			printk(KERN_ERR "alg: comp: compression failed "
3330da7f033dSHerbert Xu 			       "on test %d for %s: ret=%d\n", i + 1, algo,
3331da7f033dSHerbert Xu 			       -ret);
3332da7f033dSHerbert Xu 			goto out;
3333da7f033dSHerbert Xu 		}
3334da7f033dSHerbert Xu 
333533607384SMahipal Challa 		ilen = dlen;
333633607384SMahipal Challa 		dlen = COMP_BUF_SIZE;
333733607384SMahipal Challa 		ret = crypto_comp_decompress(tfm, output,
333833607384SMahipal Challa 					     ilen, decomp_output, &dlen);
333933607384SMahipal Challa 		if (ret) {
334033607384SMahipal Challa 			pr_err("alg: comp: compression failed: decompress: on test %d for %s failed: ret=%d\n",
334133607384SMahipal Challa 			       i + 1, algo, -ret);
334233607384SMahipal Challa 			goto out;
334333607384SMahipal Challa 		}
334433607384SMahipal Challa 
334533607384SMahipal Challa 		if (dlen != ctemplate[i].inlen) {
3346b812eb00SGeert Uytterhoeven 			printk(KERN_ERR "alg: comp: Compression test %d "
3347b812eb00SGeert Uytterhoeven 			       "failed for %s: output len = %d\n", i + 1, algo,
3348b812eb00SGeert Uytterhoeven 			       dlen);
3349b812eb00SGeert Uytterhoeven 			ret = -EINVAL;
3350b812eb00SGeert Uytterhoeven 			goto out;
3351b812eb00SGeert Uytterhoeven 		}
3352b812eb00SGeert Uytterhoeven 
335333607384SMahipal Challa 		if (memcmp(decomp_output, ctemplate[i].input,
335433607384SMahipal Challa 			   ctemplate[i].inlen)) {
335533607384SMahipal Challa 			pr_err("alg: comp: compression failed: output differs: on test %d for %s\n",
335633607384SMahipal Challa 			       i + 1, algo);
335733607384SMahipal Challa 			hexdump(decomp_output, dlen);
3358da7f033dSHerbert Xu 			ret = -EINVAL;
3359da7f033dSHerbert Xu 			goto out;
3360da7f033dSHerbert Xu 		}
3361da7f033dSHerbert Xu 	}
3362da7f033dSHerbert Xu 
3363da7f033dSHerbert Xu 	for (i = 0; i < dtcount; i++) {
3364c79cf910SGeert Uytterhoeven 		int ilen;
3365c79cf910SGeert Uytterhoeven 		unsigned int dlen = COMP_BUF_SIZE;
3366da7f033dSHerbert Xu 
336722a8118dSMichael Schupikov 		memset(decomp_output, 0, COMP_BUF_SIZE);
3368da7f033dSHerbert Xu 
3369da7f033dSHerbert Xu 		ilen = dtemplate[i].inlen;
3370da7f033dSHerbert Xu 		ret = crypto_comp_decompress(tfm, dtemplate[i].input,
337133607384SMahipal Challa 					     ilen, decomp_output, &dlen);
3372da7f033dSHerbert Xu 		if (ret) {
3373da7f033dSHerbert Xu 			printk(KERN_ERR "alg: comp: decompression failed "
3374da7f033dSHerbert Xu 			       "on test %d for %s: ret=%d\n", i + 1, algo,
3375da7f033dSHerbert Xu 			       -ret);
3376da7f033dSHerbert Xu 			goto out;
3377da7f033dSHerbert Xu 		}
3378da7f033dSHerbert Xu 
3379b812eb00SGeert Uytterhoeven 		if (dlen != dtemplate[i].outlen) {
3380b812eb00SGeert Uytterhoeven 			printk(KERN_ERR "alg: comp: Decompression test %d "
3381b812eb00SGeert Uytterhoeven 			       "failed for %s: output len = %d\n", i + 1, algo,
3382b812eb00SGeert Uytterhoeven 			       dlen);
3383b812eb00SGeert Uytterhoeven 			ret = -EINVAL;
3384b812eb00SGeert Uytterhoeven 			goto out;
3385b812eb00SGeert Uytterhoeven 		}
3386b812eb00SGeert Uytterhoeven 
338733607384SMahipal Challa 		if (memcmp(decomp_output, dtemplate[i].output, dlen)) {
3388da7f033dSHerbert Xu 			printk(KERN_ERR "alg: comp: Decompression test %d "
3389da7f033dSHerbert Xu 			       "failed for %s\n", i + 1, algo);
339033607384SMahipal Challa 			hexdump(decomp_output, dlen);
3391da7f033dSHerbert Xu 			ret = -EINVAL;
3392da7f033dSHerbert Xu 			goto out;
3393da7f033dSHerbert Xu 		}
3394da7f033dSHerbert Xu 	}
3395da7f033dSHerbert Xu 
3396da7f033dSHerbert Xu 	ret = 0;
3397da7f033dSHerbert Xu 
3398da7f033dSHerbert Xu out:
339933607384SMahipal Challa 	kfree(decomp_output);
340033607384SMahipal Challa 	kfree(output);
3401da7f033dSHerbert Xu 	return ret;
3402da7f033dSHerbert Xu }
3403da7f033dSHerbert Xu 
test_acomp(struct crypto_acomp * tfm,const struct comp_testvec * ctemplate,const struct comp_testvec * dtemplate,int ctcount,int dtcount)3404b13b1e0cSEric Biggers static int test_acomp(struct crypto_acomp *tfm,
3405b13b1e0cSEric Biggers 		      const struct comp_testvec *ctemplate,
3406b13b1e0cSEric Biggers 		      const struct comp_testvec *dtemplate,
3407b13b1e0cSEric Biggers 		      int ctcount, int dtcount)
3408d7db7a88SGiovanni Cabiddu {
3409d7db7a88SGiovanni Cabiddu 	const char *algo = crypto_tfm_alg_driver_name(crypto_acomp_tfm(tfm));
3410d7db7a88SGiovanni Cabiddu 	unsigned int i;
3411a9943a0aSGiovanni Cabiddu 	char *output, *decomp_out;
3412d7db7a88SGiovanni Cabiddu 	int ret;
3413d7db7a88SGiovanni Cabiddu 	struct scatterlist src, dst;
3414d7db7a88SGiovanni Cabiddu 	struct acomp_req *req;
34157f397136SGilad Ben-Yossef 	struct crypto_wait wait;
3416d7db7a88SGiovanni Cabiddu 
3417eb095593SEric Biggers 	output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
3418eb095593SEric Biggers 	if (!output)
3419eb095593SEric Biggers 		return -ENOMEM;
3420eb095593SEric Biggers 
3421a9943a0aSGiovanni Cabiddu 	decomp_out = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
3422a9943a0aSGiovanni Cabiddu 	if (!decomp_out) {
3423a9943a0aSGiovanni Cabiddu 		kfree(output);
3424a9943a0aSGiovanni Cabiddu 		return -ENOMEM;
3425a9943a0aSGiovanni Cabiddu 	}
3426a9943a0aSGiovanni Cabiddu 
3427d7db7a88SGiovanni Cabiddu 	for (i = 0; i < ctcount; i++) {
3428d7db7a88SGiovanni Cabiddu 		unsigned int dlen = COMP_BUF_SIZE;
3429d7db7a88SGiovanni Cabiddu 		int ilen = ctemplate[i].inlen;
343002608e02SLaura Abbott 		void *input_vec;
3431d7db7a88SGiovanni Cabiddu 
3432d2110224SEric Biggers 		input_vec = kmemdup(ctemplate[i].input, ilen, GFP_KERNEL);
343302608e02SLaura Abbott 		if (!input_vec) {
343402608e02SLaura Abbott 			ret = -ENOMEM;
343502608e02SLaura Abbott 			goto out;
343602608e02SLaura Abbott 		}
343702608e02SLaura Abbott 
3438eb095593SEric Biggers 		memset(output, 0, dlen);
34397f397136SGilad Ben-Yossef 		crypto_init_wait(&wait);
344002608e02SLaura Abbott 		sg_init_one(&src, input_vec, ilen);
3441d7db7a88SGiovanni Cabiddu 		sg_init_one(&dst, output, dlen);
3442d7db7a88SGiovanni Cabiddu 
3443d7db7a88SGiovanni Cabiddu 		req = acomp_request_alloc(tfm);
3444d7db7a88SGiovanni Cabiddu 		if (!req) {
3445d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: request alloc failed for %s\n",
3446d7db7a88SGiovanni Cabiddu 			       algo);
344702608e02SLaura Abbott 			kfree(input_vec);
3448d7db7a88SGiovanni Cabiddu 			ret = -ENOMEM;
3449d7db7a88SGiovanni Cabiddu 			goto out;
3450d7db7a88SGiovanni Cabiddu 		}
3451d7db7a88SGiovanni Cabiddu 
3452d7db7a88SGiovanni Cabiddu 		acomp_request_set_params(req, &src, &dst, ilen, dlen);
3453d7db7a88SGiovanni Cabiddu 		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
34547f397136SGilad Ben-Yossef 					   crypto_req_done, &wait);
3455d7db7a88SGiovanni Cabiddu 
34567f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_acomp_compress(req), &wait);
3457d7db7a88SGiovanni Cabiddu 		if (ret) {
3458d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
3459d7db7a88SGiovanni Cabiddu 			       i + 1, algo, -ret);
346002608e02SLaura Abbott 			kfree(input_vec);
3461d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
3462d7db7a88SGiovanni Cabiddu 			goto out;
3463d7db7a88SGiovanni Cabiddu 		}
3464d7db7a88SGiovanni Cabiddu 
3465a9943a0aSGiovanni Cabiddu 		ilen = req->dlen;
3466a9943a0aSGiovanni Cabiddu 		dlen = COMP_BUF_SIZE;
3467a9943a0aSGiovanni Cabiddu 		sg_init_one(&src, output, ilen);
3468a9943a0aSGiovanni Cabiddu 		sg_init_one(&dst, decomp_out, dlen);
34697f397136SGilad Ben-Yossef 		crypto_init_wait(&wait);
3470a9943a0aSGiovanni Cabiddu 		acomp_request_set_params(req, &src, &dst, ilen, dlen);
3471a9943a0aSGiovanni Cabiddu 
34727f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
3473a9943a0aSGiovanni Cabiddu 		if (ret) {
3474a9943a0aSGiovanni Cabiddu 			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
3475a9943a0aSGiovanni Cabiddu 			       i + 1, algo, -ret);
3476a9943a0aSGiovanni Cabiddu 			kfree(input_vec);
3477a9943a0aSGiovanni Cabiddu 			acomp_request_free(req);
3478a9943a0aSGiovanni Cabiddu 			goto out;
3479a9943a0aSGiovanni Cabiddu 		}
3480a9943a0aSGiovanni Cabiddu 
3481a9943a0aSGiovanni Cabiddu 		if (req->dlen != ctemplate[i].inlen) {
3482d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Compression test %d failed for %s: output len = %d\n",
3483d7db7a88SGiovanni Cabiddu 			       i + 1, algo, req->dlen);
3484d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
348502608e02SLaura Abbott 			kfree(input_vec);
3486d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
3487d7db7a88SGiovanni Cabiddu 			goto out;
3488d7db7a88SGiovanni Cabiddu 		}
3489d7db7a88SGiovanni Cabiddu 
3490a9943a0aSGiovanni Cabiddu 		if (memcmp(input_vec, decomp_out, req->dlen)) {
3491d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Compression test %d failed for %s\n",
3492d7db7a88SGiovanni Cabiddu 			       i + 1, algo);
3493d7db7a88SGiovanni Cabiddu 			hexdump(output, req->dlen);
3494d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
349502608e02SLaura Abbott 			kfree(input_vec);
3496d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
3497d7db7a88SGiovanni Cabiddu 			goto out;
3498d7db7a88SGiovanni Cabiddu 		}
3499d7db7a88SGiovanni Cabiddu 
35005a4c2936SLucas Segarra Fernandez #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
35015a4c2936SLucas Segarra Fernandez 		crypto_init_wait(&wait);
35025a4c2936SLucas Segarra Fernandez 		sg_init_one(&src, input_vec, ilen);
35035a4c2936SLucas Segarra Fernandez 		acomp_request_set_params(req, &src, NULL, ilen, 0);
35045a4c2936SLucas Segarra Fernandez 
35055a4c2936SLucas Segarra Fernandez 		ret = crypto_wait_req(crypto_acomp_compress(req), &wait);
35065a4c2936SLucas Segarra Fernandez 		if (ret) {
35075a4c2936SLucas Segarra Fernandez 			pr_err("alg: acomp: compression failed on NULL dst buffer test %d for %s: ret=%d\n",
35085a4c2936SLucas Segarra Fernandez 			       i + 1, algo, -ret);
35095a4c2936SLucas Segarra Fernandez 			kfree(input_vec);
35105a4c2936SLucas Segarra Fernandez 			acomp_request_free(req);
35115a4c2936SLucas Segarra Fernandez 			goto out;
35125a4c2936SLucas Segarra Fernandez 		}
35135a4c2936SLucas Segarra Fernandez #endif
35145a4c2936SLucas Segarra Fernandez 
351502608e02SLaura Abbott 		kfree(input_vec);
3516d7db7a88SGiovanni Cabiddu 		acomp_request_free(req);
3517d7db7a88SGiovanni Cabiddu 	}
3518d7db7a88SGiovanni Cabiddu 
3519d7db7a88SGiovanni Cabiddu 	for (i = 0; i < dtcount; i++) {
3520d7db7a88SGiovanni Cabiddu 		unsigned int dlen = COMP_BUF_SIZE;
3521d7db7a88SGiovanni Cabiddu 		int ilen = dtemplate[i].inlen;
352202608e02SLaura Abbott 		void *input_vec;
3523d7db7a88SGiovanni Cabiddu 
3524d2110224SEric Biggers 		input_vec = kmemdup(dtemplate[i].input, ilen, GFP_KERNEL);
352502608e02SLaura Abbott 		if (!input_vec) {
352602608e02SLaura Abbott 			ret = -ENOMEM;
352702608e02SLaura Abbott 			goto out;
352802608e02SLaura Abbott 		}
352902608e02SLaura Abbott 
3530eb095593SEric Biggers 		memset(output, 0, dlen);
35317f397136SGilad Ben-Yossef 		crypto_init_wait(&wait);
353202608e02SLaura Abbott 		sg_init_one(&src, input_vec, ilen);
3533d7db7a88SGiovanni Cabiddu 		sg_init_one(&dst, output, dlen);
3534d7db7a88SGiovanni Cabiddu 
3535d7db7a88SGiovanni Cabiddu 		req = acomp_request_alloc(tfm);
3536d7db7a88SGiovanni Cabiddu 		if (!req) {
3537d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: request alloc failed for %s\n",
3538d7db7a88SGiovanni Cabiddu 			       algo);
353902608e02SLaura Abbott 			kfree(input_vec);
3540d7db7a88SGiovanni Cabiddu 			ret = -ENOMEM;
3541d7db7a88SGiovanni Cabiddu 			goto out;
3542d7db7a88SGiovanni Cabiddu 		}
3543d7db7a88SGiovanni Cabiddu 
3544d7db7a88SGiovanni Cabiddu 		acomp_request_set_params(req, &src, &dst, ilen, dlen);
3545d7db7a88SGiovanni Cabiddu 		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
35467f397136SGilad Ben-Yossef 					   crypto_req_done, &wait);
3547d7db7a88SGiovanni Cabiddu 
35487f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
3549d7db7a88SGiovanni Cabiddu 		if (ret) {
3550d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: decompression failed on test %d for %s: ret=%d\n",
3551d7db7a88SGiovanni Cabiddu 			       i + 1, algo, -ret);
355202608e02SLaura Abbott 			kfree(input_vec);
3553d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
3554d7db7a88SGiovanni Cabiddu 			goto out;
3555d7db7a88SGiovanni Cabiddu 		}
3556d7db7a88SGiovanni Cabiddu 
3557d7db7a88SGiovanni Cabiddu 		if (req->dlen != dtemplate[i].outlen) {
3558d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Decompression test %d failed for %s: output len = %d\n",
3559d7db7a88SGiovanni Cabiddu 			       i + 1, algo, req->dlen);
3560d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
356102608e02SLaura Abbott 			kfree(input_vec);
3562d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
3563d7db7a88SGiovanni Cabiddu 			goto out;
3564d7db7a88SGiovanni Cabiddu 		}
3565d7db7a88SGiovanni Cabiddu 
3566d7db7a88SGiovanni Cabiddu 		if (memcmp(output, dtemplate[i].output, req->dlen)) {
3567d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Decompression test %d failed for %s\n",
3568d7db7a88SGiovanni Cabiddu 			       i + 1, algo);
3569d7db7a88SGiovanni Cabiddu 			hexdump(output, req->dlen);
3570d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
357102608e02SLaura Abbott 			kfree(input_vec);
3572d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
3573d7db7a88SGiovanni Cabiddu 			goto out;
3574d7db7a88SGiovanni Cabiddu 		}
3575d7db7a88SGiovanni Cabiddu 
35765a4c2936SLucas Segarra Fernandez #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
35775a4c2936SLucas Segarra Fernandez 		crypto_init_wait(&wait);
35785a4c2936SLucas Segarra Fernandez 		acomp_request_set_params(req, &src, NULL, ilen, 0);
35795a4c2936SLucas Segarra Fernandez 
35805a4c2936SLucas Segarra Fernandez 		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
35815a4c2936SLucas Segarra Fernandez 		if (ret) {
35825a4c2936SLucas Segarra Fernandez 			pr_err("alg: acomp: decompression failed on NULL dst buffer test %d for %s: ret=%d\n",
35835a4c2936SLucas Segarra Fernandez 			       i + 1, algo, -ret);
35845a4c2936SLucas Segarra Fernandez 			kfree(input_vec);
35855a4c2936SLucas Segarra Fernandez 			acomp_request_free(req);
35865a4c2936SLucas Segarra Fernandez 			goto out;
35875a4c2936SLucas Segarra Fernandez 		}
35885a4c2936SLucas Segarra Fernandez #endif
35895a4c2936SLucas Segarra Fernandez 
359002608e02SLaura Abbott 		kfree(input_vec);
3591d7db7a88SGiovanni Cabiddu 		acomp_request_free(req);
3592d7db7a88SGiovanni Cabiddu 	}
3593d7db7a88SGiovanni Cabiddu 
3594d7db7a88SGiovanni Cabiddu 	ret = 0;
3595d7db7a88SGiovanni Cabiddu 
3596d7db7a88SGiovanni Cabiddu out:
3597a9943a0aSGiovanni Cabiddu 	kfree(decomp_out);
3598eb095593SEric Biggers 	kfree(output);
3599d7db7a88SGiovanni Cabiddu 	return ret;
3600d7db7a88SGiovanni Cabiddu }
3601d7db7a88SGiovanni Cabiddu 
test_cprng(struct crypto_rng * tfm,const struct cprng_testvec * template,unsigned int tcount)3602b13b1e0cSEric Biggers static int test_cprng(struct crypto_rng *tfm,
3603b13b1e0cSEric Biggers 		      const struct cprng_testvec *template,
36047647d6ceSJarod Wilson 		      unsigned int tcount)
36057647d6ceSJarod Wilson {
36067647d6ceSJarod Wilson 	const char *algo = crypto_tfm_alg_driver_name(crypto_rng_tfm(tfm));
3607fa4ef8a6SFelipe Contreras 	int err = 0, i, j, seedsize;
36087647d6ceSJarod Wilson 	u8 *seed;
36097647d6ceSJarod Wilson 	char result[32];
36107647d6ceSJarod Wilson 
36117647d6ceSJarod Wilson 	seedsize = crypto_rng_seedsize(tfm);
36127647d6ceSJarod Wilson 
36137647d6ceSJarod Wilson 	seed = kmalloc(seedsize, GFP_KERNEL);
36147647d6ceSJarod Wilson 	if (!seed) {
36157647d6ceSJarod Wilson 		printk(KERN_ERR "alg: cprng: Failed to allocate seed space "
36167647d6ceSJarod Wilson 		       "for %s\n", algo);
36177647d6ceSJarod Wilson 		return -ENOMEM;
36187647d6ceSJarod Wilson 	}
36197647d6ceSJarod Wilson 
36207647d6ceSJarod Wilson 	for (i = 0; i < tcount; i++) {
36217647d6ceSJarod Wilson 		memset(result, 0, 32);
36227647d6ceSJarod Wilson 
36237647d6ceSJarod Wilson 		memcpy(seed, template[i].v, template[i].vlen);
36247647d6ceSJarod Wilson 		memcpy(seed + template[i].vlen, template[i].key,
36257647d6ceSJarod Wilson 		       template[i].klen);
36267647d6ceSJarod Wilson 		memcpy(seed + template[i].vlen + template[i].klen,
36277647d6ceSJarod Wilson 		       template[i].dt, template[i].dtlen);
36287647d6ceSJarod Wilson 
36297647d6ceSJarod Wilson 		err = crypto_rng_reset(tfm, seed, seedsize);
36307647d6ceSJarod Wilson 		if (err) {
36317647d6ceSJarod Wilson 			printk(KERN_ERR "alg: cprng: Failed to reset rng "
36327647d6ceSJarod Wilson 			       "for %s\n", algo);
36337647d6ceSJarod Wilson 			goto out;
36347647d6ceSJarod Wilson 		}
36357647d6ceSJarod Wilson 
36367647d6ceSJarod Wilson 		for (j = 0; j < template[i].loops; j++) {
36377647d6ceSJarod Wilson 			err = crypto_rng_get_bytes(tfm, result,
36387647d6ceSJarod Wilson 						   template[i].rlen);
363919e60e13SStephan Mueller 			if (err < 0) {
36407647d6ceSJarod Wilson 				printk(KERN_ERR "alg: cprng: Failed to obtain "
36417647d6ceSJarod Wilson 				       "the correct amount of random data for "
364219e60e13SStephan Mueller 				       "%s (requested %d)\n", algo,
364319e60e13SStephan Mueller 				       template[i].rlen);
36447647d6ceSJarod Wilson 				goto out;
36457647d6ceSJarod Wilson 			}
36467647d6ceSJarod Wilson 		}
36477647d6ceSJarod Wilson 
36487647d6ceSJarod Wilson 		err = memcmp(result, template[i].result,
36497647d6ceSJarod Wilson 			     template[i].rlen);
36507647d6ceSJarod Wilson 		if (err) {
36517647d6ceSJarod Wilson 			printk(KERN_ERR "alg: cprng: Test %d failed for %s\n",
36527647d6ceSJarod Wilson 			       i, algo);
36537647d6ceSJarod Wilson 			hexdump(result, template[i].rlen);
36547647d6ceSJarod Wilson 			err = -EINVAL;
36557647d6ceSJarod Wilson 			goto out;
36567647d6ceSJarod Wilson 		}
36577647d6ceSJarod Wilson 	}
36587647d6ceSJarod Wilson 
36597647d6ceSJarod Wilson out:
36607647d6ceSJarod Wilson 	kfree(seed);
36617647d6ceSJarod Wilson 	return err;
36627647d6ceSJarod Wilson }
36637647d6ceSJarod Wilson 
alg_test_cipher(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)3664da7f033dSHerbert Xu static int alg_test_cipher(const struct alg_test_desc *desc,
3665da7f033dSHerbert Xu 			   const char *driver, u32 type, u32 mask)
3666da7f033dSHerbert Xu {
366792a4c9feSEric Biggers 	const struct cipher_test_suite *suite = &desc->suite.cipher;
36681aa4ecd9SHerbert Xu 	struct crypto_cipher *tfm;
366992a4c9feSEric Biggers 	int err;
3670da7f033dSHerbert Xu 
3671eed93e0cSHerbert Xu 	tfm = crypto_alloc_cipher(driver, type, mask);
3672da7f033dSHerbert Xu 	if (IS_ERR(tfm)) {
3673da7f033dSHerbert Xu 		printk(KERN_ERR "alg: cipher: Failed to load transform for "
3674da7f033dSHerbert Xu 		       "%s: %ld\n", driver, PTR_ERR(tfm));
3675da7f033dSHerbert Xu 		return PTR_ERR(tfm);
3676da7f033dSHerbert Xu 	}
3677da7f033dSHerbert Xu 
367892a4c9feSEric Biggers 	err = test_cipher(tfm, ENCRYPT, suite->vecs, suite->count);
367992a4c9feSEric Biggers 	if (!err)
368092a4c9feSEric Biggers 		err = test_cipher(tfm, DECRYPT, suite->vecs, suite->count);
3681da7f033dSHerbert Xu 
36821aa4ecd9SHerbert Xu 	crypto_free_cipher(tfm);
36831aa4ecd9SHerbert Xu 	return err;
36841aa4ecd9SHerbert Xu }
36851aa4ecd9SHerbert Xu 
alg_test_comp(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)3686da7f033dSHerbert Xu static int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
3687da7f033dSHerbert Xu 			 u32 type, u32 mask)
3688da7f033dSHerbert Xu {
3689d7db7a88SGiovanni Cabiddu 	struct crypto_comp *comp;
3690d7db7a88SGiovanni Cabiddu 	struct crypto_acomp *acomp;
3691da7f033dSHerbert Xu 	int err;
3692d7db7a88SGiovanni Cabiddu 	u32 algo_type = type & CRYPTO_ALG_TYPE_ACOMPRESS_MASK;
3693da7f033dSHerbert Xu 
3694d7db7a88SGiovanni Cabiddu 	if (algo_type == CRYPTO_ALG_TYPE_ACOMPRESS) {
3695d7db7a88SGiovanni Cabiddu 		acomp = crypto_alloc_acomp(driver, type, mask);
3696d7db7a88SGiovanni Cabiddu 		if (IS_ERR(acomp)) {
3697d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Failed to load transform for %s: %ld\n",
3698d7db7a88SGiovanni Cabiddu 			       driver, PTR_ERR(acomp));
3699d7db7a88SGiovanni Cabiddu 			return PTR_ERR(acomp);
3700d7db7a88SGiovanni Cabiddu 		}
3701d7db7a88SGiovanni Cabiddu 		err = test_acomp(acomp, desc->suite.comp.comp.vecs,
3702d7db7a88SGiovanni Cabiddu 				 desc->suite.comp.decomp.vecs,
3703d7db7a88SGiovanni Cabiddu 				 desc->suite.comp.comp.count,
3704d7db7a88SGiovanni Cabiddu 				 desc->suite.comp.decomp.count);
3705d7db7a88SGiovanni Cabiddu 		crypto_free_acomp(acomp);
3706d7db7a88SGiovanni Cabiddu 	} else {
3707d7db7a88SGiovanni Cabiddu 		comp = crypto_alloc_comp(driver, type, mask);
3708d7db7a88SGiovanni Cabiddu 		if (IS_ERR(comp)) {
3709d7db7a88SGiovanni Cabiddu 			pr_err("alg: comp: Failed to load transform for %s: %ld\n",
3710d7db7a88SGiovanni Cabiddu 			       driver, PTR_ERR(comp));
3711d7db7a88SGiovanni Cabiddu 			return PTR_ERR(comp);
3712da7f033dSHerbert Xu 		}
3713da7f033dSHerbert Xu 
3714d7db7a88SGiovanni Cabiddu 		err = test_comp(comp, desc->suite.comp.comp.vecs,
3715da7f033dSHerbert Xu 				desc->suite.comp.decomp.vecs,
3716da7f033dSHerbert Xu 				desc->suite.comp.comp.count,
3717da7f033dSHerbert Xu 				desc->suite.comp.decomp.count);
3718da7f033dSHerbert Xu 
3719d7db7a88SGiovanni Cabiddu 		crypto_free_comp(comp);
3720d7db7a88SGiovanni Cabiddu 	}
3721da7f033dSHerbert Xu 	return err;
3722da7f033dSHerbert Xu }
3723da7f033dSHerbert Xu 
alg_test_crc32c(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)37248e3ee85eSHerbert Xu static int alg_test_crc32c(const struct alg_test_desc *desc,
37258e3ee85eSHerbert Xu 			   const char *driver, u32 type, u32 mask)
37268e3ee85eSHerbert Xu {
37278e3ee85eSHerbert Xu 	struct crypto_shash *tfm;
3728cb9dde88SEric Biggers 	__le32 val;
37298e3ee85eSHerbert Xu 	int err;
37308e3ee85eSHerbert Xu 
37318e3ee85eSHerbert Xu 	err = alg_test_hash(desc, driver, type, mask);
37328e3ee85eSHerbert Xu 	if (err)
3733eb5e6730SEric Biggers 		return err;
37348e3ee85eSHerbert Xu 
3735eed93e0cSHerbert Xu 	tfm = crypto_alloc_shash(driver, type, mask);
37368e3ee85eSHerbert Xu 	if (IS_ERR(tfm)) {
3737eb5e6730SEric Biggers 		if (PTR_ERR(tfm) == -ENOENT) {
3738eb5e6730SEric Biggers 			/*
3739eb5e6730SEric Biggers 			 * This crc32c implementation is only available through
3740eb5e6730SEric Biggers 			 * ahash API, not the shash API, so the remaining part
3741eb5e6730SEric Biggers 			 * of the test is not applicable to it.
3742eb5e6730SEric Biggers 			 */
3743eb5e6730SEric Biggers 			return 0;
3744eb5e6730SEric Biggers 		}
37458e3ee85eSHerbert Xu 		printk(KERN_ERR "alg: crc32c: Failed to load transform for %s: "
37468e3ee85eSHerbert Xu 		       "%ld\n", driver, PTR_ERR(tfm));
3747eb5e6730SEric Biggers 		return PTR_ERR(tfm);
37488e3ee85eSHerbert Xu 	}
374979cafe9aSEric Biggers 	driver = crypto_shash_driver_name(tfm);
37508e3ee85eSHerbert Xu 
37518e3ee85eSHerbert Xu 	do {
37524c5c3024SJan-Simon Möller 		SHASH_DESC_ON_STACK(shash, tfm);
37534c5c3024SJan-Simon Möller 		u32 *ctx = (u32 *)shash_desc_ctx(shash);
37548e3ee85eSHerbert Xu 
37554c5c3024SJan-Simon Möller 		shash->tfm = tfm;
37568e3ee85eSHerbert Xu 
3757cb9dde88SEric Biggers 		*ctx = 420553207;
37584c5c3024SJan-Simon Möller 		err = crypto_shash_final(shash, (u8 *)&val);
37598e3ee85eSHerbert Xu 		if (err) {
37608e3ee85eSHerbert Xu 			printk(KERN_ERR "alg: crc32c: Operation failed for "
37618e3ee85eSHerbert Xu 			       "%s: %d\n", driver, err);
37628e3ee85eSHerbert Xu 			break;
37638e3ee85eSHerbert Xu 		}
37648e3ee85eSHerbert Xu 
3765cb9dde88SEric Biggers 		if (val != cpu_to_le32(~420553207)) {
3766cb9dde88SEric Biggers 			pr_err("alg: crc32c: Test failed for %s: %u\n",
3767cb9dde88SEric Biggers 			       driver, le32_to_cpu(val));
37688e3ee85eSHerbert Xu 			err = -EINVAL;
37698e3ee85eSHerbert Xu 		}
37708e3ee85eSHerbert Xu 	} while (0);
37718e3ee85eSHerbert Xu 
37728e3ee85eSHerbert Xu 	crypto_free_shash(tfm);
37738e3ee85eSHerbert Xu 
37748e3ee85eSHerbert Xu 	return err;
37758e3ee85eSHerbert Xu }
37768e3ee85eSHerbert Xu 
alg_test_cprng(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)37777647d6ceSJarod Wilson static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
37787647d6ceSJarod Wilson 			  u32 type, u32 mask)
37797647d6ceSJarod Wilson {
37807647d6ceSJarod Wilson 	struct crypto_rng *rng;
37817647d6ceSJarod Wilson 	int err;
37827647d6ceSJarod Wilson 
3783eed93e0cSHerbert Xu 	rng = crypto_alloc_rng(driver, type, mask);
37847647d6ceSJarod Wilson 	if (IS_ERR(rng)) {
37857647d6ceSJarod Wilson 		printk(KERN_ERR "alg: cprng: Failed to load transform for %s: "
37867647d6ceSJarod Wilson 		       "%ld\n", driver, PTR_ERR(rng));
37877647d6ceSJarod Wilson 		return PTR_ERR(rng);
37887647d6ceSJarod Wilson 	}
37897647d6ceSJarod Wilson 
37907647d6ceSJarod Wilson 	err = test_cprng(rng, desc->suite.cprng.vecs, desc->suite.cprng.count);
37917647d6ceSJarod Wilson 
37927647d6ceSJarod Wilson 	crypto_free_rng(rng);
37937647d6ceSJarod Wilson 
37947647d6ceSJarod Wilson 	return err;
37957647d6ceSJarod Wilson }
37967647d6ceSJarod Wilson 
379764d1cdfbSStephan Mueller 
drbg_cavs_test(const struct drbg_testvec * test,int pr,const char * driver,u32 type,u32 mask)3798b13b1e0cSEric Biggers static int drbg_cavs_test(const struct drbg_testvec *test, int pr,
379964d1cdfbSStephan Mueller 			  const char *driver, u32 type, u32 mask)
380064d1cdfbSStephan Mueller {
380164d1cdfbSStephan Mueller 	int ret = -EAGAIN;
380264d1cdfbSStephan Mueller 	struct crypto_rng *drng;
380364d1cdfbSStephan Mueller 	struct drbg_test_data test_data;
380464d1cdfbSStephan Mueller 	struct drbg_string addtl, pers, testentropy;
380564d1cdfbSStephan Mueller 	unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
380664d1cdfbSStephan Mueller 
380764d1cdfbSStephan Mueller 	if (!buf)
380864d1cdfbSStephan Mueller 		return -ENOMEM;
380964d1cdfbSStephan Mueller 
3810eed93e0cSHerbert Xu 	drng = crypto_alloc_rng(driver, type, mask);
381164d1cdfbSStephan Mueller 	if (IS_ERR(drng)) {
381264d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for "
381364d1cdfbSStephan Mueller 		       "%s\n", driver);
3814453431a5SWaiman Long 		kfree_sensitive(buf);
381564d1cdfbSStephan Mueller 		return -ENOMEM;
381664d1cdfbSStephan Mueller 	}
381764d1cdfbSStephan Mueller 
381864d1cdfbSStephan Mueller 	test_data.testentropy = &testentropy;
381964d1cdfbSStephan Mueller 	drbg_string_fill(&testentropy, test->entropy, test->entropylen);
382064d1cdfbSStephan Mueller 	drbg_string_fill(&pers, test->pers, test->perslen);
382164d1cdfbSStephan Mueller 	ret = crypto_drbg_reset_test(drng, &pers, &test_data);
382264d1cdfbSStephan Mueller 	if (ret) {
382364d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
382464d1cdfbSStephan Mueller 		goto outbuf;
382564d1cdfbSStephan Mueller 	}
382664d1cdfbSStephan Mueller 
382764d1cdfbSStephan Mueller 	drbg_string_fill(&addtl, test->addtla, test->addtllen);
382864d1cdfbSStephan Mueller 	if (pr) {
382964d1cdfbSStephan Mueller 		drbg_string_fill(&testentropy, test->entpra, test->entprlen);
383064d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl_test(drng,
383164d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl,	&test_data);
383264d1cdfbSStephan Mueller 	} else {
383364d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl(drng,
383464d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl);
383564d1cdfbSStephan Mueller 	}
383619e60e13SStephan Mueller 	if (ret < 0) {
383764d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: could not obtain random data for "
383864d1cdfbSStephan Mueller 		       "driver %s\n", driver);
383964d1cdfbSStephan Mueller 		goto outbuf;
384064d1cdfbSStephan Mueller 	}
384164d1cdfbSStephan Mueller 
384264d1cdfbSStephan Mueller 	drbg_string_fill(&addtl, test->addtlb, test->addtllen);
384364d1cdfbSStephan Mueller 	if (pr) {
384464d1cdfbSStephan Mueller 		drbg_string_fill(&testentropy, test->entprb, test->entprlen);
384564d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl_test(drng,
384664d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl, &test_data);
384764d1cdfbSStephan Mueller 	} else {
384864d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl(drng,
384964d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl);
385064d1cdfbSStephan Mueller 	}
385119e60e13SStephan Mueller 	if (ret < 0) {
385264d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: could not obtain random data for "
385364d1cdfbSStephan Mueller 		       "driver %s\n", driver);
385464d1cdfbSStephan Mueller 		goto outbuf;
385564d1cdfbSStephan Mueller 	}
385664d1cdfbSStephan Mueller 
385764d1cdfbSStephan Mueller 	ret = memcmp(test->expected, buf, test->expectedlen);
385864d1cdfbSStephan Mueller 
385964d1cdfbSStephan Mueller outbuf:
386064d1cdfbSStephan Mueller 	crypto_free_rng(drng);
3861453431a5SWaiman Long 	kfree_sensitive(buf);
386264d1cdfbSStephan Mueller 	return ret;
386364d1cdfbSStephan Mueller }
386464d1cdfbSStephan Mueller 
386564d1cdfbSStephan Mueller 
alg_test_drbg(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)386664d1cdfbSStephan Mueller static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
386764d1cdfbSStephan Mueller 			 u32 type, u32 mask)
386864d1cdfbSStephan Mueller {
386964d1cdfbSStephan Mueller 	int err = 0;
387064d1cdfbSStephan Mueller 	int pr = 0;
387164d1cdfbSStephan Mueller 	int i = 0;
3872b13b1e0cSEric Biggers 	const struct drbg_testvec *template = desc->suite.drbg.vecs;
387364d1cdfbSStephan Mueller 	unsigned int tcount = desc->suite.drbg.count;
387464d1cdfbSStephan Mueller 
387564d1cdfbSStephan Mueller 	if (0 == memcmp(driver, "drbg_pr_", 8))
387664d1cdfbSStephan Mueller 		pr = 1;
387764d1cdfbSStephan Mueller 
387864d1cdfbSStephan Mueller 	for (i = 0; i < tcount; i++) {
387964d1cdfbSStephan Mueller 		err = drbg_cavs_test(&template[i], pr, driver, type, mask);
388064d1cdfbSStephan Mueller 		if (err) {
388164d1cdfbSStephan Mueller 			printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
388264d1cdfbSStephan Mueller 			       i, driver);
388364d1cdfbSStephan Mueller 			err = -EINVAL;
388464d1cdfbSStephan Mueller 			break;
388564d1cdfbSStephan Mueller 		}
388664d1cdfbSStephan Mueller 	}
388764d1cdfbSStephan Mueller 	return err;
388864d1cdfbSStephan Mueller 
388964d1cdfbSStephan Mueller }
389064d1cdfbSStephan Mueller 
do_test_kpp(struct crypto_kpp * tfm,const struct kpp_testvec * vec,const char * alg)3891b13b1e0cSEric Biggers static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
3892802c7f1cSSalvatore Benedetto 		       const char *alg)
3893802c7f1cSSalvatore Benedetto {
3894802c7f1cSSalvatore Benedetto 	struct kpp_request *req;
3895802c7f1cSSalvatore Benedetto 	void *input_buf = NULL;
3896802c7f1cSSalvatore Benedetto 	void *output_buf = NULL;
389747d3fd39STudor-Dan Ambarus 	void *a_public = NULL;
389847d3fd39STudor-Dan Ambarus 	void *a_ss = NULL;
389947d3fd39STudor-Dan Ambarus 	void *shared_secret = NULL;
39007f397136SGilad Ben-Yossef 	struct crypto_wait wait;
3901802c7f1cSSalvatore Benedetto 	unsigned int out_len_max;
3902802c7f1cSSalvatore Benedetto 	int err = -ENOMEM;
3903802c7f1cSSalvatore Benedetto 	struct scatterlist src, dst;
3904802c7f1cSSalvatore Benedetto 
3905802c7f1cSSalvatore Benedetto 	req = kpp_request_alloc(tfm, GFP_KERNEL);
3906802c7f1cSSalvatore Benedetto 	if (!req)
3907802c7f1cSSalvatore Benedetto 		return err;
3908802c7f1cSSalvatore Benedetto 
39097f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
3910802c7f1cSSalvatore Benedetto 
3911802c7f1cSSalvatore Benedetto 	err = crypto_kpp_set_secret(tfm, vec->secret, vec->secret_size);
3912802c7f1cSSalvatore Benedetto 	if (err < 0)
3913802c7f1cSSalvatore Benedetto 		goto free_req;
3914802c7f1cSSalvatore Benedetto 
3915802c7f1cSSalvatore Benedetto 	out_len_max = crypto_kpp_maxsize(tfm);
3916802c7f1cSSalvatore Benedetto 	output_buf = kzalloc(out_len_max, GFP_KERNEL);
3917802c7f1cSSalvatore Benedetto 	if (!output_buf) {
3918802c7f1cSSalvatore Benedetto 		err = -ENOMEM;
3919802c7f1cSSalvatore Benedetto 		goto free_req;
3920802c7f1cSSalvatore Benedetto 	}
3921802c7f1cSSalvatore Benedetto 
3922802c7f1cSSalvatore Benedetto 	/* Use appropriate parameter as base */
3923802c7f1cSSalvatore Benedetto 	kpp_request_set_input(req, NULL, 0);
3924802c7f1cSSalvatore Benedetto 	sg_init_one(&dst, output_buf, out_len_max);
3925802c7f1cSSalvatore Benedetto 	kpp_request_set_output(req, &dst, out_len_max);
3926802c7f1cSSalvatore Benedetto 	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
39277f397136SGilad Ben-Yossef 				 crypto_req_done, &wait);
3928802c7f1cSSalvatore Benedetto 
392947d3fd39STudor-Dan Ambarus 	/* Compute party A's public key */
39307f397136SGilad Ben-Yossef 	err = crypto_wait_req(crypto_kpp_generate_public_key(req), &wait);
3931802c7f1cSSalvatore Benedetto 	if (err) {
393247d3fd39STudor-Dan Ambarus 		pr_err("alg: %s: Party A: generate public key test failed. err %d\n",
3933802c7f1cSSalvatore Benedetto 		       alg, err);
3934802c7f1cSSalvatore Benedetto 		goto free_output;
3935802c7f1cSSalvatore Benedetto 	}
393647d3fd39STudor-Dan Ambarus 
393747d3fd39STudor-Dan Ambarus 	if (vec->genkey) {
393847d3fd39STudor-Dan Ambarus 		/* Save party A's public key */
3939e3d90e52SChristopher Diaz Riveros 		a_public = kmemdup(sg_virt(req->dst), out_len_max, GFP_KERNEL);
394047d3fd39STudor-Dan Ambarus 		if (!a_public) {
394147d3fd39STudor-Dan Ambarus 			err = -ENOMEM;
394247d3fd39STudor-Dan Ambarus 			goto free_output;
394347d3fd39STudor-Dan Ambarus 		}
394447d3fd39STudor-Dan Ambarus 	} else {
3945802c7f1cSSalvatore Benedetto 		/* Verify calculated public key */
3946802c7f1cSSalvatore Benedetto 		if (memcmp(vec->expected_a_public, sg_virt(req->dst),
3947802c7f1cSSalvatore Benedetto 			   vec->expected_a_public_size)) {
394847d3fd39STudor-Dan Ambarus 			pr_err("alg: %s: Party A: generate public key test failed. Invalid output\n",
3949802c7f1cSSalvatore Benedetto 			       alg);
3950802c7f1cSSalvatore Benedetto 			err = -EINVAL;
3951802c7f1cSSalvatore Benedetto 			goto free_output;
3952802c7f1cSSalvatore Benedetto 		}
395347d3fd39STudor-Dan Ambarus 	}
3954802c7f1cSSalvatore Benedetto 
3955802c7f1cSSalvatore Benedetto 	/* Calculate shared secret key by using counter part (b) public key. */
3956e3d90e52SChristopher Diaz Riveros 	input_buf = kmemdup(vec->b_public, vec->b_public_size, GFP_KERNEL);
3957802c7f1cSSalvatore Benedetto 	if (!input_buf) {
3958802c7f1cSSalvatore Benedetto 		err = -ENOMEM;
3959802c7f1cSSalvatore Benedetto 		goto free_output;
3960802c7f1cSSalvatore Benedetto 	}
3961802c7f1cSSalvatore Benedetto 
3962802c7f1cSSalvatore Benedetto 	sg_init_one(&src, input_buf, vec->b_public_size);
3963802c7f1cSSalvatore Benedetto 	sg_init_one(&dst, output_buf, out_len_max);
3964802c7f1cSSalvatore Benedetto 	kpp_request_set_input(req, &src, vec->b_public_size);
3965802c7f1cSSalvatore Benedetto 	kpp_request_set_output(req, &dst, out_len_max);
3966802c7f1cSSalvatore Benedetto 	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
39677f397136SGilad Ben-Yossef 				 crypto_req_done, &wait);
39687f397136SGilad Ben-Yossef 	err = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait);
3969802c7f1cSSalvatore Benedetto 	if (err) {
397047d3fd39STudor-Dan Ambarus 		pr_err("alg: %s: Party A: compute shared secret test failed. err %d\n",
3971802c7f1cSSalvatore Benedetto 		       alg, err);
3972802c7f1cSSalvatore Benedetto 		goto free_all;
3973802c7f1cSSalvatore Benedetto 	}
397447d3fd39STudor-Dan Ambarus 
397547d3fd39STudor-Dan Ambarus 	if (vec->genkey) {
397647d3fd39STudor-Dan Ambarus 		/* Save the shared secret obtained by party A */
3977e3d90e52SChristopher Diaz Riveros 		a_ss = kmemdup(sg_virt(req->dst), vec->expected_ss_size, GFP_KERNEL);
397847d3fd39STudor-Dan Ambarus 		if (!a_ss) {
397947d3fd39STudor-Dan Ambarus 			err = -ENOMEM;
398047d3fd39STudor-Dan Ambarus 			goto free_all;
398147d3fd39STudor-Dan Ambarus 		}
398247d3fd39STudor-Dan Ambarus 
398347d3fd39STudor-Dan Ambarus 		/*
398447d3fd39STudor-Dan Ambarus 		 * Calculate party B's shared secret by using party A's
398547d3fd39STudor-Dan Ambarus 		 * public key.
398647d3fd39STudor-Dan Ambarus 		 */
398747d3fd39STudor-Dan Ambarus 		err = crypto_kpp_set_secret(tfm, vec->b_secret,
398847d3fd39STudor-Dan Ambarus 					    vec->b_secret_size);
398947d3fd39STudor-Dan Ambarus 		if (err < 0)
399047d3fd39STudor-Dan Ambarus 			goto free_all;
399147d3fd39STudor-Dan Ambarus 
399247d3fd39STudor-Dan Ambarus 		sg_init_one(&src, a_public, vec->expected_a_public_size);
399347d3fd39STudor-Dan Ambarus 		sg_init_one(&dst, output_buf, out_len_max);
399447d3fd39STudor-Dan Ambarus 		kpp_request_set_input(req, &src, vec->expected_a_public_size);
399547d3fd39STudor-Dan Ambarus 		kpp_request_set_output(req, &dst, out_len_max);
399647d3fd39STudor-Dan Ambarus 		kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
39977f397136SGilad Ben-Yossef 					 crypto_req_done, &wait);
39987f397136SGilad Ben-Yossef 		err = crypto_wait_req(crypto_kpp_compute_shared_secret(req),
39997f397136SGilad Ben-Yossef 				      &wait);
400047d3fd39STudor-Dan Ambarus 		if (err) {
400147d3fd39STudor-Dan Ambarus 			pr_err("alg: %s: Party B: compute shared secret failed. err %d\n",
400247d3fd39STudor-Dan Ambarus 			       alg, err);
400347d3fd39STudor-Dan Ambarus 			goto free_all;
400447d3fd39STudor-Dan Ambarus 		}
400547d3fd39STudor-Dan Ambarus 
400647d3fd39STudor-Dan Ambarus 		shared_secret = a_ss;
400747d3fd39STudor-Dan Ambarus 	} else {
400847d3fd39STudor-Dan Ambarus 		shared_secret = (void *)vec->expected_ss;
400947d3fd39STudor-Dan Ambarus 	}
401047d3fd39STudor-Dan Ambarus 
4011802c7f1cSSalvatore Benedetto 	/*
4012802c7f1cSSalvatore Benedetto 	 * verify shared secret from which the user will derive
4013802c7f1cSSalvatore Benedetto 	 * secret key by executing whatever hash it has chosen
4014802c7f1cSSalvatore Benedetto 	 */
401547d3fd39STudor-Dan Ambarus 	if (memcmp(shared_secret, sg_virt(req->dst),
4016802c7f1cSSalvatore Benedetto 		   vec->expected_ss_size)) {
4017802c7f1cSSalvatore Benedetto 		pr_err("alg: %s: compute shared secret test failed. Invalid output\n",
4018802c7f1cSSalvatore Benedetto 		       alg);
4019802c7f1cSSalvatore Benedetto 		err = -EINVAL;
4020802c7f1cSSalvatore Benedetto 	}
4021802c7f1cSSalvatore Benedetto 
4022802c7f1cSSalvatore Benedetto free_all:
402347d3fd39STudor-Dan Ambarus 	kfree(a_ss);
4024802c7f1cSSalvatore Benedetto 	kfree(input_buf);
4025802c7f1cSSalvatore Benedetto free_output:
402647d3fd39STudor-Dan Ambarus 	kfree(a_public);
4027802c7f1cSSalvatore Benedetto 	kfree(output_buf);
4028802c7f1cSSalvatore Benedetto free_req:
4029802c7f1cSSalvatore Benedetto 	kpp_request_free(req);
4030802c7f1cSSalvatore Benedetto 	return err;
4031802c7f1cSSalvatore Benedetto }
4032802c7f1cSSalvatore Benedetto 
test_kpp(struct crypto_kpp * tfm,const char * alg,const struct kpp_testvec * vecs,unsigned int tcount)4033802c7f1cSSalvatore Benedetto static int test_kpp(struct crypto_kpp *tfm, const char *alg,
4034b13b1e0cSEric Biggers 		    const struct kpp_testvec *vecs, unsigned int tcount)
4035802c7f1cSSalvatore Benedetto {
4036802c7f1cSSalvatore Benedetto 	int ret, i;
4037802c7f1cSSalvatore Benedetto 
4038802c7f1cSSalvatore Benedetto 	for (i = 0; i < tcount; i++) {
4039802c7f1cSSalvatore Benedetto 		ret = do_test_kpp(tfm, vecs++, alg);
4040802c7f1cSSalvatore Benedetto 		if (ret) {
4041802c7f1cSSalvatore Benedetto 			pr_err("alg: %s: test failed on vector %d, err=%d\n",
4042802c7f1cSSalvatore Benedetto 			       alg, i + 1, ret);
4043802c7f1cSSalvatore Benedetto 			return ret;
4044802c7f1cSSalvatore Benedetto 		}
4045802c7f1cSSalvatore Benedetto 	}
4046802c7f1cSSalvatore Benedetto 	return 0;
4047802c7f1cSSalvatore Benedetto }
4048802c7f1cSSalvatore Benedetto 
alg_test_kpp(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)4049802c7f1cSSalvatore Benedetto static int alg_test_kpp(const struct alg_test_desc *desc, const char *driver,
4050802c7f1cSSalvatore Benedetto 			u32 type, u32 mask)
4051802c7f1cSSalvatore Benedetto {
4052802c7f1cSSalvatore Benedetto 	struct crypto_kpp *tfm;
4053802c7f1cSSalvatore Benedetto 	int err = 0;
4054802c7f1cSSalvatore Benedetto 
4055eed93e0cSHerbert Xu 	tfm = crypto_alloc_kpp(driver, type, mask);
4056802c7f1cSSalvatore Benedetto 	if (IS_ERR(tfm)) {
4057802c7f1cSSalvatore Benedetto 		pr_err("alg: kpp: Failed to load tfm for %s: %ld\n",
4058802c7f1cSSalvatore Benedetto 		       driver, PTR_ERR(tfm));
4059802c7f1cSSalvatore Benedetto 		return PTR_ERR(tfm);
4060802c7f1cSSalvatore Benedetto 	}
4061802c7f1cSSalvatore Benedetto 	if (desc->suite.kpp.vecs)
4062802c7f1cSSalvatore Benedetto 		err = test_kpp(tfm, desc->alg, desc->suite.kpp.vecs,
4063802c7f1cSSalvatore Benedetto 			       desc->suite.kpp.count);
4064802c7f1cSSalvatore Benedetto 
4065802c7f1cSSalvatore Benedetto 	crypto_free_kpp(tfm);
4066802c7f1cSSalvatore Benedetto 	return err;
4067802c7f1cSSalvatore Benedetto }
4068802c7f1cSSalvatore Benedetto 
test_pack_u32(u8 * dst,u32 val)4069f1774cb8SVitaly Chikunov static u8 *test_pack_u32(u8 *dst, u32 val)
4070f1774cb8SVitaly Chikunov {
4071f1774cb8SVitaly Chikunov 	memcpy(dst, &val, sizeof(val));
4072f1774cb8SVitaly Chikunov 	return dst + sizeof(val);
4073f1774cb8SVitaly Chikunov }
4074f1774cb8SVitaly Chikunov 
test_akcipher_one(struct crypto_akcipher * tfm,const struct akcipher_testvec * vecs)407550d2b643SHerbert Xu static int test_akcipher_one(struct crypto_akcipher *tfm,
4076b13b1e0cSEric Biggers 			     const struct akcipher_testvec *vecs)
4077946cc463STadeusz Struk {
4078df27b26fSHerbert Xu 	char *xbuf[XBUFSIZE];
4079946cc463STadeusz Struk 	struct akcipher_request *req;
4080946cc463STadeusz Struk 	void *outbuf_enc = NULL;
4081946cc463STadeusz Struk 	void *outbuf_dec = NULL;
40827f397136SGilad Ben-Yossef 	struct crypto_wait wait;
4083946cc463STadeusz Struk 	unsigned int out_len_max, out_len = 0;
4084946cc463STadeusz Struk 	int err = -ENOMEM;
4085c7381b01SVitaly Chikunov 	struct scatterlist src, dst, src_tab[3];
40860507de94SVitaly Chikunov 	const char *m, *c;
40870507de94SVitaly Chikunov 	unsigned int m_size, c_size;
40880507de94SVitaly Chikunov 	const char *op;
4089f1774cb8SVitaly Chikunov 	u8 *key, *ptr;
4090946cc463STadeusz Struk 
4091df27b26fSHerbert Xu 	if (testmgr_alloc_buf(xbuf))
4092df27b26fSHerbert Xu 		return err;
4093df27b26fSHerbert Xu 
4094946cc463STadeusz Struk 	req = akcipher_request_alloc(tfm, GFP_KERNEL);
4095946cc463STadeusz Struk 	if (!req)
4096df27b26fSHerbert Xu 		goto free_xbuf;
4097946cc463STadeusz Struk 
40987f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
409922287b0bSTadeusz Struk 
4100f1774cb8SVitaly Chikunov 	key = kmalloc(vecs->key_len + sizeof(u32) * 2 + vecs->param_len,
4101f1774cb8SVitaly Chikunov 		      GFP_KERNEL);
4102f1774cb8SVitaly Chikunov 	if (!key)
41032b403867STianjia Zhang 		goto free_req;
4104f1774cb8SVitaly Chikunov 	memcpy(key, vecs->key, vecs->key_len);
4105f1774cb8SVitaly Chikunov 	ptr = key + vecs->key_len;
4106f1774cb8SVitaly Chikunov 	ptr = test_pack_u32(ptr, vecs->algo);
4107f1774cb8SVitaly Chikunov 	ptr = test_pack_u32(ptr, vecs->param_len);
4108f1774cb8SVitaly Chikunov 	memcpy(ptr, vecs->params, vecs->param_len);
4109f1774cb8SVitaly Chikunov 
411022287b0bSTadeusz Struk 	if (vecs->public_key_vec)
4111f1774cb8SVitaly Chikunov 		err = crypto_akcipher_set_pub_key(tfm, key, vecs->key_len);
411222287b0bSTadeusz Struk 	else
4113f1774cb8SVitaly Chikunov 		err = crypto_akcipher_set_priv_key(tfm, key, vecs->key_len);
4114946cc463STadeusz Struk 	if (err)
41152b403867STianjia Zhang 		goto free_key;
4116946cc463STadeusz Struk 
41170507de94SVitaly Chikunov 	/*
41180507de94SVitaly Chikunov 	 * First run test which do not require a private key, such as
41190507de94SVitaly Chikunov 	 * encrypt or verify.
41200507de94SVitaly Chikunov 	 */
4121c7381b01SVitaly Chikunov 	err = -ENOMEM;
4122c7381b01SVitaly Chikunov 	out_len_max = crypto_akcipher_maxsize(tfm);
4123946cc463STadeusz Struk 	outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
4124946cc463STadeusz Struk 	if (!outbuf_enc)
41252b403867STianjia Zhang 		goto free_key;
4126946cc463STadeusz Struk 
41270507de94SVitaly Chikunov 	if (!vecs->siggen_sigver_test) {
41280507de94SVitaly Chikunov 		m = vecs->m;
41290507de94SVitaly Chikunov 		m_size = vecs->m_size;
41300507de94SVitaly Chikunov 		c = vecs->c;
41310507de94SVitaly Chikunov 		c_size = vecs->c_size;
41320507de94SVitaly Chikunov 		op = "encrypt";
41330507de94SVitaly Chikunov 	} else {
41340507de94SVitaly Chikunov 		/* Swap args so we could keep plaintext (digest)
41350507de94SVitaly Chikunov 		 * in vecs->m, and cooked signature in vecs->c.
41360507de94SVitaly Chikunov 		 */
41370507de94SVitaly Chikunov 		m = vecs->c; /* signature */
41380507de94SVitaly Chikunov 		m_size = vecs->c_size;
41390507de94SVitaly Chikunov 		c = vecs->m; /* digest */
41400507de94SVitaly Chikunov 		c_size = vecs->m_size;
41410507de94SVitaly Chikunov 		op = "verify";
41420507de94SVitaly Chikunov 	}
4143df27b26fSHerbert Xu 
41442b403867STianjia Zhang 	err = -E2BIG;
41450507de94SVitaly Chikunov 	if (WARN_ON(m_size > PAGE_SIZE))
41460507de94SVitaly Chikunov 		goto free_all;
41470507de94SVitaly Chikunov 	memcpy(xbuf[0], m, m_size);
4148df27b26fSHerbert Xu 
4149c7381b01SVitaly Chikunov 	sg_init_table(src_tab, 3);
4150df27b26fSHerbert Xu 	sg_set_buf(&src_tab[0], xbuf[0], 8);
41510507de94SVitaly Chikunov 	sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8);
4152c7381b01SVitaly Chikunov 	if (vecs->siggen_sigver_test) {
4153c7381b01SVitaly Chikunov 		if (WARN_ON(c_size > PAGE_SIZE))
4154c7381b01SVitaly Chikunov 			goto free_all;
4155c7381b01SVitaly Chikunov 		memcpy(xbuf[1], c, c_size);
4156c7381b01SVitaly Chikunov 		sg_set_buf(&src_tab[2], xbuf[1], c_size);
4157c7381b01SVitaly Chikunov 		akcipher_request_set_crypt(req, src_tab, NULL, m_size, c_size);
4158c7381b01SVitaly Chikunov 	} else {
415922287b0bSTadeusz Struk 		sg_init_one(&dst, outbuf_enc, out_len_max);
41600507de94SVitaly Chikunov 		akcipher_request_set_crypt(req, src_tab, &dst, m_size,
416122287b0bSTadeusz Struk 					   out_len_max);
4162c7381b01SVitaly Chikunov 	}
4163946cc463STadeusz Struk 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
41647f397136SGilad Ben-Yossef 				      crypto_req_done, &wait);
4165946cc463STadeusz Struk 
41667f397136SGilad Ben-Yossef 	err = crypto_wait_req(vecs->siggen_sigver_test ?
41670507de94SVitaly Chikunov 			      /* Run asymmetric signature verification */
41680507de94SVitaly Chikunov 			      crypto_akcipher_verify(req) :
41691207107cSStephan Mueller 			      /* Run asymmetric encrypt */
41707f397136SGilad Ben-Yossef 			      crypto_akcipher_encrypt(req), &wait);
4171946cc463STadeusz Struk 	if (err) {
41720507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
4173946cc463STadeusz Struk 		goto free_all;
4174946cc463STadeusz Struk 	}
4175a1f62c21STianjia Zhang 	if (!vecs->siggen_sigver_test && c) {
41760507de94SVitaly Chikunov 		if (req->dst_len != c_size) {
41770507de94SVitaly Chikunov 			pr_err("alg: akcipher: %s test failed. Invalid output len\n",
41780507de94SVitaly Chikunov 			       op);
4179946cc463STadeusz Struk 			err = -EINVAL;
4180946cc463STadeusz Struk 			goto free_all;
4181946cc463STadeusz Struk 		}
4182946cc463STadeusz Struk 		/* verify that encrypted message is equal to expected */
4183c7381b01SVitaly Chikunov 		if (memcmp(c, outbuf_enc, c_size) != 0) {
4184c7381b01SVitaly Chikunov 			pr_err("alg: akcipher: %s test failed. Invalid output\n",
4185c7381b01SVitaly Chikunov 			       op);
41860507de94SVitaly Chikunov 			hexdump(outbuf_enc, c_size);
4187946cc463STadeusz Struk 			err = -EINVAL;
4188946cc463STadeusz Struk 			goto free_all;
4189946cc463STadeusz Struk 		}
4190c7381b01SVitaly Chikunov 	}
41910507de94SVitaly Chikunov 
41920507de94SVitaly Chikunov 	/*
41930507de94SVitaly Chikunov 	 * Don't invoke (decrypt or sign) test which require a private key
41940507de94SVitaly Chikunov 	 * for vectors with only a public key.
41950507de94SVitaly Chikunov 	 */
4196946cc463STadeusz Struk 	if (vecs->public_key_vec) {
4197946cc463STadeusz Struk 		err = 0;
4198946cc463STadeusz Struk 		goto free_all;
4199946cc463STadeusz Struk 	}
4200946cc463STadeusz Struk 	outbuf_dec = kzalloc(out_len_max, GFP_KERNEL);
4201946cc463STadeusz Struk 	if (!outbuf_dec) {
4202946cc463STadeusz Struk 		err = -ENOMEM;
4203946cc463STadeusz Struk 		goto free_all;
4204946cc463STadeusz Struk 	}
4205df27b26fSHerbert Xu 
4206a1f62c21STianjia Zhang 	if (!vecs->siggen_sigver_test && !c) {
4207a1f62c21STianjia Zhang 		c = outbuf_enc;
4208a1f62c21STianjia Zhang 		c_size = req->dst_len;
4209a1f62c21STianjia Zhang 	}
4210a1f62c21STianjia Zhang 
42112b403867STianjia Zhang 	err = -E2BIG;
42120507de94SVitaly Chikunov 	op = vecs->siggen_sigver_test ? "sign" : "decrypt";
42130507de94SVitaly Chikunov 	if (WARN_ON(c_size > PAGE_SIZE))
4214df27b26fSHerbert Xu 		goto free_all;
42150507de94SVitaly Chikunov 	memcpy(xbuf[0], c, c_size);
4216df27b26fSHerbert Xu 
42170507de94SVitaly Chikunov 	sg_init_one(&src, xbuf[0], c_size);
421822287b0bSTadeusz Struk 	sg_init_one(&dst, outbuf_dec, out_len_max);
42197f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
42200507de94SVitaly Chikunov 	akcipher_request_set_crypt(req, &src, &dst, c_size, out_len_max);
4221946cc463STadeusz Struk 
42227f397136SGilad Ben-Yossef 	err = crypto_wait_req(vecs->siggen_sigver_test ?
42230507de94SVitaly Chikunov 			      /* Run asymmetric signature generation */
42240507de94SVitaly Chikunov 			      crypto_akcipher_sign(req) :
42251207107cSStephan Mueller 			      /* Run asymmetric decrypt */
42267f397136SGilad Ben-Yossef 			      crypto_akcipher_decrypt(req), &wait);
4227946cc463STadeusz Struk 	if (err) {
42280507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
4229946cc463STadeusz Struk 		goto free_all;
4230946cc463STadeusz Struk 	}
4231946cc463STadeusz Struk 	out_len = req->dst_len;
42320507de94SVitaly Chikunov 	if (out_len < m_size) {
42330507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output len %u\n",
42340507de94SVitaly Chikunov 		       op, out_len);
4235946cc463STadeusz Struk 		err = -EINVAL;
4236946cc463STadeusz Struk 		goto free_all;
4237946cc463STadeusz Struk 	}
4238946cc463STadeusz Struk 	/* verify that decrypted message is equal to the original msg */
42390507de94SVitaly Chikunov 	if (memchr_inv(outbuf_dec, 0, out_len - m_size) ||
42400507de94SVitaly Chikunov 	    memcmp(m, outbuf_dec + out_len - m_size, m_size)) {
42410507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output\n", op);
424250d2b643SHerbert Xu 		hexdump(outbuf_dec, out_len);
4243946cc463STadeusz Struk 		err = -EINVAL;
4244946cc463STadeusz Struk 	}
4245946cc463STadeusz Struk free_all:
4246946cc463STadeusz Struk 	kfree(outbuf_dec);
4247946cc463STadeusz Struk 	kfree(outbuf_enc);
42482b403867STianjia Zhang free_key:
42492b403867STianjia Zhang 	kfree(key);
4250946cc463STadeusz Struk free_req:
4251946cc463STadeusz Struk 	akcipher_request_free(req);
4252df27b26fSHerbert Xu free_xbuf:
4253df27b26fSHerbert Xu 	testmgr_free_buf(xbuf);
4254946cc463STadeusz Struk 	return err;
4255946cc463STadeusz Struk }
4256946cc463STadeusz Struk 
test_akcipher(struct crypto_akcipher * tfm,const char * alg,const struct akcipher_testvec * vecs,unsigned int tcount)425750d2b643SHerbert Xu static int test_akcipher(struct crypto_akcipher *tfm, const char *alg,
4258b13b1e0cSEric Biggers 			 const struct akcipher_testvec *vecs,
4259b13b1e0cSEric Biggers 			 unsigned int tcount)
4260946cc463STadeusz Struk {
426115226e48SHerbert Xu 	const char *algo =
426215226e48SHerbert Xu 		crypto_tfm_alg_driver_name(crypto_akcipher_tfm(tfm));
4263946cc463STadeusz Struk 	int ret, i;
4264946cc463STadeusz Struk 
4265946cc463STadeusz Struk 	for (i = 0; i < tcount; i++) {
426650d2b643SHerbert Xu 		ret = test_akcipher_one(tfm, vecs++);
426750d2b643SHerbert Xu 		if (!ret)
426850d2b643SHerbert Xu 			continue;
426950d2b643SHerbert Xu 
427015226e48SHerbert Xu 		pr_err("alg: akcipher: test %d failed for %s, err=%d\n",
427115226e48SHerbert Xu 		       i + 1, algo, ret);
4272946cc463STadeusz Struk 		return ret;
4273946cc463STadeusz Struk 	}
4274946cc463STadeusz Struk 	return 0;
4275946cc463STadeusz Struk }
4276946cc463STadeusz Struk 
alg_test_akcipher(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)4277946cc463STadeusz Struk static int alg_test_akcipher(const struct alg_test_desc *desc,
4278946cc463STadeusz Struk 			     const char *driver, u32 type, u32 mask)
4279946cc463STadeusz Struk {
4280946cc463STadeusz Struk 	struct crypto_akcipher *tfm;
4281946cc463STadeusz Struk 	int err = 0;
4282946cc463STadeusz Struk 
4283eed93e0cSHerbert Xu 	tfm = crypto_alloc_akcipher(driver, type, mask);
4284946cc463STadeusz Struk 	if (IS_ERR(tfm)) {
4285946cc463STadeusz Struk 		pr_err("alg: akcipher: Failed to load tfm for %s: %ld\n",
4286946cc463STadeusz Struk 		       driver, PTR_ERR(tfm));
4287946cc463STadeusz Struk 		return PTR_ERR(tfm);
4288946cc463STadeusz Struk 	}
4289946cc463STadeusz Struk 	if (desc->suite.akcipher.vecs)
4290946cc463STadeusz Struk 		err = test_akcipher(tfm, desc->alg, desc->suite.akcipher.vecs,
4291946cc463STadeusz Struk 				    desc->suite.akcipher.count);
4292946cc463STadeusz Struk 
4293946cc463STadeusz Struk 	crypto_free_akcipher(tfm);
4294946cc463STadeusz Struk 	return err;
4295946cc463STadeusz Struk }
4296946cc463STadeusz Struk 
alg_test_null(const struct alg_test_desc * desc,const char * driver,u32 type,u32 mask)4297863b557aSYouquan, Song static int alg_test_null(const struct alg_test_desc *desc,
4298863b557aSYouquan, Song 			     const char *driver, u32 type, u32 mask)
4299863b557aSYouquan, Song {
4300863b557aSYouquan, Song 	return 0;
4301863b557aSYouquan, Song }
4302863b557aSYouquan, Song 
430349763fc6SEric Biggers #define ____VECS(tv)	.vecs = tv, .count = ARRAY_SIZE(tv)
430449763fc6SEric Biggers #define __VECS(tv)	{ ____VECS(tv) }
430521c8e720SArd Biesheuvel 
4306da7f033dSHerbert Xu /* Please keep this list sorted by algorithm name. */
4307da7f033dSHerbert Xu static const struct alg_test_desc alg_test_descs[] = {
4308da7f033dSHerbert Xu 	{
4309059c2a4dSEric Biggers 		.alg = "adiantum(xchacha12,aes)",
4310d435e10eSEric Biggers 		.generic_driver = "adiantum(xchacha12-generic,aes-generic,nhpoly1305-generic)",
4311059c2a4dSEric Biggers 		.test = alg_test_skcipher,
4312059c2a4dSEric Biggers 		.suite = {
4313059c2a4dSEric Biggers 			.cipher = __VECS(adiantum_xchacha12_aes_tv_template)
4314059c2a4dSEric Biggers 		},
4315059c2a4dSEric Biggers 	}, {
4316059c2a4dSEric Biggers 		.alg = "adiantum(xchacha20,aes)",
4317d435e10eSEric Biggers 		.generic_driver = "adiantum(xchacha20-generic,aes-generic,nhpoly1305-generic)",
4318059c2a4dSEric Biggers 		.test = alg_test_skcipher,
4319059c2a4dSEric Biggers 		.suite = {
4320059c2a4dSEric Biggers 			.cipher = __VECS(adiantum_xchacha20_aes_tv_template)
4321059c2a4dSEric Biggers 		},
4322059c2a4dSEric Biggers 	}, {
4323b87dc203SOndrej Mosnacek 		.alg = "aegis128",
4324b87dc203SOndrej Mosnacek 		.test = alg_test_aead,
4325b87dc203SOndrej Mosnacek 		.suite = {
4326a0d608eeSEric Biggers 			.aead = __VECS(aegis128_tv_template)
4327b87dc203SOndrej Mosnacek 		}
4328b87dc203SOndrej Mosnacek 	}, {
4329e08ca2daSJarod Wilson 		.alg = "ansi_cprng",
4330e08ca2daSJarod Wilson 		.test = alg_test_cprng,
4331e08ca2daSJarod Wilson 		.suite = {
433221c8e720SArd Biesheuvel 			.cprng = __VECS(ansi_cprng_aes_tv_template)
4333e08ca2daSJarod Wilson 		}
4334e08ca2daSJarod Wilson 	}, {
4335bca4feb0SHoria Geanta 		.alg = "authenc(hmac(md5),ecb(cipher_null))",
4336bca4feb0SHoria Geanta 		.test = alg_test_aead,
4337bca4feb0SHoria Geanta 		.suite = {
4338a0d608eeSEric Biggers 			.aead = __VECS(hmac_md5_ecb_cipher_null_tv_template)
4339bca4feb0SHoria Geanta 		}
4340bca4feb0SHoria Geanta 	}, {
4341a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha1),cbc(aes))",
4342e46e9a46SHoria Geanta 		.test = alg_test_aead,
4343bcf741cbSHerbert Xu 		.fips_allowed = 1,
4344e46e9a46SHoria Geanta 		.suite = {
4345a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_aes_cbc_tv_temp)
43465208ed2cSNitesh Lal 		}
43475208ed2cSNitesh Lal 	}, {
4348a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha1),cbc(des))",
43495208ed2cSNitesh Lal 		.test = alg_test_aead,
43505208ed2cSNitesh Lal 		.suite = {
4351a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_des_cbc_tv_temp)
43525208ed2cSNitesh Lal 		}
43535208ed2cSNitesh Lal 	}, {
4354a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha1),cbc(des3_ede))",
43555208ed2cSNitesh Lal 		.test = alg_test_aead,
43565208ed2cSNitesh Lal 		.suite = {
4357a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_des3_ede_cbc_tv_temp)
4358e46e9a46SHoria Geanta 		}
4359e46e9a46SHoria Geanta 	}, {
4360fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha1),ctr(aes))",
4361fb16abc2SMarcus Meissner 		.test = alg_test_null,
4362fb16abc2SMarcus Meissner 		.fips_allowed = 1,
4363fb16abc2SMarcus Meissner 	}, {
4364bca4feb0SHoria Geanta 		.alg = "authenc(hmac(sha1),ecb(cipher_null))",
4365bca4feb0SHoria Geanta 		.test = alg_test_aead,
4366bca4feb0SHoria Geanta 		.suite = {
4367a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_ecb_cipher_null_tv_temp)
43685208ed2cSNitesh Lal 		}
43695208ed2cSNitesh Lal 	}, {
43708888690eSMarcus Meissner 		.alg = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
43718888690eSMarcus Meissner 		.test = alg_test_null,
43728888690eSMarcus Meissner 		.fips_allowed = 1,
43738888690eSMarcus Meissner 	}, {
4374a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha224),cbc(des))",
43755208ed2cSNitesh Lal 		.test = alg_test_aead,
43765208ed2cSNitesh Lal 		.suite = {
4377a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha224_des_cbc_tv_temp)
43785208ed2cSNitesh Lal 		}
43795208ed2cSNitesh Lal 	}, {
4380a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha224),cbc(des3_ede))",
43815208ed2cSNitesh Lal 		.test = alg_test_aead,
43825208ed2cSNitesh Lal 		.suite = {
4383a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha224_des3_ede_cbc_tv_temp)
4384bca4feb0SHoria Geanta 		}
4385bca4feb0SHoria Geanta 	}, {
4386a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha256),cbc(aes))",
4387e46e9a46SHoria Geanta 		.test = alg_test_aead,
4388ed1afac9SMarcus Meissner 		.fips_allowed = 1,
4389e46e9a46SHoria Geanta 		.suite = {
4390a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha256_aes_cbc_tv_temp)
43915208ed2cSNitesh Lal 		}
43925208ed2cSNitesh Lal 	}, {
4393a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha256),cbc(des))",
43945208ed2cSNitesh Lal 		.test = alg_test_aead,
43955208ed2cSNitesh Lal 		.suite = {
4396a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha256_des_cbc_tv_temp)
43975208ed2cSNitesh Lal 		}
43985208ed2cSNitesh Lal 	}, {
4399a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha256),cbc(des3_ede))",
44005208ed2cSNitesh Lal 		.test = alg_test_aead,
44015208ed2cSNitesh Lal 		.suite = {
4402a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha256_des3_ede_cbc_tv_temp)
44035208ed2cSNitesh Lal 		}
44045208ed2cSNitesh Lal 	}, {
4405fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha256),ctr(aes))",
4406fb16abc2SMarcus Meissner 		.test = alg_test_null,
4407fb16abc2SMarcus Meissner 		.fips_allowed = 1,
4408fb16abc2SMarcus Meissner 	}, {
44098888690eSMarcus Meissner 		.alg = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
44108888690eSMarcus Meissner 		.test = alg_test_null,
44118888690eSMarcus Meissner 		.fips_allowed = 1,
44128888690eSMarcus Meissner 	}, {
4413a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha384),cbc(des))",
44145208ed2cSNitesh Lal 		.test = alg_test_aead,
44155208ed2cSNitesh Lal 		.suite = {
4416a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha384_des_cbc_tv_temp)
44175208ed2cSNitesh Lal 		}
44185208ed2cSNitesh Lal 	}, {
4419a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha384),cbc(des3_ede))",
44205208ed2cSNitesh Lal 		.test = alg_test_aead,
44215208ed2cSNitesh Lal 		.suite = {
4422a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha384_des3_ede_cbc_tv_temp)
4423e46e9a46SHoria Geanta 		}
4424e46e9a46SHoria Geanta 	}, {
4425fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha384),ctr(aes))",
4426fb16abc2SMarcus Meissner 		.test = alg_test_null,
4427fb16abc2SMarcus Meissner 		.fips_allowed = 1,
4428fb16abc2SMarcus Meissner 	}, {
44298888690eSMarcus Meissner 		.alg = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
44308888690eSMarcus Meissner 		.test = alg_test_null,
44318888690eSMarcus Meissner 		.fips_allowed = 1,
44328888690eSMarcus Meissner 	}, {
4433a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha512),cbc(aes))",
4434ed1afac9SMarcus Meissner 		.fips_allowed = 1,
4435e46e9a46SHoria Geanta 		.test = alg_test_aead,
4436e46e9a46SHoria Geanta 		.suite = {
4437a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha512_aes_cbc_tv_temp)
44385208ed2cSNitesh Lal 		}
44395208ed2cSNitesh Lal 	}, {
4440a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha512),cbc(des))",
44415208ed2cSNitesh Lal 		.test = alg_test_aead,
44425208ed2cSNitesh Lal 		.suite = {
4443a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha512_des_cbc_tv_temp)
44445208ed2cSNitesh Lal 		}
44455208ed2cSNitesh Lal 	}, {
4446a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha512),cbc(des3_ede))",
44475208ed2cSNitesh Lal 		.test = alg_test_aead,
44485208ed2cSNitesh Lal 		.suite = {
4449a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha512_des3_ede_cbc_tv_temp)
4450e46e9a46SHoria Geanta 		}
4451e46e9a46SHoria Geanta 	}, {
4452fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha512),ctr(aes))",
4453fb16abc2SMarcus Meissner 		.test = alg_test_null,
4454fb16abc2SMarcus Meissner 		.fips_allowed = 1,
4455fb16abc2SMarcus Meissner 	}, {
44568888690eSMarcus Meissner 		.alg = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
44578888690eSMarcus Meissner 		.test = alg_test_null,
44588888690eSMarcus Meissner 		.fips_allowed = 1,
44598888690eSMarcus Meissner 	}, {
4460a1afe274SDavid Sterba 		.alg = "blake2b-160",
4461a1afe274SDavid Sterba 		.test = alg_test_hash,
4462a1afe274SDavid Sterba 		.fips_allowed = 0,
4463a1afe274SDavid Sterba 		.suite = {
4464a1afe274SDavid Sterba 			.hash = __VECS(blake2b_160_tv_template)
4465a1afe274SDavid Sterba 		}
4466a1afe274SDavid Sterba 	}, {
4467a1afe274SDavid Sterba 		.alg = "blake2b-256",
4468a1afe274SDavid Sterba 		.test = alg_test_hash,
4469a1afe274SDavid Sterba 		.fips_allowed = 0,
4470a1afe274SDavid Sterba 		.suite = {
4471a1afe274SDavid Sterba 			.hash = __VECS(blake2b_256_tv_template)
4472a1afe274SDavid Sterba 		}
4473a1afe274SDavid Sterba 	}, {
4474a1afe274SDavid Sterba 		.alg = "blake2b-384",
4475a1afe274SDavid Sterba 		.test = alg_test_hash,
4476a1afe274SDavid Sterba 		.fips_allowed = 0,
4477a1afe274SDavid Sterba 		.suite = {
4478a1afe274SDavid Sterba 			.hash = __VECS(blake2b_384_tv_template)
4479a1afe274SDavid Sterba 		}
4480a1afe274SDavid Sterba 	}, {
4481a1afe274SDavid Sterba 		.alg = "blake2b-512",
4482a1afe274SDavid Sterba 		.test = alg_test_hash,
4483a1afe274SDavid Sterba 		.fips_allowed = 0,
4484a1afe274SDavid Sterba 		.suite = {
4485a1afe274SDavid Sterba 			.hash = __VECS(blake2b_512_tv_template)
4486a1afe274SDavid Sterba 		}
4487a1afe274SDavid Sterba 	}, {
4488da7f033dSHerbert Xu 		.alg = "cbc(aes)",
44891aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4490a1915d51SJarod Wilson 		.fips_allowed = 1,
4491da7f033dSHerbert Xu 		.suite = {
449292a4c9feSEric Biggers 			.cipher = __VECS(aes_cbc_tv_template)
449392a4c9feSEric Biggers 		},
4494da7f033dSHerbert Xu 	}, {
4495da7f033dSHerbert Xu 		.alg = "cbc(anubis)",
44961aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4497da7f033dSHerbert Xu 		.suite = {
449892a4c9feSEric Biggers 			.cipher = __VECS(anubis_cbc_tv_template)
449992a4c9feSEric Biggers 		},
4500da7f033dSHerbert Xu 	}, {
450101ce31deSTaehee Yoo 		.alg = "cbc(aria)",
450201ce31deSTaehee Yoo 		.test = alg_test_skcipher,
450301ce31deSTaehee Yoo 		.suite = {
450401ce31deSTaehee Yoo 			.cipher = __VECS(aria_cbc_tv_template)
450501ce31deSTaehee Yoo 		},
450601ce31deSTaehee Yoo 	}, {
4507da7f033dSHerbert Xu 		.alg = "cbc(blowfish)",
45081aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4509da7f033dSHerbert Xu 		.suite = {
451092a4c9feSEric Biggers 			.cipher = __VECS(bf_cbc_tv_template)
451192a4c9feSEric Biggers 		},
4512da7f033dSHerbert Xu 	}, {
4513da7f033dSHerbert Xu 		.alg = "cbc(camellia)",
45141aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4515da7f033dSHerbert Xu 		.suite = {
451692a4c9feSEric Biggers 			.cipher = __VECS(camellia_cbc_tv_template)
451792a4c9feSEric Biggers 		},
4518da7f033dSHerbert Xu 	}, {
4519a2c58260SJohannes Goetzfried 		.alg = "cbc(cast5)",
4520a2c58260SJohannes Goetzfried 		.test = alg_test_skcipher,
4521a2c58260SJohannes Goetzfried 		.suite = {
452292a4c9feSEric Biggers 			.cipher = __VECS(cast5_cbc_tv_template)
452392a4c9feSEric Biggers 		},
4524a2c58260SJohannes Goetzfried 	}, {
45259b8b0405SJohannes Goetzfried 		.alg = "cbc(cast6)",
45269b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
45279b8b0405SJohannes Goetzfried 		.suite = {
452892a4c9feSEric Biggers 			.cipher = __VECS(cast6_cbc_tv_template)
452992a4c9feSEric Biggers 		},
45309b8b0405SJohannes Goetzfried 	}, {
4531da7f033dSHerbert Xu 		.alg = "cbc(des)",
45321aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4533da7f033dSHerbert Xu 		.suite = {
453492a4c9feSEric Biggers 			.cipher = __VECS(des_cbc_tv_template)
453592a4c9feSEric Biggers 		},
4536da7f033dSHerbert Xu 	}, {
4537da7f033dSHerbert Xu 		.alg = "cbc(des3_ede)",
45381aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4539da7f033dSHerbert Xu 		.suite = {
454092a4c9feSEric Biggers 			.cipher = __VECS(des3_ede_cbc_tv_template)
454192a4c9feSEric Biggers 		},
4542da7f033dSHerbert Xu 	}, {
4543a794d8d8SGilad Ben-Yossef 		/* Same as cbc(aes) except the key is stored in
4544a794d8d8SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
4545a794d8d8SGilad Ben-Yossef 		 */
4546a794d8d8SGilad Ben-Yossef 		.alg = "cbc(paes)",
4547a794d8d8SGilad Ben-Yossef 		.test = alg_test_null,
4548a794d8d8SGilad Ben-Yossef 		.fips_allowed = 1,
4549a794d8d8SGilad Ben-Yossef 	}, {
4550f0372c00SGilad Ben-Yossef 		/* Same as cbc(sm4) except the key is stored in
4551f0372c00SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
4552f0372c00SGilad Ben-Yossef 		 */
4553f0372c00SGilad Ben-Yossef 		.alg = "cbc(psm4)",
4554f0372c00SGilad Ben-Yossef 		.test = alg_test_null,
4555f0372c00SGilad Ben-Yossef 	}, {
45569d25917dSJussi Kivilinna 		.alg = "cbc(serpent)",
45579d25917dSJussi Kivilinna 		.test = alg_test_skcipher,
45589d25917dSJussi Kivilinna 		.suite = {
455992a4c9feSEric Biggers 			.cipher = __VECS(serpent_cbc_tv_template)
456092a4c9feSEric Biggers 		},
45619d25917dSJussi Kivilinna 	}, {
456295ba5973SGilad Ben-Yossef 		.alg = "cbc(sm4)",
456395ba5973SGilad Ben-Yossef 		.test = alg_test_skcipher,
456495ba5973SGilad Ben-Yossef 		.suite = {
456595ba5973SGilad Ben-Yossef 			.cipher = __VECS(sm4_cbc_tv_template)
456695ba5973SGilad Ben-Yossef 		}
456795ba5973SGilad Ben-Yossef 	}, {
4568da7f033dSHerbert Xu 		.alg = "cbc(twofish)",
45691aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4570da7f033dSHerbert Xu 		.suite = {
457192a4c9feSEric Biggers 			.cipher = __VECS(tf_cbc_tv_template)
457292a4c9feSEric Biggers 		},
4573da7f033dSHerbert Xu 	}, {
4574c7ff8573SHarald Freudenberger #if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
4575c7ff8573SHarald Freudenberger 		.alg = "cbc-paes-s390",
4576c7ff8573SHarald Freudenberger 		.fips_allowed = 1,
4577c7ff8573SHarald Freudenberger 		.test = alg_test_skcipher,
4578c7ff8573SHarald Freudenberger 		.suite = {
4579c7ff8573SHarald Freudenberger 			.cipher = __VECS(aes_cbc_tv_template)
4580c7ff8573SHarald Freudenberger 		}
4581c7ff8573SHarald Freudenberger 	}, {
4582c7ff8573SHarald Freudenberger #endif
4583092acf06SArd Biesheuvel 		.alg = "cbcmac(aes)",
4584092acf06SArd Biesheuvel 		.test = alg_test_hash,
4585092acf06SArd Biesheuvel 		.suite = {
4586092acf06SArd Biesheuvel 			.hash = __VECS(aes_cbcmac_tv_template)
4587092acf06SArd Biesheuvel 		}
4588092acf06SArd Biesheuvel 	}, {
458968039d60STianjia Zhang 		.alg = "cbcmac(sm4)",
459068039d60STianjia Zhang 		.test = alg_test_hash,
459168039d60STianjia Zhang 		.suite = {
459268039d60STianjia Zhang 			.hash = __VECS(sm4_cbcmac_tv_template)
459368039d60STianjia Zhang 		}
459468039d60STianjia Zhang 	}, {
4595da7f033dSHerbert Xu 		.alg = "ccm(aes)",
459640153b10SEric Biggers 		.generic_driver = "ccm_base(ctr(aes-generic),cbcmac(aes-generic))",
4597da7f033dSHerbert Xu 		.test = alg_test_aead,
4598a1915d51SJarod Wilson 		.fips_allowed = 1,
4599da7f033dSHerbert Xu 		.suite = {
460049763fc6SEric Biggers 			.aead = {
460149763fc6SEric Biggers 				____VECS(aes_ccm_tv_template),
460249763fc6SEric Biggers 				.einval_allowed = 1,
460349763fc6SEric Biggers 			}
4604da7f033dSHerbert Xu 		}
4605da7f033dSHerbert Xu 	}, {
460668039d60STianjia Zhang 		.alg = "ccm(sm4)",
460768039d60STianjia Zhang 		.generic_driver = "ccm_base(ctr(sm4-generic),cbcmac(sm4-generic))",
460868039d60STianjia Zhang 		.test = alg_test_aead,
460968039d60STianjia Zhang 		.suite = {
461068039d60STianjia Zhang 			.aead = {
461168039d60STianjia Zhang 				____VECS(sm4_ccm_tv_template),
461268039d60STianjia Zhang 				.einval_allowed = 1,
461368039d60STianjia Zhang 			}
461468039d60STianjia Zhang 		}
461568039d60STianjia Zhang 	}, {
46167da66670SDmitry Eremin-Solenikov 		.alg = "cfb(aes)",
46177da66670SDmitry Eremin-Solenikov 		.test = alg_test_skcipher,
46187da66670SDmitry Eremin-Solenikov 		.fips_allowed = 1,
46197da66670SDmitry Eremin-Solenikov 		.suite = {
46207da66670SDmitry Eremin-Solenikov 			.cipher = __VECS(aes_cfb_tv_template)
46217da66670SDmitry Eremin-Solenikov 		},
46227da66670SDmitry Eremin-Solenikov 	}, {
462301ce31deSTaehee Yoo 		.alg = "cfb(aria)",
462401ce31deSTaehee Yoo 		.test = alg_test_skcipher,
462501ce31deSTaehee Yoo 		.suite = {
462601ce31deSTaehee Yoo 			.cipher = __VECS(aria_cfb_tv_template)
462701ce31deSTaehee Yoo 		},
462801ce31deSTaehee Yoo 	}, {
4629a06b15b2SPascal van Leeuwen 		.alg = "cfb(sm4)",
4630a06b15b2SPascal van Leeuwen 		.test = alg_test_skcipher,
4631a06b15b2SPascal van Leeuwen 		.suite = {
4632a06b15b2SPascal van Leeuwen 			.cipher = __VECS(sm4_cfb_tv_template)
4633a06b15b2SPascal van Leeuwen 		}
4634a06b15b2SPascal van Leeuwen 	}, {
46353590ebf2SMartin Willi 		.alg = "chacha20",
46363590ebf2SMartin Willi 		.test = alg_test_skcipher,
46373590ebf2SMartin Willi 		.suite = {
463892a4c9feSEric Biggers 			.cipher = __VECS(chacha20_tv_template)
463992a4c9feSEric Biggers 		},
46403590ebf2SMartin Willi 	}, {
464193b5e86aSJussi Kivilinna 		.alg = "cmac(aes)",
46428f183751SStephan Mueller 		.fips_allowed = 1,
464393b5e86aSJussi Kivilinna 		.test = alg_test_hash,
464493b5e86aSJussi Kivilinna 		.suite = {
464521c8e720SArd Biesheuvel 			.hash = __VECS(aes_cmac128_tv_template)
464693b5e86aSJussi Kivilinna 		}
464793b5e86aSJussi Kivilinna 	}, {
4648*ba24b8ebSDavid Howells 		.alg = "cmac(camellia)",
4649*ba24b8ebSDavid Howells 		.test = alg_test_hash,
4650*ba24b8ebSDavid Howells 		.suite = {
4651*ba24b8ebSDavid Howells 			.hash = __VECS(camellia_cmac128_tv_template)
4652*ba24b8ebSDavid Howells 		}
4653*ba24b8ebSDavid Howells 	}, {
465493b5e86aSJussi Kivilinna 		.alg = "cmac(des3_ede)",
465593b5e86aSJussi Kivilinna 		.test = alg_test_hash,
465693b5e86aSJussi Kivilinna 		.suite = {
465721c8e720SArd Biesheuvel 			.hash = __VECS(des3_ede_cmac64_tv_template)
465893b5e86aSJussi Kivilinna 		}
465993b5e86aSJussi Kivilinna 	}, {
466068039d60STianjia Zhang 		.alg = "cmac(sm4)",
466168039d60STianjia Zhang 		.test = alg_test_hash,
466268039d60STianjia Zhang 		.suite = {
466368039d60STianjia Zhang 			.hash = __VECS(sm4_cmac128_tv_template)
466468039d60STianjia Zhang 		}
466568039d60STianjia Zhang 	}, {
4666e448370dSJussi Kivilinna 		.alg = "compress_null",
4667e448370dSJussi Kivilinna 		.test = alg_test_null,
4668e448370dSJussi Kivilinna 	}, {
4669ebb3472fSArd Biesheuvel 		.alg = "crc32",
4670ebb3472fSArd Biesheuvel 		.test = alg_test_hash,
4671a8a34416SMilan Broz 		.fips_allowed = 1,
4672ebb3472fSArd Biesheuvel 		.suite = {
467321c8e720SArd Biesheuvel 			.hash = __VECS(crc32_tv_template)
4674ebb3472fSArd Biesheuvel 		}
4675ebb3472fSArd Biesheuvel 	}, {
4676da7f033dSHerbert Xu 		.alg = "crc32c",
46778e3ee85eSHerbert Xu 		.test = alg_test_crc32c,
4678a1915d51SJarod Wilson 		.fips_allowed = 1,
4679da7f033dSHerbert Xu 		.suite = {
468021c8e720SArd Biesheuvel 			.hash = __VECS(crc32c_tv_template)
4681da7f033dSHerbert Xu 		}
4682da7f033dSHerbert Xu 	}, {
4683f3813f4bSKeith Busch 		.alg = "crc64-rocksoft",
4684f3813f4bSKeith Busch 		.test = alg_test_hash,
4685f3813f4bSKeith Busch 		.fips_allowed = 1,
4686f3813f4bSKeith Busch 		.suite = {
4687f3813f4bSKeith Busch 			.hash = __VECS(crc64_rocksoft_tv_template)
4688f3813f4bSKeith Busch 		}
4689f3813f4bSKeith Busch 	}, {
469068411521SHerbert Xu 		.alg = "crct10dif",
469168411521SHerbert Xu 		.test = alg_test_hash,
469268411521SHerbert Xu 		.fips_allowed = 1,
469368411521SHerbert Xu 		.suite = {
469421c8e720SArd Biesheuvel 			.hash = __VECS(crct10dif_tv_template)
469568411521SHerbert Xu 		}
469668411521SHerbert Xu 	}, {
4697f7cb80f2SJarod Wilson 		.alg = "ctr(aes)",
4698f7cb80f2SJarod Wilson 		.test = alg_test_skcipher,
4699a1915d51SJarod Wilson 		.fips_allowed = 1,
4700f7cb80f2SJarod Wilson 		.suite = {
470192a4c9feSEric Biggers 			.cipher = __VECS(aes_ctr_tv_template)
4702f7cb80f2SJarod Wilson 		}
4703f7cb80f2SJarod Wilson 	}, {
470401ce31deSTaehee Yoo 		.alg = "ctr(aria)",
470501ce31deSTaehee Yoo 		.test = alg_test_skcipher,
470601ce31deSTaehee Yoo 		.suite = {
470701ce31deSTaehee Yoo 			.cipher = __VECS(aria_ctr_tv_template)
470801ce31deSTaehee Yoo 		}
470901ce31deSTaehee Yoo 	}, {
471085b63e34SJussi Kivilinna 		.alg = "ctr(blowfish)",
471185b63e34SJussi Kivilinna 		.test = alg_test_skcipher,
471285b63e34SJussi Kivilinna 		.suite = {
471392a4c9feSEric Biggers 			.cipher = __VECS(bf_ctr_tv_template)
471485b63e34SJussi Kivilinna 		}
471585b63e34SJussi Kivilinna 	}, {
47160840605eSJussi Kivilinna 		.alg = "ctr(camellia)",
47170840605eSJussi Kivilinna 		.test = alg_test_skcipher,
47180840605eSJussi Kivilinna 		.suite = {
471992a4c9feSEric Biggers 			.cipher = __VECS(camellia_ctr_tv_template)
47200840605eSJussi Kivilinna 		}
47210840605eSJussi Kivilinna 	}, {
4722a2c58260SJohannes Goetzfried 		.alg = "ctr(cast5)",
4723a2c58260SJohannes Goetzfried 		.test = alg_test_skcipher,
4724a2c58260SJohannes Goetzfried 		.suite = {
472592a4c9feSEric Biggers 			.cipher = __VECS(cast5_ctr_tv_template)
4726a2c58260SJohannes Goetzfried 		}
4727a2c58260SJohannes Goetzfried 	}, {
47289b8b0405SJohannes Goetzfried 		.alg = "ctr(cast6)",
47299b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
47309b8b0405SJohannes Goetzfried 		.suite = {
473192a4c9feSEric Biggers 			.cipher = __VECS(cast6_ctr_tv_template)
47329b8b0405SJohannes Goetzfried 		}
47339b8b0405SJohannes Goetzfried 	}, {
47348163fc30SJussi Kivilinna 		.alg = "ctr(des)",
47358163fc30SJussi Kivilinna 		.test = alg_test_skcipher,
47368163fc30SJussi Kivilinna 		.suite = {
473792a4c9feSEric Biggers 			.cipher = __VECS(des_ctr_tv_template)
47388163fc30SJussi Kivilinna 		}
47398163fc30SJussi Kivilinna 	}, {
4740e080b17aSJussi Kivilinna 		.alg = "ctr(des3_ede)",
4741e080b17aSJussi Kivilinna 		.test = alg_test_skcipher,
4742e080b17aSJussi Kivilinna 		.suite = {
474392a4c9feSEric Biggers 			.cipher = __VECS(des3_ede_ctr_tv_template)
4744e080b17aSJussi Kivilinna 		}
4745e080b17aSJussi Kivilinna 	}, {
4746a794d8d8SGilad Ben-Yossef 		/* Same as ctr(aes) except the key is stored in
4747a794d8d8SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
4748a794d8d8SGilad Ben-Yossef 		 */
4749a794d8d8SGilad Ben-Yossef 		.alg = "ctr(paes)",
4750a794d8d8SGilad Ben-Yossef 		.test = alg_test_null,
4751a794d8d8SGilad Ben-Yossef 		.fips_allowed = 1,
4752a794d8d8SGilad Ben-Yossef 	}, {
4753f0372c00SGilad Ben-Yossef 
4754f0372c00SGilad Ben-Yossef 		/* Same as ctr(sm4) except the key is stored in
4755f0372c00SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
4756f0372c00SGilad Ben-Yossef 		 */
4757f0372c00SGilad Ben-Yossef 		.alg = "ctr(psm4)",
4758f0372c00SGilad Ben-Yossef 		.test = alg_test_null,
4759f0372c00SGilad Ben-Yossef 	}, {
47609d25917dSJussi Kivilinna 		.alg = "ctr(serpent)",
47619d25917dSJussi Kivilinna 		.test = alg_test_skcipher,
47629d25917dSJussi Kivilinna 		.suite = {
476392a4c9feSEric Biggers 			.cipher = __VECS(serpent_ctr_tv_template)
47649d25917dSJussi Kivilinna 		}
47659d25917dSJussi Kivilinna 	}, {
476695ba5973SGilad Ben-Yossef 		.alg = "ctr(sm4)",
476795ba5973SGilad Ben-Yossef 		.test = alg_test_skcipher,
476895ba5973SGilad Ben-Yossef 		.suite = {
476995ba5973SGilad Ben-Yossef 			.cipher = __VECS(sm4_ctr_tv_template)
477095ba5973SGilad Ben-Yossef 		}
477195ba5973SGilad Ben-Yossef 	}, {
4772573da620SJussi Kivilinna 		.alg = "ctr(twofish)",
4773573da620SJussi Kivilinna 		.test = alg_test_skcipher,
4774573da620SJussi Kivilinna 		.suite = {
477592a4c9feSEric Biggers 			.cipher = __VECS(tf_ctr_tv_template)
4776573da620SJussi Kivilinna 		}
4777573da620SJussi Kivilinna 	}, {
4778c7ff8573SHarald Freudenberger #if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
4779c7ff8573SHarald Freudenberger 		.alg = "ctr-paes-s390",
4780c7ff8573SHarald Freudenberger 		.fips_allowed = 1,
4781c7ff8573SHarald Freudenberger 		.test = alg_test_skcipher,
4782c7ff8573SHarald Freudenberger 		.suite = {
4783c7ff8573SHarald Freudenberger 			.cipher = __VECS(aes_ctr_tv_template)
4784c7ff8573SHarald Freudenberger 		}
4785c7ff8573SHarald Freudenberger 	}, {
4786c7ff8573SHarald Freudenberger #endif
4787da7f033dSHerbert Xu 		.alg = "cts(cbc(aes))",
47881aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4789196ad604SGilad Ben-Yossef 		.fips_allowed = 1,
4790da7f033dSHerbert Xu 		.suite = {
479192a4c9feSEric Biggers 			.cipher = __VECS(cts_mode_tv_template)
4792da7f033dSHerbert Xu 		}
4793da7f033dSHerbert Xu 	}, {
4794f0372c00SGilad Ben-Yossef 		/* Same as cts(cbc((aes)) except the key is stored in
4795f0372c00SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
4796f0372c00SGilad Ben-Yossef 		 */
4797f0372c00SGilad Ben-Yossef 		.alg = "cts(cbc(paes))",
4798f0372c00SGilad Ben-Yossef 		.test = alg_test_null,
4799f0372c00SGilad Ben-Yossef 		.fips_allowed = 1,
4800f0372c00SGilad Ben-Yossef 	}, {
4801c24ee936STianjia Zhang 		.alg = "cts(cbc(sm4))",
4802c24ee936STianjia Zhang 		.test = alg_test_skcipher,
4803c24ee936STianjia Zhang 		.suite = {
4804c24ee936STianjia Zhang 			.cipher = __VECS(sm4_cts_tv_template)
4805c24ee936STianjia Zhang 		}
4806c24ee936STianjia Zhang 	}, {
4807f613457aSArd Biesheuvel 		.alg = "curve25519",
4808f613457aSArd Biesheuvel 		.test = alg_test_kpp,
4809f613457aSArd Biesheuvel 		.suite = {
4810f613457aSArd Biesheuvel 			.kpp = __VECS(curve25519_tv_template)
4811f613457aSArd Biesheuvel 		}
4812f613457aSArd Biesheuvel 	}, {
4813da7f033dSHerbert Xu 		.alg = "deflate",
4814da7f033dSHerbert Xu 		.test = alg_test_comp,
48150818904dSMilan Broz 		.fips_allowed = 1,
4816da7f033dSHerbert Xu 		.suite = {
4817da7f033dSHerbert Xu 			.comp = {
481821c8e720SArd Biesheuvel 				.comp = __VECS(deflate_comp_tv_template),
481921c8e720SArd Biesheuvel 				.decomp = __VECS(deflate_decomp_tv_template)
4820da7f033dSHerbert Xu 			}
4821da7f033dSHerbert Xu 		}
4822da7f033dSHerbert Xu 	}, {
4823802c7f1cSSalvatore Benedetto 		.alg = "dh",
4824802c7f1cSSalvatore Benedetto 		.test = alg_test_kpp,
4825802c7f1cSSalvatore Benedetto 		.suite = {
482621c8e720SArd Biesheuvel 			.kpp = __VECS(dh_tv_template)
4827802c7f1cSSalvatore Benedetto 		}
4828802c7f1cSSalvatore Benedetto 	}, {
4829e448370dSJussi Kivilinna 		.alg = "digest_null",
4830e448370dSJussi Kivilinna 		.test = alg_test_null,
4831e448370dSJussi Kivilinna 	}, {
483264d1cdfbSStephan Mueller 		.alg = "drbg_nopr_ctr_aes128",
483364d1cdfbSStephan Mueller 		.test = alg_test_drbg,
483464d1cdfbSStephan Mueller 		.fips_allowed = 1,
483564d1cdfbSStephan Mueller 		.suite = {
483621c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_ctr_aes128_tv_template)
483764d1cdfbSStephan Mueller 		}
483864d1cdfbSStephan Mueller 	}, {
483964d1cdfbSStephan Mueller 		.alg = "drbg_nopr_ctr_aes192",
484064d1cdfbSStephan Mueller 		.test = alg_test_drbg,
484164d1cdfbSStephan Mueller 		.fips_allowed = 1,
484264d1cdfbSStephan Mueller 		.suite = {
484321c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_ctr_aes192_tv_template)
484464d1cdfbSStephan Mueller 		}
484564d1cdfbSStephan Mueller 	}, {
484664d1cdfbSStephan Mueller 		.alg = "drbg_nopr_ctr_aes256",
484764d1cdfbSStephan Mueller 		.test = alg_test_drbg,
484864d1cdfbSStephan Mueller 		.fips_allowed = 1,
484964d1cdfbSStephan Mueller 		.suite = {
485021c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_ctr_aes256_tv_template)
485164d1cdfbSStephan Mueller 		}
485264d1cdfbSStephan Mueller 	}, {
485364d1cdfbSStephan Mueller 		/*
485464d1cdfbSStephan Mueller 		 * There is no need to specifically test the DRBG with every
485564d1cdfbSStephan Mueller 		 * backend cipher -- covered by drbg_nopr_hmac_sha256 test
485664d1cdfbSStephan Mueller 		 */
485764d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha1",
485864d1cdfbSStephan Mueller 		.fips_allowed = 1,
485964d1cdfbSStephan Mueller 		.test = alg_test_null,
486064d1cdfbSStephan Mueller 	}, {
486164d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha256",
486264d1cdfbSStephan Mueller 		.test = alg_test_drbg,
486364d1cdfbSStephan Mueller 		.fips_allowed = 1,
486464d1cdfbSStephan Mueller 		.suite = {
486521c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_hmac_sha256_tv_template)
486664d1cdfbSStephan Mueller 		}
486764d1cdfbSStephan Mueller 	}, {
486864d1cdfbSStephan Mueller 		/* covered by drbg_nopr_hmac_sha256 test */
486964d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha384",
487064d1cdfbSStephan Mueller 		.test = alg_test_null,
487164d1cdfbSStephan Mueller 	}, {
487264d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha512",
48738833272dSStephan Müller 		.test = alg_test_drbg,
487464d1cdfbSStephan Mueller 		.fips_allowed = 1,
48758833272dSStephan Müller 		.suite = {
48768833272dSStephan Müller 			.drbg = __VECS(drbg_nopr_hmac_sha512_tv_template)
48778833272dSStephan Müller 		}
487864d1cdfbSStephan Mueller 	}, {
487964d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha1",
488064d1cdfbSStephan Mueller 		.fips_allowed = 1,
488164d1cdfbSStephan Mueller 		.test = alg_test_null,
488264d1cdfbSStephan Mueller 	}, {
488364d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha256",
488464d1cdfbSStephan Mueller 		.test = alg_test_drbg,
488564d1cdfbSStephan Mueller 		.fips_allowed = 1,
488664d1cdfbSStephan Mueller 		.suite = {
488721c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_sha256_tv_template)
488864d1cdfbSStephan Mueller 		}
488964d1cdfbSStephan Mueller 	}, {
489064d1cdfbSStephan Mueller 		/* covered by drbg_nopr_sha256 test */
489164d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha384",
489264d1cdfbSStephan Mueller 		.test = alg_test_null,
489364d1cdfbSStephan Mueller 	}, {
489464d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha512",
489564d1cdfbSStephan Mueller 		.fips_allowed = 1,
489664d1cdfbSStephan Mueller 		.test = alg_test_null,
489764d1cdfbSStephan Mueller 	}, {
489864d1cdfbSStephan Mueller 		.alg = "drbg_pr_ctr_aes128",
489964d1cdfbSStephan Mueller 		.test = alg_test_drbg,
490064d1cdfbSStephan Mueller 		.fips_allowed = 1,
490164d1cdfbSStephan Mueller 		.suite = {
490221c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_pr_ctr_aes128_tv_template)
490364d1cdfbSStephan Mueller 		}
490464d1cdfbSStephan Mueller 	}, {
490564d1cdfbSStephan Mueller 		/* covered by drbg_pr_ctr_aes128 test */
490664d1cdfbSStephan Mueller 		.alg = "drbg_pr_ctr_aes192",
490764d1cdfbSStephan Mueller 		.fips_allowed = 1,
490864d1cdfbSStephan Mueller 		.test = alg_test_null,
490964d1cdfbSStephan Mueller 	}, {
491064d1cdfbSStephan Mueller 		.alg = "drbg_pr_ctr_aes256",
491164d1cdfbSStephan Mueller 		.fips_allowed = 1,
491264d1cdfbSStephan Mueller 		.test = alg_test_null,
491364d1cdfbSStephan Mueller 	}, {
491464d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha1",
491564d1cdfbSStephan Mueller 		.fips_allowed = 1,
491664d1cdfbSStephan Mueller 		.test = alg_test_null,
491764d1cdfbSStephan Mueller 	}, {
491864d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha256",
491964d1cdfbSStephan Mueller 		.test = alg_test_drbg,
492064d1cdfbSStephan Mueller 		.fips_allowed = 1,
492164d1cdfbSStephan Mueller 		.suite = {
492221c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_pr_hmac_sha256_tv_template)
492364d1cdfbSStephan Mueller 		}
492464d1cdfbSStephan Mueller 	}, {
492564d1cdfbSStephan Mueller 		/* covered by drbg_pr_hmac_sha256 test */
492664d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha384",
492764d1cdfbSStephan Mueller 		.test = alg_test_null,
492864d1cdfbSStephan Mueller 	}, {
492964d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha512",
493064d1cdfbSStephan Mueller 		.test = alg_test_null,
493164d1cdfbSStephan Mueller 		.fips_allowed = 1,
493264d1cdfbSStephan Mueller 	}, {
493364d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha1",
493464d1cdfbSStephan Mueller 		.fips_allowed = 1,
493564d1cdfbSStephan Mueller 		.test = alg_test_null,
493664d1cdfbSStephan Mueller 	}, {
493764d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha256",
493864d1cdfbSStephan Mueller 		.test = alg_test_drbg,
493964d1cdfbSStephan Mueller 		.fips_allowed = 1,
494064d1cdfbSStephan Mueller 		.suite = {
494121c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_pr_sha256_tv_template)
494264d1cdfbSStephan Mueller 		}
494364d1cdfbSStephan Mueller 	}, {
494464d1cdfbSStephan Mueller 		/* covered by drbg_pr_sha256 test */
494564d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha384",
494664d1cdfbSStephan Mueller 		.test = alg_test_null,
494764d1cdfbSStephan Mueller 	}, {
494864d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha512",
494964d1cdfbSStephan Mueller 		.fips_allowed = 1,
495064d1cdfbSStephan Mueller 		.test = alg_test_null,
495164d1cdfbSStephan Mueller 	}, {
4952da7f033dSHerbert Xu 		.alg = "ecb(aes)",
49531aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4954a1915d51SJarod Wilson 		.fips_allowed = 1,
4955da7f033dSHerbert Xu 		.suite = {
495692a4c9feSEric Biggers 			.cipher = __VECS(aes_tv_template)
4957da7f033dSHerbert Xu 		}
4958da7f033dSHerbert Xu 	}, {
4959da7f033dSHerbert Xu 		.alg = "ecb(anubis)",
49601aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4961da7f033dSHerbert Xu 		.suite = {
496292a4c9feSEric Biggers 			.cipher = __VECS(anubis_tv_template)
4963da7f033dSHerbert Xu 		}
4964da7f033dSHerbert Xu 	}, {
4965da7f033dSHerbert Xu 		.alg = "ecb(arc4)",
4966611a23c2SArd Biesheuvel 		.generic_driver = "ecb(arc4)-generic",
49671aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4968da7f033dSHerbert Xu 		.suite = {
496992a4c9feSEric Biggers 			.cipher = __VECS(arc4_tv_template)
4970da7f033dSHerbert Xu 		}
4971da7f033dSHerbert Xu 	}, {
497201ce31deSTaehee Yoo 		.alg = "ecb(aria)",
497301ce31deSTaehee Yoo 		.test = alg_test_skcipher,
497401ce31deSTaehee Yoo 		.suite = {
497501ce31deSTaehee Yoo 			.cipher = __VECS(aria_tv_template)
497601ce31deSTaehee Yoo 		}
497701ce31deSTaehee Yoo 	}, {
4978da7f033dSHerbert Xu 		.alg = "ecb(blowfish)",
49791aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4980da7f033dSHerbert Xu 		.suite = {
498192a4c9feSEric Biggers 			.cipher = __VECS(bf_tv_template)
4982da7f033dSHerbert Xu 		}
4983da7f033dSHerbert Xu 	}, {
4984da7f033dSHerbert Xu 		.alg = "ecb(camellia)",
49851aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4986da7f033dSHerbert Xu 		.suite = {
498792a4c9feSEric Biggers 			.cipher = __VECS(camellia_tv_template)
4988da7f033dSHerbert Xu 		}
4989da7f033dSHerbert Xu 	}, {
4990da7f033dSHerbert Xu 		.alg = "ecb(cast5)",
49911aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4992da7f033dSHerbert Xu 		.suite = {
499392a4c9feSEric Biggers 			.cipher = __VECS(cast5_tv_template)
4994da7f033dSHerbert Xu 		}
4995da7f033dSHerbert Xu 	}, {
4996da7f033dSHerbert Xu 		.alg = "ecb(cast6)",
49971aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
4998da7f033dSHerbert Xu 		.suite = {
499992a4c9feSEric Biggers 			.cipher = __VECS(cast6_tv_template)
5000da7f033dSHerbert Xu 		}
5001da7f033dSHerbert Xu 	}, {
5002e448370dSJussi Kivilinna 		.alg = "ecb(cipher_null)",
5003e448370dSJussi Kivilinna 		.test = alg_test_null,
50046175ca2bSMilan Broz 		.fips_allowed = 1,
5005e448370dSJussi Kivilinna 	}, {
5006da7f033dSHerbert Xu 		.alg = "ecb(des)",
50071aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5008da7f033dSHerbert Xu 		.suite = {
500992a4c9feSEric Biggers 			.cipher = __VECS(des_tv_template)
5010da7f033dSHerbert Xu 		}
5011da7f033dSHerbert Xu 	}, {
5012da7f033dSHerbert Xu 		.alg = "ecb(des3_ede)",
50131aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5014da7f033dSHerbert Xu 		.suite = {
501592a4c9feSEric Biggers 			.cipher = __VECS(des3_ede_tv_template)
5016da7f033dSHerbert Xu 		}
5017da7f033dSHerbert Xu 	}, {
501866e5bd00SJussi Kivilinna 		.alg = "ecb(fcrypt)",
501966e5bd00SJussi Kivilinna 		.test = alg_test_skcipher,
502066e5bd00SJussi Kivilinna 		.suite = {
502166e5bd00SJussi Kivilinna 			.cipher = {
502292a4c9feSEric Biggers 				.vecs = fcrypt_pcbc_tv_template,
502366e5bd00SJussi Kivilinna 				.count = 1
502466e5bd00SJussi Kivilinna 			}
502566e5bd00SJussi Kivilinna 		}
502666e5bd00SJussi Kivilinna 	}, {
5027da7f033dSHerbert Xu 		.alg = "ecb(khazad)",
50281aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5029da7f033dSHerbert Xu 		.suite = {
503092a4c9feSEric Biggers 			.cipher = __VECS(khazad_tv_template)
5031da7f033dSHerbert Xu 		}
5032da7f033dSHerbert Xu 	}, {
503315f47ce5SGilad Ben-Yossef 		/* Same as ecb(aes) except the key is stored in
503415f47ce5SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
503515f47ce5SGilad Ben-Yossef 		 */
503615f47ce5SGilad Ben-Yossef 		.alg = "ecb(paes)",
503715f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
503815f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
503915f47ce5SGilad Ben-Yossef 	}, {
5040da7f033dSHerbert Xu 		.alg = "ecb(seed)",
50411aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5042da7f033dSHerbert Xu 		.suite = {
504392a4c9feSEric Biggers 			.cipher = __VECS(seed_tv_template)
5044da7f033dSHerbert Xu 		}
5045da7f033dSHerbert Xu 	}, {
5046da7f033dSHerbert Xu 		.alg = "ecb(serpent)",
50471aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5048da7f033dSHerbert Xu 		.suite = {
504992a4c9feSEric Biggers 			.cipher = __VECS(serpent_tv_template)
5050da7f033dSHerbert Xu 		}
5051da7f033dSHerbert Xu 	}, {
5052cd83a8a7SGilad Ben-Yossef 		.alg = "ecb(sm4)",
5053cd83a8a7SGilad Ben-Yossef 		.test = alg_test_skcipher,
5054cd83a8a7SGilad Ben-Yossef 		.suite = {
505592a4c9feSEric Biggers 			.cipher = __VECS(sm4_tv_template)
5056cd83a8a7SGilad Ben-Yossef 		}
5057cd83a8a7SGilad Ben-Yossef 	}, {
5058da7f033dSHerbert Xu 		.alg = "ecb(tea)",
50591aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5060da7f033dSHerbert Xu 		.suite = {
506192a4c9feSEric Biggers 			.cipher = __VECS(tea_tv_template)
5062da7f033dSHerbert Xu 		}
5063da7f033dSHerbert Xu 	}, {
5064da7f033dSHerbert Xu 		.alg = "ecb(twofish)",
50651aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5066da7f033dSHerbert Xu 		.suite = {
506792a4c9feSEric Biggers 			.cipher = __VECS(tf_tv_template)
5068da7f033dSHerbert Xu 		}
5069da7f033dSHerbert Xu 	}, {
5070da7f033dSHerbert Xu 		.alg = "ecb(xeta)",
50711aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5072da7f033dSHerbert Xu 		.suite = {
507392a4c9feSEric Biggers 			.cipher = __VECS(xeta_tv_template)
5074da7f033dSHerbert Xu 		}
5075da7f033dSHerbert Xu 	}, {
5076da7f033dSHerbert Xu 		.alg = "ecb(xtea)",
50771aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5078da7f033dSHerbert Xu 		.suite = {
507992a4c9feSEric Biggers 			.cipher = __VECS(xtea_tv_template)
5080da7f033dSHerbert Xu 		}
5081da7f033dSHerbert Xu 	}, {
5082c7ff8573SHarald Freudenberger #if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
5083c7ff8573SHarald Freudenberger 		.alg = "ecb-paes-s390",
5084c7ff8573SHarald Freudenberger 		.fips_allowed = 1,
5085c7ff8573SHarald Freudenberger 		.test = alg_test_skcipher,
5086c7ff8573SHarald Freudenberger 		.suite = {
5087c7ff8573SHarald Freudenberger 			.cipher = __VECS(aes_tv_template)
5088c7ff8573SHarald Freudenberger 		}
5089c7ff8573SHarald Freudenberger 	}, {
5090c7ff8573SHarald Freudenberger #endif
50916763f5eaSMeng Yu 		.alg = "ecdh-nist-p192",
50923c4b2390SSalvatore Benedetto 		.test = alg_test_kpp,
50933c4b2390SSalvatore Benedetto 		.suite = {
50946763f5eaSMeng Yu 			.kpp = __VECS(ecdh_p192_tv_template)
50956763f5eaSMeng Yu 		}
50966763f5eaSMeng Yu 	}, {
50976763f5eaSMeng Yu 		.alg = "ecdh-nist-p256",
50986763f5eaSMeng Yu 		.test = alg_test_kpp,
50996763f5eaSMeng Yu 		.fips_allowed = 1,
51006763f5eaSMeng Yu 		.suite = {
51016763f5eaSMeng Yu 			.kpp = __VECS(ecdh_p256_tv_template)
51023c4b2390SSalvatore Benedetto 		}
51033c4b2390SSalvatore Benedetto 	}, {
51048e568fc2SHui Tang 		.alg = "ecdh-nist-p384",
51058e568fc2SHui Tang 		.test = alg_test_kpp,
51068e568fc2SHui Tang 		.fips_allowed = 1,
51078e568fc2SHui Tang 		.suite = {
51088e568fc2SHui Tang 			.kpp = __VECS(ecdh_p384_tv_template)
51098e568fc2SHui Tang 		}
51108e568fc2SHui Tang 	}, {
51114e660291SStefan Berger 		.alg = "ecdsa-nist-p192",
51124e660291SStefan Berger 		.test = alg_test_akcipher,
51134e660291SStefan Berger 		.suite = {
51144e660291SStefan Berger 			.akcipher = __VECS(ecdsa_nist_p192_tv_template)
51154e660291SStefan Berger 		}
51164e660291SStefan Berger 	}, {
51174e660291SStefan Berger 		.alg = "ecdsa-nist-p256",
51184e660291SStefan Berger 		.test = alg_test_akcipher,
5119c27b2d20SNicolai Stange 		.fips_allowed = 1,
51204e660291SStefan Berger 		.suite = {
51214e660291SStefan Berger 			.akcipher = __VECS(ecdsa_nist_p256_tv_template)
51224e660291SStefan Berger 		}
51234e660291SStefan Berger 	}, {
5124c12d448bSSaulo Alessandre 		.alg = "ecdsa-nist-p384",
5125c12d448bSSaulo Alessandre 		.test = alg_test_akcipher,
5126c27b2d20SNicolai Stange 		.fips_allowed = 1,
5127c12d448bSSaulo Alessandre 		.suite = {
5128c12d448bSSaulo Alessandre 			.akcipher = __VECS(ecdsa_nist_p384_tv_template)
5129c12d448bSSaulo Alessandre 		}
5130c12d448bSSaulo Alessandre 	}, {
513132fbdbd3SVitaly Chikunov 		.alg = "ecrdsa",
513232fbdbd3SVitaly Chikunov 		.test = alg_test_akcipher,
513332fbdbd3SVitaly Chikunov 		.suite = {
513432fbdbd3SVitaly Chikunov 			.akcipher = __VECS(ecrdsa_tv_template)
513532fbdbd3SVitaly Chikunov 		}
513632fbdbd3SVitaly Chikunov 	}, {
5137f975abb2SArd Biesheuvel 		.alg = "essiv(authenc(hmac(sha256),cbc(aes)),sha256)",
5138f975abb2SArd Biesheuvel 		.test = alg_test_aead,
5139f975abb2SArd Biesheuvel 		.fips_allowed = 1,
5140f975abb2SArd Biesheuvel 		.suite = {
5141f975abb2SArd Biesheuvel 			.aead = __VECS(essiv_hmac_sha256_aes_cbc_tv_temp)
5142f975abb2SArd Biesheuvel 		}
5143f975abb2SArd Biesheuvel 	}, {
5144f975abb2SArd Biesheuvel 		.alg = "essiv(cbc(aes),sha256)",
5145f975abb2SArd Biesheuvel 		.test = alg_test_skcipher,
5146f975abb2SArd Biesheuvel 		.fips_allowed = 1,
5147f975abb2SArd Biesheuvel 		.suite = {
5148f975abb2SArd Biesheuvel 			.cipher = __VECS(essiv_aes_cbc_tv_template)
5149f975abb2SArd Biesheuvel 		}
5150f975abb2SArd Biesheuvel 	}, {
515160a273e9SNicolai Stange #if IS_ENABLED(CONFIG_CRYPTO_DH_RFC7919_GROUPS)
515260a273e9SNicolai Stange 		.alg = "ffdhe2048(dh)",
515360a273e9SNicolai Stange 		.test = alg_test_kpp,
515460a273e9SNicolai Stange 		.fips_allowed = 1,
515560a273e9SNicolai Stange 		.suite = {
515660a273e9SNicolai Stange 			.kpp = __VECS(ffdhe2048_dh_tv_template)
515760a273e9SNicolai Stange 		}
515860a273e9SNicolai Stange 	}, {
515960a273e9SNicolai Stange 		.alg = "ffdhe3072(dh)",
516060a273e9SNicolai Stange 		.test = alg_test_kpp,
516160a273e9SNicolai Stange 		.fips_allowed = 1,
516260a273e9SNicolai Stange 		.suite = {
516360a273e9SNicolai Stange 			.kpp = __VECS(ffdhe3072_dh_tv_template)
516460a273e9SNicolai Stange 		}
516560a273e9SNicolai Stange 	}, {
516660a273e9SNicolai Stange 		.alg = "ffdhe4096(dh)",
516760a273e9SNicolai Stange 		.test = alg_test_kpp,
516860a273e9SNicolai Stange 		.fips_allowed = 1,
516960a273e9SNicolai Stange 		.suite = {
517060a273e9SNicolai Stange 			.kpp = __VECS(ffdhe4096_dh_tv_template)
517160a273e9SNicolai Stange 		}
517260a273e9SNicolai Stange 	}, {
517360a273e9SNicolai Stange 		.alg = "ffdhe6144(dh)",
517460a273e9SNicolai Stange 		.test = alg_test_kpp,
517560a273e9SNicolai Stange 		.fips_allowed = 1,
517660a273e9SNicolai Stange 		.suite = {
517760a273e9SNicolai Stange 			.kpp = __VECS(ffdhe6144_dh_tv_template)
517860a273e9SNicolai Stange 		}
517960a273e9SNicolai Stange 	}, {
518060a273e9SNicolai Stange 		.alg = "ffdhe8192(dh)",
518160a273e9SNicolai Stange 		.test = alg_test_kpp,
518260a273e9SNicolai Stange 		.fips_allowed = 1,
518360a273e9SNicolai Stange 		.suite = {
518460a273e9SNicolai Stange 			.kpp = __VECS(ffdhe8192_dh_tv_template)
518560a273e9SNicolai Stange 		}
518660a273e9SNicolai Stange 	}, {
518760a273e9SNicolai Stange #endif /* CONFIG_CRYPTO_DH_RFC7919_GROUPS */
5188da7f033dSHerbert Xu 		.alg = "gcm(aes)",
518940153b10SEric Biggers 		.generic_driver = "gcm_base(ctr(aes-generic),ghash-generic)",
5190da7f033dSHerbert Xu 		.test = alg_test_aead,
5191a1915d51SJarod Wilson 		.fips_allowed = 1,
5192da7f033dSHerbert Xu 		.suite = {
5193a0d608eeSEric Biggers 			.aead = __VECS(aes_gcm_tv_template)
5194da7f033dSHerbert Xu 		}
5195da7f033dSHerbert Xu 	}, {
519601ce31deSTaehee Yoo 		.alg = "gcm(aria)",
519701ce31deSTaehee Yoo 		.generic_driver = "gcm_base(ctr(aria-generic),ghash-generic)",
519801ce31deSTaehee Yoo 		.test = alg_test_aead,
519901ce31deSTaehee Yoo 		.suite = {
520001ce31deSTaehee Yoo 			.aead = __VECS(aria_gcm_tv_template)
520101ce31deSTaehee Yoo 		}
520201ce31deSTaehee Yoo 	}, {
520368039d60STianjia Zhang 		.alg = "gcm(sm4)",
520468039d60STianjia Zhang 		.generic_driver = "gcm_base(ctr(sm4-generic),ghash-generic)",
520568039d60STianjia Zhang 		.test = alg_test_aead,
520668039d60STianjia Zhang 		.suite = {
520768039d60STianjia Zhang 			.aead = __VECS(sm4_gcm_tv_template)
520868039d60STianjia Zhang 		}
520968039d60STianjia Zhang 	}, {
5210507069c9SYouquan, Song 		.alg = "ghash",
5211507069c9SYouquan, Song 		.test = alg_test_hash,
5212507069c9SYouquan, Song 		.suite = {
521321c8e720SArd Biesheuvel 			.hash = __VECS(ghash_tv_template)
5214507069c9SYouquan, Song 		}
5215507069c9SYouquan, Song 	}, {
52167ff554ceSNathan Huckleberry 		.alg = "hctr2(aes)",
52177ff554ceSNathan Huckleberry 		.generic_driver =
52187ff554ceSNathan Huckleberry 		    "hctr2_base(xctr(aes-generic),polyval-generic)",
52197ff554ceSNathan Huckleberry 		.test = alg_test_skcipher,
52207ff554ceSNathan Huckleberry 		.suite = {
52217ff554ceSNathan Huckleberry 			.cipher = __VECS(aes_hctr2_tv_template)
52227ff554ceSNathan Huckleberry 		}
52237ff554ceSNathan Huckleberry 	}, {
5224da7f033dSHerbert Xu 		.alg = "hmac(md5)",
5225da7f033dSHerbert Xu 		.test = alg_test_hash,
5226da7f033dSHerbert Xu 		.suite = {
522721c8e720SArd Biesheuvel 			.hash = __VECS(hmac_md5_tv_template)
5228da7f033dSHerbert Xu 		}
5229da7f033dSHerbert Xu 	}, {
5230da7f033dSHerbert Xu 		.alg = "hmac(rmd160)",
5231da7f033dSHerbert Xu 		.test = alg_test_hash,
5232da7f033dSHerbert Xu 		.suite = {
523321c8e720SArd Biesheuvel 			.hash = __VECS(hmac_rmd160_tv_template)
5234da7f033dSHerbert Xu 		}
5235da7f033dSHerbert Xu 	}, {
5236da7f033dSHerbert Xu 		.alg = "hmac(sha1)",
5237da7f033dSHerbert Xu 		.test = alg_test_hash,
5238a1915d51SJarod Wilson 		.fips_allowed = 1,
5239da7f033dSHerbert Xu 		.suite = {
524021c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha1_tv_template)
5241da7f033dSHerbert Xu 		}
5242da7f033dSHerbert Xu 	}, {
5243da7f033dSHerbert Xu 		.alg = "hmac(sha224)",
5244da7f033dSHerbert Xu 		.test = alg_test_hash,
5245a1915d51SJarod Wilson 		.fips_allowed = 1,
5246da7f033dSHerbert Xu 		.suite = {
524721c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha224_tv_template)
5248da7f033dSHerbert Xu 		}
5249da7f033dSHerbert Xu 	}, {
5250da7f033dSHerbert Xu 		.alg = "hmac(sha256)",
5251da7f033dSHerbert Xu 		.test = alg_test_hash,
5252a1915d51SJarod Wilson 		.fips_allowed = 1,
5253da7f033dSHerbert Xu 		.suite = {
525421c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha256_tv_template)
5255da7f033dSHerbert Xu 		}
5256da7f033dSHerbert Xu 	}, {
525798eca72fSraveendra padasalagi 		.alg = "hmac(sha3-224)",
525898eca72fSraveendra padasalagi 		.test = alg_test_hash,
525998eca72fSraveendra padasalagi 		.fips_allowed = 1,
526098eca72fSraveendra padasalagi 		.suite = {
526121c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_224_tv_template)
526298eca72fSraveendra padasalagi 		}
526398eca72fSraveendra padasalagi 	}, {
526498eca72fSraveendra padasalagi 		.alg = "hmac(sha3-256)",
526598eca72fSraveendra padasalagi 		.test = alg_test_hash,
526698eca72fSraveendra padasalagi 		.fips_allowed = 1,
526798eca72fSraveendra padasalagi 		.suite = {
526821c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_256_tv_template)
526998eca72fSraveendra padasalagi 		}
527098eca72fSraveendra padasalagi 	}, {
527198eca72fSraveendra padasalagi 		.alg = "hmac(sha3-384)",
527298eca72fSraveendra padasalagi 		.test = alg_test_hash,
527398eca72fSraveendra padasalagi 		.fips_allowed = 1,
527498eca72fSraveendra padasalagi 		.suite = {
527521c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_384_tv_template)
527698eca72fSraveendra padasalagi 		}
527798eca72fSraveendra padasalagi 	}, {
527898eca72fSraveendra padasalagi 		.alg = "hmac(sha3-512)",
527998eca72fSraveendra padasalagi 		.test = alg_test_hash,
528098eca72fSraveendra padasalagi 		.fips_allowed = 1,
528198eca72fSraveendra padasalagi 		.suite = {
528221c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_512_tv_template)
528398eca72fSraveendra padasalagi 		}
528498eca72fSraveendra padasalagi 	}, {
5285da7f033dSHerbert Xu 		.alg = "hmac(sha384)",
5286da7f033dSHerbert Xu 		.test = alg_test_hash,
5287a1915d51SJarod Wilson 		.fips_allowed = 1,
5288da7f033dSHerbert Xu 		.suite = {
528921c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha384_tv_template)
5290da7f033dSHerbert Xu 		}
5291da7f033dSHerbert Xu 	}, {
5292da7f033dSHerbert Xu 		.alg = "hmac(sha512)",
5293da7f033dSHerbert Xu 		.test = alg_test_hash,
5294a1915d51SJarod Wilson 		.fips_allowed = 1,
5295da7f033dSHerbert Xu 		.suite = {
529621c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha512_tv_template)
5297da7f033dSHerbert Xu 		}
5298da7f033dSHerbert Xu 	}, {
52998194fd1dSPascal van Leeuwen 		.alg = "hmac(sm3)",
53008194fd1dSPascal van Leeuwen 		.test = alg_test_hash,
53018194fd1dSPascal van Leeuwen 		.suite = {
53028194fd1dSPascal van Leeuwen 			.hash = __VECS(hmac_sm3_tv_template)
53038194fd1dSPascal van Leeuwen 		}
53048194fd1dSPascal van Leeuwen 	}, {
530525a0b9d4SVitaly Chikunov 		.alg = "hmac(streebog256)",
530625a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
530725a0b9d4SVitaly Chikunov 		.suite = {
530825a0b9d4SVitaly Chikunov 			.hash = __VECS(hmac_streebog256_tv_template)
530925a0b9d4SVitaly Chikunov 		}
531025a0b9d4SVitaly Chikunov 	}, {
531125a0b9d4SVitaly Chikunov 		.alg = "hmac(streebog512)",
531225a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
531325a0b9d4SVitaly Chikunov 		.suite = {
531425a0b9d4SVitaly Chikunov 			.hash = __VECS(hmac_streebog512_tv_template)
531525a0b9d4SVitaly Chikunov 		}
531625a0b9d4SVitaly Chikunov 	}, {
5317bb5530e4SStephan Mueller 		.alg = "jitterentropy_rng",
5318bb5530e4SStephan Mueller 		.fips_allowed = 1,
5319bb5530e4SStephan Mueller 		.test = alg_test_null,
5320bb5530e4SStephan Mueller 	}, {
532135351988SStephan Mueller 		.alg = "kw(aes)",
532235351988SStephan Mueller 		.test = alg_test_skcipher,
532335351988SStephan Mueller 		.fips_allowed = 1,
532435351988SStephan Mueller 		.suite = {
532592a4c9feSEric Biggers 			.cipher = __VECS(aes_kw_tv_template)
532635351988SStephan Mueller 		}
532735351988SStephan Mueller 	}, {
5328da7f033dSHerbert Xu 		.alg = "lrw(aes)",
5329d435e10eSEric Biggers 		.generic_driver = "lrw(ecb(aes-generic))",
53301aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5331da7f033dSHerbert Xu 		.suite = {
533292a4c9feSEric Biggers 			.cipher = __VECS(aes_lrw_tv_template)
5333da7f033dSHerbert Xu 		}
5334da7f033dSHerbert Xu 	}, {
53350840605eSJussi Kivilinna 		.alg = "lrw(camellia)",
5336d435e10eSEric Biggers 		.generic_driver = "lrw(ecb(camellia-generic))",
53370840605eSJussi Kivilinna 		.test = alg_test_skcipher,
53380840605eSJussi Kivilinna 		.suite = {
533992a4c9feSEric Biggers 			.cipher = __VECS(camellia_lrw_tv_template)
53400840605eSJussi Kivilinna 		}
53410840605eSJussi Kivilinna 	}, {
53429b8b0405SJohannes Goetzfried 		.alg = "lrw(cast6)",
5343d435e10eSEric Biggers 		.generic_driver = "lrw(ecb(cast6-generic))",
53449b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
53459b8b0405SJohannes Goetzfried 		.suite = {
534692a4c9feSEric Biggers 			.cipher = __VECS(cast6_lrw_tv_template)
53479b8b0405SJohannes Goetzfried 		}
53489b8b0405SJohannes Goetzfried 	}, {
5349d7bfc0faSJussi Kivilinna 		.alg = "lrw(serpent)",
5350d435e10eSEric Biggers 		.generic_driver = "lrw(ecb(serpent-generic))",
5351d7bfc0faSJussi Kivilinna 		.test = alg_test_skcipher,
5352d7bfc0faSJussi Kivilinna 		.suite = {
535392a4c9feSEric Biggers 			.cipher = __VECS(serpent_lrw_tv_template)
5354d7bfc0faSJussi Kivilinna 		}
5355d7bfc0faSJussi Kivilinna 	}, {
53560b2a1551SJussi Kivilinna 		.alg = "lrw(twofish)",
5357d435e10eSEric Biggers 		.generic_driver = "lrw(ecb(twofish-generic))",
53580b2a1551SJussi Kivilinna 		.test = alg_test_skcipher,
53590b2a1551SJussi Kivilinna 		.suite = {
536092a4c9feSEric Biggers 			.cipher = __VECS(tf_lrw_tv_template)
53610b2a1551SJussi Kivilinna 		}
53620b2a1551SJussi Kivilinna 	}, {
53631443cc9bSKOVACS Krisztian 		.alg = "lz4",
53641443cc9bSKOVACS Krisztian 		.test = alg_test_comp,
53651443cc9bSKOVACS Krisztian 		.fips_allowed = 1,
53661443cc9bSKOVACS Krisztian 		.suite = {
53671443cc9bSKOVACS Krisztian 			.comp = {
536821c8e720SArd Biesheuvel 				.comp = __VECS(lz4_comp_tv_template),
536921c8e720SArd Biesheuvel 				.decomp = __VECS(lz4_decomp_tv_template)
53701443cc9bSKOVACS Krisztian 			}
53711443cc9bSKOVACS Krisztian 		}
53721443cc9bSKOVACS Krisztian 	}, {
53731443cc9bSKOVACS Krisztian 		.alg = "lz4hc",
53741443cc9bSKOVACS Krisztian 		.test = alg_test_comp,
53751443cc9bSKOVACS Krisztian 		.fips_allowed = 1,
53761443cc9bSKOVACS Krisztian 		.suite = {
53771443cc9bSKOVACS Krisztian 			.comp = {
537821c8e720SArd Biesheuvel 				.comp = __VECS(lz4hc_comp_tv_template),
537921c8e720SArd Biesheuvel 				.decomp = __VECS(lz4hc_decomp_tv_template)
53801443cc9bSKOVACS Krisztian 			}
53811443cc9bSKOVACS Krisztian 		}
53821443cc9bSKOVACS Krisztian 	}, {
5383da7f033dSHerbert Xu 		.alg = "lzo",
5384da7f033dSHerbert Xu 		.test = alg_test_comp,
53850818904dSMilan Broz 		.fips_allowed = 1,
5386da7f033dSHerbert Xu 		.suite = {
5387da7f033dSHerbert Xu 			.comp = {
538821c8e720SArd Biesheuvel 				.comp = __VECS(lzo_comp_tv_template),
538921c8e720SArd Biesheuvel 				.decomp = __VECS(lzo_decomp_tv_template)
5390da7f033dSHerbert Xu 			}
5391da7f033dSHerbert Xu 		}
5392da7f033dSHerbert Xu 	}, {
5393f248caf9SHannah Pan 		.alg = "lzo-rle",
5394f248caf9SHannah Pan 		.test = alg_test_comp,
5395f248caf9SHannah Pan 		.fips_allowed = 1,
5396f248caf9SHannah Pan 		.suite = {
5397f248caf9SHannah Pan 			.comp = {
5398f248caf9SHannah Pan 				.comp = __VECS(lzorle_comp_tv_template),
5399f248caf9SHannah Pan 				.decomp = __VECS(lzorle_decomp_tv_template)
5400f248caf9SHannah Pan 			}
5401f248caf9SHannah Pan 		}
5402f248caf9SHannah Pan 	}, {
5403da7f033dSHerbert Xu 		.alg = "md4",
5404da7f033dSHerbert Xu 		.test = alg_test_hash,
5405da7f033dSHerbert Xu 		.suite = {
540621c8e720SArd Biesheuvel 			.hash = __VECS(md4_tv_template)
5407da7f033dSHerbert Xu 		}
5408da7f033dSHerbert Xu 	}, {
5409da7f033dSHerbert Xu 		.alg = "md5",
5410da7f033dSHerbert Xu 		.test = alg_test_hash,
5411da7f033dSHerbert Xu 		.suite = {
541221c8e720SArd Biesheuvel 			.hash = __VECS(md5_tv_template)
5413da7f033dSHerbert Xu 		}
5414da7f033dSHerbert Xu 	}, {
5415da7f033dSHerbert Xu 		.alg = "michael_mic",
5416da7f033dSHerbert Xu 		.test = alg_test_hash,
5417da7f033dSHerbert Xu 		.suite = {
541821c8e720SArd Biesheuvel 			.hash = __VECS(michael_mic_tv_template)
5419da7f033dSHerbert Xu 		}
5420da7f033dSHerbert Xu 	}, {
542126609a21SEric Biggers 		.alg = "nhpoly1305",
542226609a21SEric Biggers 		.test = alg_test_hash,
542326609a21SEric Biggers 		.suite = {
542426609a21SEric Biggers 			.hash = __VECS(nhpoly1305_tv_template)
542526609a21SEric Biggers 		}
542626609a21SEric Biggers 	}, {
5427ba0e14acSPuneet Saxena 		.alg = "ofb(aes)",
5428ba0e14acSPuneet Saxena 		.test = alg_test_skcipher,
5429ba0e14acSPuneet Saxena 		.fips_allowed = 1,
5430ba0e14acSPuneet Saxena 		.suite = {
543192a4c9feSEric Biggers 			.cipher = __VECS(aes_ofb_tv_template)
5432ba0e14acSPuneet Saxena 		}
5433ba0e14acSPuneet Saxena 	}, {
5434a794d8d8SGilad Ben-Yossef 		/* Same as ofb(aes) except the key is stored in
5435a794d8d8SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
5436a794d8d8SGilad Ben-Yossef 		 */
5437a794d8d8SGilad Ben-Yossef 		.alg = "ofb(paes)",
5438a794d8d8SGilad Ben-Yossef 		.test = alg_test_null,
5439a794d8d8SGilad Ben-Yossef 		.fips_allowed = 1,
5440a794d8d8SGilad Ben-Yossef 	}, {
5441a06b15b2SPascal van Leeuwen 		.alg = "ofb(sm4)",
5442a06b15b2SPascal van Leeuwen 		.test = alg_test_skcipher,
5443a06b15b2SPascal van Leeuwen 		.suite = {
5444a06b15b2SPascal van Leeuwen 			.cipher = __VECS(sm4_ofb_tv_template)
5445a06b15b2SPascal van Leeuwen 		}
5446a06b15b2SPascal van Leeuwen 	}, {
5447da7f033dSHerbert Xu 		.alg = "pcbc(fcrypt)",
54481aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5449da7f033dSHerbert Xu 		.suite = {
545092a4c9feSEric Biggers 			.cipher = __VECS(fcrypt_pcbc_tv_template)
5451da7f033dSHerbert Xu 		}
5452da7f033dSHerbert Xu 	}, {
54531207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha224)",
54541207107cSStephan Mueller 		.test = alg_test_null,
54551207107cSStephan Mueller 		.fips_allowed = 1,
54561207107cSStephan Mueller 	}, {
54571207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha256)",
54581207107cSStephan Mueller 		.test = alg_test_akcipher,
54591207107cSStephan Mueller 		.fips_allowed = 1,
54601207107cSStephan Mueller 		.suite = {
54611207107cSStephan Mueller 			.akcipher = __VECS(pkcs1pad_rsa_tv_template)
54621207107cSStephan Mueller 		}
54631207107cSStephan Mueller 	}, {
54641207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha384)",
54651207107cSStephan Mueller 		.test = alg_test_null,
54661207107cSStephan Mueller 		.fips_allowed = 1,
54671207107cSStephan Mueller 	}, {
54681207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha512)",
54691207107cSStephan Mueller 		.test = alg_test_null,
54701207107cSStephan Mueller 		.fips_allowed = 1,
54711207107cSStephan Mueller 	}, {
5472eee9dc61SMartin Willi 		.alg = "poly1305",
5473eee9dc61SMartin Willi 		.test = alg_test_hash,
5474eee9dc61SMartin Willi 		.suite = {
547521c8e720SArd Biesheuvel 			.hash = __VECS(poly1305_tv_template)
5476eee9dc61SMartin Willi 		}
5477eee9dc61SMartin Willi 	}, {
5478f3c923a0SNathan Huckleberry 		.alg = "polyval",
5479f3c923a0SNathan Huckleberry 		.test = alg_test_hash,
5480f3c923a0SNathan Huckleberry 		.suite = {
5481f3c923a0SNathan Huckleberry 			.hash = __VECS(polyval_tv_template)
5482f3c923a0SNathan Huckleberry 		}
5483f3c923a0SNathan Huckleberry 	}, {
5484da7f033dSHerbert Xu 		.alg = "rfc3686(ctr(aes))",
54851aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
5486a1915d51SJarod Wilson 		.fips_allowed = 1,
5487da7f033dSHerbert Xu 		.suite = {
548892a4c9feSEric Biggers 			.cipher = __VECS(aes_ctr_rfc3686_tv_template)
5489da7f033dSHerbert Xu 		}
5490da7f033dSHerbert Xu 	}, {
5491e4886214SPascal van Leeuwen 		.alg = "rfc3686(ctr(sm4))",
5492e4886214SPascal van Leeuwen 		.test = alg_test_skcipher,
5493e4886214SPascal van Leeuwen 		.suite = {
5494e4886214SPascal van Leeuwen 			.cipher = __VECS(sm4_ctr_rfc3686_tv_template)
5495e4886214SPascal van Leeuwen 		}
5496e4886214SPascal van Leeuwen 	}, {
54973f31a740SHerbert Xu 		.alg = "rfc4106(gcm(aes))",
549840153b10SEric Biggers 		.generic_driver = "rfc4106(gcm_base(ctr(aes-generic),ghash-generic))",
549969435b94SAdrian Hoban 		.test = alg_test_aead,
5500db71f29aSJarod Wilson 		.fips_allowed = 1,
550169435b94SAdrian Hoban 		.suite = {
550249763fc6SEric Biggers 			.aead = {
550349763fc6SEric Biggers 				____VECS(aes_gcm_rfc4106_tv_template),
550449763fc6SEric Biggers 				.einval_allowed = 1,
55056f3a06d9SEric Biggers 				.aad_iv = 1,
550649763fc6SEric Biggers 			}
550769435b94SAdrian Hoban 		}
550869435b94SAdrian Hoban 	}, {
5509544c436aSHerbert Xu 		.alg = "rfc4309(ccm(aes))",
551040153b10SEric Biggers 		.generic_driver = "rfc4309(ccm_base(ctr(aes-generic),cbcmac(aes-generic)))",
55115d667322SJarod Wilson 		.test = alg_test_aead,
5512a1915d51SJarod Wilson 		.fips_allowed = 1,
55135d667322SJarod Wilson 		.suite = {
551449763fc6SEric Biggers 			.aead = {
551549763fc6SEric Biggers 				____VECS(aes_ccm_rfc4309_tv_template),
551649763fc6SEric Biggers 				.einval_allowed = 1,
55176f3a06d9SEric Biggers 				.aad_iv = 1,
551849763fc6SEric Biggers 			}
55195d667322SJarod Wilson 		}
55205d667322SJarod Wilson 	}, {
5521bb68745eSHerbert Xu 		.alg = "rfc4543(gcm(aes))",
552240153b10SEric Biggers 		.generic_driver = "rfc4543(gcm_base(ctr(aes-generic),ghash-generic))",
5523e9b7441aSJussi Kivilinna 		.test = alg_test_aead,
5524e9b7441aSJussi Kivilinna 		.suite = {
552549763fc6SEric Biggers 			.aead = {
552649763fc6SEric Biggers 				____VECS(aes_gcm_rfc4543_tv_template),
552749763fc6SEric Biggers 				.einval_allowed = 1,
55286f3a06d9SEric Biggers 				.aad_iv = 1,
552949763fc6SEric Biggers 			}
5530e9b7441aSJussi Kivilinna 		}
5531e9b7441aSJussi Kivilinna 	}, {
5532af2b76b5SMartin Willi 		.alg = "rfc7539(chacha20,poly1305)",
5533af2b76b5SMartin Willi 		.test = alg_test_aead,
5534af2b76b5SMartin Willi 		.suite = {
5535a0d608eeSEric Biggers 			.aead = __VECS(rfc7539_tv_template)
5536af2b76b5SMartin Willi 		}
5537af2b76b5SMartin Willi 	}, {
55385900758dSMartin Willi 		.alg = "rfc7539esp(chacha20,poly1305)",
55395900758dSMartin Willi 		.test = alg_test_aead,
55405900758dSMartin Willi 		.suite = {
554149763fc6SEric Biggers 			.aead = {
554249763fc6SEric Biggers 				____VECS(rfc7539esp_tv_template),
554349763fc6SEric Biggers 				.einval_allowed = 1,
55446f3a06d9SEric Biggers 				.aad_iv = 1,
554549763fc6SEric Biggers 			}
55465900758dSMartin Willi 		}
55475900758dSMartin Willi 	}, {
5548da7f033dSHerbert Xu 		.alg = "rmd160",
5549da7f033dSHerbert Xu 		.test = alg_test_hash,
5550da7f033dSHerbert Xu 		.suite = {
555121c8e720SArd Biesheuvel 			.hash = __VECS(rmd160_tv_template)
5552da7f033dSHerbert Xu 		}
5553da7f033dSHerbert Xu 	}, {
5554946cc463STadeusz Struk 		.alg = "rsa",
5555946cc463STadeusz Struk 		.test = alg_test_akcipher,
5556946cc463STadeusz Struk 		.fips_allowed = 1,
5557946cc463STadeusz Struk 		.suite = {
555821c8e720SArd Biesheuvel 			.akcipher = __VECS(rsa_tv_template)
5559946cc463STadeusz Struk 		}
5560946cc463STadeusz Struk 	}, {
5561da7f033dSHerbert Xu 		.alg = "sha1",
5562da7f033dSHerbert Xu 		.test = alg_test_hash,
5563a1915d51SJarod Wilson 		.fips_allowed = 1,
5564da7f033dSHerbert Xu 		.suite = {
556521c8e720SArd Biesheuvel 			.hash = __VECS(sha1_tv_template)
5566da7f033dSHerbert Xu 		}
5567da7f033dSHerbert Xu 	}, {
5568da7f033dSHerbert Xu 		.alg = "sha224",
5569da7f033dSHerbert Xu 		.test = alg_test_hash,
5570a1915d51SJarod Wilson 		.fips_allowed = 1,
5571da7f033dSHerbert Xu 		.suite = {
557221c8e720SArd Biesheuvel 			.hash = __VECS(sha224_tv_template)
5573da7f033dSHerbert Xu 		}
5574da7f033dSHerbert Xu 	}, {
5575da7f033dSHerbert Xu 		.alg = "sha256",
5576da7f033dSHerbert Xu 		.test = alg_test_hash,
5577a1915d51SJarod Wilson 		.fips_allowed = 1,
5578da7f033dSHerbert Xu 		.suite = {
557921c8e720SArd Biesheuvel 			.hash = __VECS(sha256_tv_template)
5580da7f033dSHerbert Xu 		}
5581da7f033dSHerbert Xu 	}, {
558279cc6ab8Sraveendra padasalagi 		.alg = "sha3-224",
558379cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
558479cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
558579cc6ab8Sraveendra padasalagi 		.suite = {
558621c8e720SArd Biesheuvel 			.hash = __VECS(sha3_224_tv_template)
558779cc6ab8Sraveendra padasalagi 		}
558879cc6ab8Sraveendra padasalagi 	}, {
558979cc6ab8Sraveendra padasalagi 		.alg = "sha3-256",
559079cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
559179cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
559279cc6ab8Sraveendra padasalagi 		.suite = {
559321c8e720SArd Biesheuvel 			.hash = __VECS(sha3_256_tv_template)
559479cc6ab8Sraveendra padasalagi 		}
559579cc6ab8Sraveendra padasalagi 	}, {
559679cc6ab8Sraveendra padasalagi 		.alg = "sha3-384",
559779cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
559879cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
559979cc6ab8Sraveendra padasalagi 		.suite = {
560021c8e720SArd Biesheuvel 			.hash = __VECS(sha3_384_tv_template)
560179cc6ab8Sraveendra padasalagi 		}
560279cc6ab8Sraveendra padasalagi 	}, {
560379cc6ab8Sraveendra padasalagi 		.alg = "sha3-512",
560479cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
560579cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
560679cc6ab8Sraveendra padasalagi 		.suite = {
560721c8e720SArd Biesheuvel 			.hash = __VECS(sha3_512_tv_template)
560879cc6ab8Sraveendra padasalagi 		}
560979cc6ab8Sraveendra padasalagi 	}, {
5610da7f033dSHerbert Xu 		.alg = "sha384",
5611da7f033dSHerbert Xu 		.test = alg_test_hash,
5612a1915d51SJarod Wilson 		.fips_allowed = 1,
5613da7f033dSHerbert Xu 		.suite = {
561421c8e720SArd Biesheuvel 			.hash = __VECS(sha384_tv_template)
5615da7f033dSHerbert Xu 		}
5616da7f033dSHerbert Xu 	}, {
5617da7f033dSHerbert Xu 		.alg = "sha512",
5618da7f033dSHerbert Xu 		.test = alg_test_hash,
5619a1915d51SJarod Wilson 		.fips_allowed = 1,
5620da7f033dSHerbert Xu 		.suite = {
562121c8e720SArd Biesheuvel 			.hash = __VECS(sha512_tv_template)
5622da7f033dSHerbert Xu 		}
5623da7f033dSHerbert Xu 	}, {
56248b805b97STianjia Zhang 		.alg = "sm2",
56258b805b97STianjia Zhang 		.test = alg_test_akcipher,
56268b805b97STianjia Zhang 		.suite = {
56278b805b97STianjia Zhang 			.akcipher = __VECS(sm2_tv_template)
56288b805b97STianjia Zhang 		}
56298b805b97STianjia Zhang 	}, {
5630b7e27530SGilad Ben-Yossef 		.alg = "sm3",
5631b7e27530SGilad Ben-Yossef 		.test = alg_test_hash,
5632b7e27530SGilad Ben-Yossef 		.suite = {
5633b7e27530SGilad Ben-Yossef 			.hash = __VECS(sm3_tv_template)
5634b7e27530SGilad Ben-Yossef 		}
5635b7e27530SGilad Ben-Yossef 	}, {
563625a0b9d4SVitaly Chikunov 		.alg = "streebog256",
563725a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
563825a0b9d4SVitaly Chikunov 		.suite = {
563925a0b9d4SVitaly Chikunov 			.hash = __VECS(streebog256_tv_template)
564025a0b9d4SVitaly Chikunov 		}
564125a0b9d4SVitaly Chikunov 	}, {
564225a0b9d4SVitaly Chikunov 		.alg = "streebog512",
564325a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
564425a0b9d4SVitaly Chikunov 		.suite = {
564525a0b9d4SVitaly Chikunov 			.hash = __VECS(streebog512_tv_template)
564625a0b9d4SVitaly Chikunov 		}
564725a0b9d4SVitaly Chikunov 	}, {
5648ed331adaSEric Biggers 		.alg = "vmac64(aes)",
5649ed331adaSEric Biggers 		.test = alg_test_hash,
5650ed331adaSEric Biggers 		.suite = {
5651ed331adaSEric Biggers 			.hash = __VECS(vmac64_aes_tv_template)
5652ed331adaSEric Biggers 		}
5653ed331adaSEric Biggers 	}, {
5654da7f033dSHerbert Xu 		.alg = "wp256",
5655da7f033dSHerbert Xu 		.test = alg_test_hash,
5656da7f033dSHerbert Xu 		.suite = {
565721c8e720SArd Biesheuvel 			.hash = __VECS(wp256_tv_template)
5658da7f033dSHerbert Xu 		}
5659da7f033dSHerbert Xu 	}, {
5660da7f033dSHerbert Xu 		.alg = "wp384",
5661da7f033dSHerbert Xu 		.test = alg_test_hash,
5662da7f033dSHerbert Xu 		.suite = {
566321c8e720SArd Biesheuvel 			.hash = __VECS(wp384_tv_template)
5664da7f033dSHerbert Xu 		}
5665da7f033dSHerbert Xu 	}, {
5666da7f033dSHerbert Xu 		.alg = "wp512",
5667da7f033dSHerbert Xu 		.test = alg_test_hash,
5668da7f033dSHerbert Xu 		.suite = {
566921c8e720SArd Biesheuvel 			.hash = __VECS(wp512_tv_template)
5670da7f033dSHerbert Xu 		}
5671da7f033dSHerbert Xu 	}, {
5672da7f033dSHerbert Xu 		.alg = "xcbc(aes)",
5673da7f033dSHerbert Xu 		.test = alg_test_hash,
5674da7f033dSHerbert Xu 		.suite = {
567521c8e720SArd Biesheuvel 			.hash = __VECS(aes_xcbc128_tv_template)
5676da7f033dSHerbert Xu 		}
5677da7f033dSHerbert Xu 	}, {
5678c24ee936STianjia Zhang 		.alg = "xcbc(sm4)",
5679c24ee936STianjia Zhang 		.test = alg_test_hash,
5680c24ee936STianjia Zhang 		.suite = {
5681c24ee936STianjia Zhang 			.hash = __VECS(sm4_xcbc128_tv_template)
5682c24ee936STianjia Zhang 		}
5683c24ee936STianjia Zhang 	}, {
5684aa762409SEric Biggers 		.alg = "xchacha12",
5685aa762409SEric Biggers 		.test = alg_test_skcipher,
5686aa762409SEric Biggers 		.suite = {
5687aa762409SEric Biggers 			.cipher = __VECS(xchacha12_tv_template)
5688aa762409SEric Biggers 		},
5689aa762409SEric Biggers 	}, {
5690de61d7aeSEric Biggers 		.alg = "xchacha20",
5691de61d7aeSEric Biggers 		.test = alg_test_skcipher,
5692de61d7aeSEric Biggers 		.suite = {
5693de61d7aeSEric Biggers 			.cipher = __VECS(xchacha20_tv_template)
5694de61d7aeSEric Biggers 		},
5695de61d7aeSEric Biggers 	}, {
569617fee07aSNathan Huckleberry 		.alg = "xctr(aes)",
569717fee07aSNathan Huckleberry 		.test = alg_test_skcipher,
569817fee07aSNathan Huckleberry 		.suite = {
569917fee07aSNathan Huckleberry 			.cipher = __VECS(aes_xctr_tv_template)
570017fee07aSNathan Huckleberry 		}
570117fee07aSNathan Huckleberry 	}, {
5702da7f033dSHerbert Xu 		.alg = "xts(aes)",
5703d435e10eSEric Biggers 		.generic_driver = "xts(ecb(aes-generic))",
57041aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
57052918aa8dSJarod Wilson 		.fips_allowed = 1,
5706da7f033dSHerbert Xu 		.suite = {
570792a4c9feSEric Biggers 			.cipher = __VECS(aes_xts_tv_template)
5708da7f033dSHerbert Xu 		}
57090c01aed5SGeert Uytterhoeven 	}, {
57100840605eSJussi Kivilinna 		.alg = "xts(camellia)",
5711d435e10eSEric Biggers 		.generic_driver = "xts(ecb(camellia-generic))",
57120840605eSJussi Kivilinna 		.test = alg_test_skcipher,
57130840605eSJussi Kivilinna 		.suite = {
571492a4c9feSEric Biggers 			.cipher = __VECS(camellia_xts_tv_template)
57150840605eSJussi Kivilinna 		}
57160840605eSJussi Kivilinna 	}, {
57179b8b0405SJohannes Goetzfried 		.alg = "xts(cast6)",
5718d435e10eSEric Biggers 		.generic_driver = "xts(ecb(cast6-generic))",
57199b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
57209b8b0405SJohannes Goetzfried 		.suite = {
572192a4c9feSEric Biggers 			.cipher = __VECS(cast6_xts_tv_template)
57229b8b0405SJohannes Goetzfried 		}
57239b8b0405SJohannes Goetzfried 	}, {
572415f47ce5SGilad Ben-Yossef 		/* Same as xts(aes) except the key is stored in
572515f47ce5SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
572615f47ce5SGilad Ben-Yossef 		 */
572715f47ce5SGilad Ben-Yossef 		.alg = "xts(paes)",
572815f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
572915f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
573015f47ce5SGilad Ben-Yossef 	}, {
573118be20b9SJussi Kivilinna 		.alg = "xts(serpent)",
5732d435e10eSEric Biggers 		.generic_driver = "xts(ecb(serpent-generic))",
573318be20b9SJussi Kivilinna 		.test = alg_test_skcipher,
573418be20b9SJussi Kivilinna 		.suite = {
573592a4c9feSEric Biggers 			.cipher = __VECS(serpent_xts_tv_template)
573618be20b9SJussi Kivilinna 		}
573718be20b9SJussi Kivilinna 	}, {
5738c24ee936STianjia Zhang 		.alg = "xts(sm4)",
5739c24ee936STianjia Zhang 		.generic_driver = "xts(ecb(sm4-generic))",
5740c24ee936STianjia Zhang 		.test = alg_test_skcipher,
5741c24ee936STianjia Zhang 		.suite = {
5742c24ee936STianjia Zhang 			.cipher = __VECS(sm4_xts_tv_template)
5743c24ee936STianjia Zhang 		}
5744c24ee936STianjia Zhang 	}, {
5745aed265b9SJussi Kivilinna 		.alg = "xts(twofish)",
5746d435e10eSEric Biggers 		.generic_driver = "xts(ecb(twofish-generic))",
5747aed265b9SJussi Kivilinna 		.test = alg_test_skcipher,
5748aed265b9SJussi Kivilinna 		.suite = {
574992a4c9feSEric Biggers 			.cipher = __VECS(tf_xts_tv_template)
5750aed265b9SJussi Kivilinna 		}
5751a368f43dSGiovanni Cabiddu 	}, {
5752c7ff8573SHarald Freudenberger #if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
5753c7ff8573SHarald Freudenberger 		.alg = "xts-paes-s390",
5754c7ff8573SHarald Freudenberger 		.fips_allowed = 1,
5755c7ff8573SHarald Freudenberger 		.test = alg_test_skcipher,
5756c7ff8573SHarald Freudenberger 		.suite = {
5757c7ff8573SHarald Freudenberger 			.cipher = __VECS(aes_xts_tv_template)
5758c7ff8573SHarald Freudenberger 		}
5759c7ff8573SHarald Freudenberger 	}, {
5760c7ff8573SHarald Freudenberger #endif
576115f47ce5SGilad Ben-Yossef 		.alg = "xts4096(paes)",
576215f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
576315f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
576415f47ce5SGilad Ben-Yossef 	}, {
576515f47ce5SGilad Ben-Yossef 		.alg = "xts512(paes)",
576615f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
576715f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
576815f47ce5SGilad Ben-Yossef 	}, {
576967882e76SNikolay Borisov 		.alg = "xxhash64",
577067882e76SNikolay Borisov 		.test = alg_test_hash,
577167882e76SNikolay Borisov 		.fips_allowed = 1,
577267882e76SNikolay Borisov 		.suite = {
577367882e76SNikolay Borisov 			.hash = __VECS(xxhash64_tv_template)
577467882e76SNikolay Borisov 		}
577567882e76SNikolay Borisov 	}, {
5776a368f43dSGiovanni Cabiddu 		.alg = "zlib-deflate",
5777a368f43dSGiovanni Cabiddu 		.test = alg_test_comp,
5778a368f43dSGiovanni Cabiddu 		.fips_allowed = 1,
5779a368f43dSGiovanni Cabiddu 		.suite = {
5780a368f43dSGiovanni Cabiddu 			.comp = {
5781a368f43dSGiovanni Cabiddu 				.comp = __VECS(zlib_deflate_comp_tv_template),
5782a368f43dSGiovanni Cabiddu 				.decomp = __VECS(zlib_deflate_decomp_tv_template)
5783a368f43dSGiovanni Cabiddu 			}
5784a368f43dSGiovanni Cabiddu 		}
5785d28fc3dbSNick Terrell 	}, {
5786d28fc3dbSNick Terrell 		.alg = "zstd",
5787d28fc3dbSNick Terrell 		.test = alg_test_comp,
5788d28fc3dbSNick Terrell 		.fips_allowed = 1,
5789d28fc3dbSNick Terrell 		.suite = {
5790d28fc3dbSNick Terrell 			.comp = {
5791d28fc3dbSNick Terrell 				.comp = __VECS(zstd_comp_tv_template),
5792d28fc3dbSNick Terrell 				.decomp = __VECS(zstd_decomp_tv_template)
5793d28fc3dbSNick Terrell 			}
5794d28fc3dbSNick Terrell 		}
5795da7f033dSHerbert Xu 	}
5796da7f033dSHerbert Xu };
5797da7f033dSHerbert Xu 
alg_check_test_descs_order(void)57983f47a03dSEric Biggers static void alg_check_test_descs_order(void)
57995714758bSJussi Kivilinna {
58005714758bSJussi Kivilinna 	int i;
58015714758bSJussi Kivilinna 
58025714758bSJussi Kivilinna 	for (i = 1; i < ARRAY_SIZE(alg_test_descs); i++) {
58035714758bSJussi Kivilinna 		int diff = strcmp(alg_test_descs[i - 1].alg,
58045714758bSJussi Kivilinna 				  alg_test_descs[i].alg);
58055714758bSJussi Kivilinna 
58065714758bSJussi Kivilinna 		if (WARN_ON(diff > 0)) {
58075714758bSJussi Kivilinna 			pr_warn("testmgr: alg_test_descs entries in wrong order: '%s' before '%s'\n",
58085714758bSJussi Kivilinna 				alg_test_descs[i - 1].alg,
58095714758bSJussi Kivilinna 				alg_test_descs[i].alg);
58105714758bSJussi Kivilinna 		}
58115714758bSJussi Kivilinna 
58125714758bSJussi Kivilinna 		if (WARN_ON(diff == 0)) {
58135714758bSJussi Kivilinna 			pr_warn("testmgr: duplicate alg_test_descs entry: '%s'\n",
58145714758bSJussi Kivilinna 				alg_test_descs[i].alg);
58155714758bSJussi Kivilinna 		}
58165714758bSJussi Kivilinna 	}
58175714758bSJussi Kivilinna }
58185714758bSJussi Kivilinna 
alg_check_testvec_configs(void)58193f47a03dSEric Biggers static void alg_check_testvec_configs(void)
58203f47a03dSEric Biggers {
58214e7babbaSEric Biggers 	int i;
58224e7babbaSEric Biggers 
58234e7babbaSEric Biggers 	for (i = 0; i < ARRAY_SIZE(default_cipher_testvec_configs); i++)
58244e7babbaSEric Biggers 		WARN_ON(!valid_testvec_config(
58254e7babbaSEric Biggers 				&default_cipher_testvec_configs[i]));
58264cc2dcf9SEric Biggers 
58274cc2dcf9SEric Biggers 	for (i = 0; i < ARRAY_SIZE(default_hash_testvec_configs); i++)
58284cc2dcf9SEric Biggers 		WARN_ON(!valid_testvec_config(
58294cc2dcf9SEric Biggers 				&default_hash_testvec_configs[i]));
58303f47a03dSEric Biggers }
58313f47a03dSEric Biggers 
testmgr_onetime_init(void)58323f47a03dSEric Biggers static void testmgr_onetime_init(void)
58333f47a03dSEric Biggers {
58343f47a03dSEric Biggers 	alg_check_test_descs_order();
58353f47a03dSEric Biggers 	alg_check_testvec_configs();
58365b2706a4SEric Biggers 
58375b2706a4SEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
58385b2706a4SEric Biggers 	pr_warn("alg: extra crypto tests enabled.  This is intended for developer use only.\n");
58395b2706a4SEric Biggers #endif
58403f47a03dSEric Biggers }
58413f47a03dSEric Biggers 
alg_find_test(const char * alg)58421aa4ecd9SHerbert Xu static int alg_find_test(const char *alg)
5843da7f033dSHerbert Xu {
5844da7f033dSHerbert Xu 	int start = 0;
5845da7f033dSHerbert Xu 	int end = ARRAY_SIZE(alg_test_descs);
5846da7f033dSHerbert Xu 
5847da7f033dSHerbert Xu 	while (start < end) {
5848da7f033dSHerbert Xu 		int i = (start + end) / 2;
5849da7f033dSHerbert Xu 		int diff = strcmp(alg_test_descs[i].alg, alg);
5850da7f033dSHerbert Xu 
5851da7f033dSHerbert Xu 		if (diff > 0) {
5852da7f033dSHerbert Xu 			end = i;
5853da7f033dSHerbert Xu 			continue;
5854da7f033dSHerbert Xu 		}
5855da7f033dSHerbert Xu 
5856da7f033dSHerbert Xu 		if (diff < 0) {
5857da7f033dSHerbert Xu 			start = i + 1;
5858da7f033dSHerbert Xu 			continue;
5859da7f033dSHerbert Xu 		}
5860da7f033dSHerbert Xu 
58611aa4ecd9SHerbert Xu 		return i;
5862da7f033dSHerbert Xu 	}
5863da7f033dSHerbert Xu 
58641aa4ecd9SHerbert Xu 	return -1;
58651aa4ecd9SHerbert Xu }
58661aa4ecd9SHerbert Xu 
alg_fips_disabled(const char * driver,const char * alg)5867d6097b8dSNicolai Stange static int alg_fips_disabled(const char *driver, const char *alg)
5868d6097b8dSNicolai Stange {
5869d6097b8dSNicolai Stange 	pr_info("alg: %s (%s) is disabled due to FIPS\n", alg, driver);
5870d6097b8dSNicolai Stange 
5871d6097b8dSNicolai Stange 	return -ECANCELED;
5872d6097b8dSNicolai Stange }
5873d6097b8dSNicolai Stange 
alg_test(const char * driver,const char * alg,u32 type,u32 mask)58741aa4ecd9SHerbert Xu int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
58751aa4ecd9SHerbert Xu {
58761aa4ecd9SHerbert Xu 	int i;
5877a68f6610SHerbert Xu 	int j;
5878d12d6b6dSNeil Horman 	int rc;
58791aa4ecd9SHerbert Xu 
58809e5c9fe4SRichard W.M. Jones 	if (!fips_enabled && notests) {
58819e5c9fe4SRichard W.M. Jones 		printk_once(KERN_INFO "alg: self-tests disabled\n");
58829e5c9fe4SRichard W.M. Jones 		return 0;
58839e5c9fe4SRichard W.M. Jones 	}
58849e5c9fe4SRichard W.M. Jones 
58853f47a03dSEric Biggers 	DO_ONCE(testmgr_onetime_init);
58865714758bSJussi Kivilinna 
58871aa4ecd9SHerbert Xu 	if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) {
58881aa4ecd9SHerbert Xu 		char nalg[CRYPTO_MAX_ALG_NAME];
58891aa4ecd9SHerbert Xu 
58901aa4ecd9SHerbert Xu 		if (snprintf(nalg, sizeof(nalg), "ecb(%s)", alg) >=
58911aa4ecd9SHerbert Xu 		    sizeof(nalg))
58921aa4ecd9SHerbert Xu 			return -ENAMETOOLONG;
58931aa4ecd9SHerbert Xu 
58941aa4ecd9SHerbert Xu 		i = alg_find_test(nalg);
58951aa4ecd9SHerbert Xu 		if (i < 0)
58961aa4ecd9SHerbert Xu 			goto notest;
58971aa4ecd9SHerbert Xu 
5898a3bef3a3SJarod Wilson 		if (fips_enabled && !alg_test_descs[i].fips_allowed)
5899a3bef3a3SJarod Wilson 			goto non_fips_alg;
5900a3bef3a3SJarod Wilson 
5901941fb328SJarod Wilson 		rc = alg_test_cipher(alg_test_descs + i, driver, type, mask);
5902941fb328SJarod Wilson 		goto test_done;
59031aa4ecd9SHerbert Xu 	}
59041aa4ecd9SHerbert Xu 
59051aa4ecd9SHerbert Xu 	i = alg_find_test(alg);
5906a68f6610SHerbert Xu 	j = alg_find_test(driver);
5907a68f6610SHerbert Xu 	if (i < 0 && j < 0)
59081aa4ecd9SHerbert Xu 		goto notest;
59091aa4ecd9SHerbert Xu 
5910d6097b8dSNicolai Stange 	if (fips_enabled) {
5911d6097b8dSNicolai Stange 		if (j >= 0 && !alg_test_descs[j].fips_allowed)
5912d6097b8dSNicolai Stange 			return -EINVAL;
5913d6097b8dSNicolai Stange 
5914d6097b8dSNicolai Stange 		if (i >= 0 && !alg_test_descs[i].fips_allowed)
5915a3bef3a3SJarod Wilson 			goto non_fips_alg;
5916d6097b8dSNicolai Stange 	}
5917a3bef3a3SJarod Wilson 
5918a68f6610SHerbert Xu 	rc = 0;
5919a68f6610SHerbert Xu 	if (i >= 0)
5920a68f6610SHerbert Xu 		rc |= alg_test_descs[i].test(alg_test_descs + i, driver,
59211aa4ecd9SHerbert Xu 					     type, mask);
5922032c8cacSCristian Stoica 	if (j >= 0 && j != i)
5923a68f6610SHerbert Xu 		rc |= alg_test_descs[j].test(alg_test_descs + j, driver,
5924a68f6610SHerbert Xu 					     type, mask);
5925a68f6610SHerbert Xu 
5926941fb328SJarod Wilson test_done:
592709a5ef96SEric Biggers 	if (rc) {
592809a5ef96SEric Biggers 		if (fips_enabled || panic_on_fail) {
59299552389cSGilad Ben-Yossef 			fips_fail_notify();
5930eda69b0cSEric Biggers 			panic("alg: self-tests for %s (%s) failed in %s mode!\n",
593109a5ef96SEric Biggers 			      driver, alg,
593209a5ef96SEric Biggers 			      fips_enabled ? "fips" : "panic_on_fail");
59339552389cSGilad Ben-Yossef 		}
5934a76bd86aSRobert Elliott 		pr_warn("alg: self-tests for %s using %s failed (rc=%d)",
5935a76bd86aSRobert Elliott 			alg, driver, rc);
5936a76bd86aSRobert Elliott 		WARN(rc != -ENOENT,
5937a76bd86aSRobert Elliott 		     "alg: self-tests for %s using %s failed (rc=%d)",
5938a76bd86aSRobert Elliott 		     alg, driver, rc);
593909a5ef96SEric Biggers 	} else {
594009a5ef96SEric Biggers 		if (fips_enabled)
594109a5ef96SEric Biggers 			pr_info("alg: self-tests for %s (%s) passed\n",
594209a5ef96SEric Biggers 				driver, alg);
594309a5ef96SEric Biggers 	}
594429ecd4abSJarod Wilson 
5945d12d6b6dSNeil Horman 	return rc;
59461aa4ecd9SHerbert Xu 
59471aa4ecd9SHerbert Xu notest:
5948da7f033dSHerbert Xu 	printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);
5949d6097b8dSNicolai Stange 
5950d6097b8dSNicolai Stange 	if (type & CRYPTO_ALG_FIPS_INTERNAL)
5951d6097b8dSNicolai Stange 		return alg_fips_disabled(driver, alg);
5952d6097b8dSNicolai Stange 
5953da7f033dSHerbert Xu 	return 0;
5954a3bef3a3SJarod Wilson non_fips_alg:
5955d6097b8dSNicolai Stange 	return alg_fips_disabled(driver, alg);
5956da7f033dSHerbert Xu }
59570b767f96SAlexander Shishkin 
5958326a6346SHerbert Xu #endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */
59590b767f96SAlexander Shishkin 
5960da7f033dSHerbert Xu EXPORT_SYMBOL_GPL(alg_test);
5961