xref: /openbmc/linux/crypto/testmgr.c (revision 25f9dddb)
1da7f033dSHerbert Xu /*
2da7f033dSHerbert Xu  * Algorithm testing framework and tests.
3da7f033dSHerbert Xu  *
4da7f033dSHerbert Xu  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
5da7f033dSHerbert Xu  * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
6da7f033dSHerbert Xu  * Copyright (c) 2007 Nokia Siemens Networks
7da7f033dSHerbert Xu  * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
83f47a03dSEric Biggers  * Copyright (c) 2019 Google LLC
9da7f033dSHerbert Xu  *
1069435b94SAdrian Hoban  * Updated RFC4106 AES-GCM testing.
1169435b94SAdrian Hoban  *    Authors: Aidan O'Mahony (aidan.o.mahony@intel.com)
1269435b94SAdrian Hoban  *             Adrian Hoban <adrian.hoban@intel.com>
1369435b94SAdrian Hoban  *             Gabriele Paoloni <gabriele.paoloni@intel.com>
1469435b94SAdrian Hoban  *             Tadeusz Struk (tadeusz.struk@intel.com)
1569435b94SAdrian Hoban  *    Copyright (c) 2010, Intel Corporation.
1669435b94SAdrian Hoban  *
17da7f033dSHerbert Xu  * This program is free software; you can redistribute it and/or modify it
18da7f033dSHerbert Xu  * under the terms of the GNU General Public License as published by the Free
19da7f033dSHerbert Xu  * Software Foundation; either version 2 of the License, or (at your option)
20da7f033dSHerbert Xu  * any later version.
21da7f033dSHerbert Xu  *
22da7f033dSHerbert Xu  */
23da7f033dSHerbert Xu 
241ce33115SHerbert Xu #include <crypto/aead.h>
25da7f033dSHerbert Xu #include <crypto/hash.h>
2612773d93SHerbert Xu #include <crypto/skcipher.h>
27da7f033dSHerbert Xu #include <linux/err.h>
281c41b882SHerbert Xu #include <linux/fips.h>
29da7f033dSHerbert Xu #include <linux/module.h>
303f47a03dSEric Biggers #include <linux/once.h>
3125f9dddbSEric Biggers #include <linux/random.h>
32da7f033dSHerbert Xu #include <linux/scatterlist.h>
33da7f033dSHerbert Xu #include <linux/slab.h>
34da7f033dSHerbert Xu #include <linux/string.h>
357647d6ceSJarod Wilson #include <crypto/rng.h>
3664d1cdfbSStephan Mueller #include <crypto/drbg.h>
37946cc463STadeusz Struk #include <crypto/akcipher.h>
38802c7f1cSSalvatore Benedetto #include <crypto/kpp.h>
39d7db7a88SGiovanni Cabiddu #include <crypto/acompress.h>
40da7f033dSHerbert Xu 
41da7f033dSHerbert Xu #include "internal.h"
420b767f96SAlexander Shishkin 
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 
475b2706a4SEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
485b2706a4SEric Biggers static bool noextratests;
495b2706a4SEric Biggers module_param(noextratests, bool, 0644);
505b2706a4SEric Biggers MODULE_PARM_DESC(noextratests, "disable expensive crypto self-tests");
515b2706a4SEric Biggers 
525b2706a4SEric Biggers static unsigned int fuzz_iterations = 100;
535b2706a4SEric Biggers module_param(fuzz_iterations, uint, 0644);
545b2706a4SEric Biggers MODULE_PARM_DESC(fuzz_iterations, "number of fuzz test iterations");
555b2706a4SEric Biggers #endif
565b2706a4SEric Biggers 
57326a6346SHerbert Xu #ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
580b767f96SAlexander Shishkin 
590b767f96SAlexander Shishkin /* a perfect nop */
600b767f96SAlexander Shishkin int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
610b767f96SAlexander Shishkin {
620b767f96SAlexander Shishkin 	return 0;
630b767f96SAlexander Shishkin }
640b767f96SAlexander Shishkin 
650b767f96SAlexander Shishkin #else
660b767f96SAlexander Shishkin 
67da7f033dSHerbert Xu #include "testmgr.h"
68da7f033dSHerbert Xu 
69da7f033dSHerbert Xu /*
70da7f033dSHerbert Xu  * Need slab memory for testing (size in number of pages).
71da7f033dSHerbert Xu  */
72da7f033dSHerbert Xu #define XBUFSIZE	8
73da7f033dSHerbert Xu 
74da7f033dSHerbert Xu /*
75da7f033dSHerbert Xu  * Indexes into the xbuf to simulate cross-page access.
76da7f033dSHerbert Xu  */
77da7f033dSHerbert Xu #define IDX1		32
78da7f033dSHerbert Xu #define IDX2		32400
7904b46fbdSArd Biesheuvel #define IDX3		1511
80da7f033dSHerbert Xu #define IDX4		8193
81da7f033dSHerbert Xu #define IDX5		22222
82da7f033dSHerbert Xu #define IDX6		17101
83da7f033dSHerbert Xu #define IDX7		27333
84da7f033dSHerbert Xu #define IDX8		3000
85da7f033dSHerbert Xu 
86da7f033dSHerbert Xu /*
87da7f033dSHerbert Xu * Used by test_cipher()
88da7f033dSHerbert Xu */
89da7f033dSHerbert Xu #define ENCRYPT 1
90da7f033dSHerbert Xu #define DECRYPT 0
91da7f033dSHerbert Xu 
92da7f033dSHerbert Xu struct aead_test_suite {
93b13b1e0cSEric Biggers 	const struct aead_testvec *vecs;
94da7f033dSHerbert Xu 	unsigned int count;
95da7f033dSHerbert Xu };
96da7f033dSHerbert Xu 
97da7f033dSHerbert Xu struct cipher_test_suite {
98b13b1e0cSEric Biggers 	const struct cipher_testvec *vecs;
99da7f033dSHerbert Xu 	unsigned int count;
100da7f033dSHerbert Xu };
101da7f033dSHerbert Xu 
102da7f033dSHerbert Xu struct comp_test_suite {
103da7f033dSHerbert Xu 	struct {
104b13b1e0cSEric Biggers 		const struct comp_testvec *vecs;
105da7f033dSHerbert Xu 		unsigned int count;
106da7f033dSHerbert Xu 	} comp, decomp;
107da7f033dSHerbert Xu };
108da7f033dSHerbert Xu 
109da7f033dSHerbert Xu struct hash_test_suite {
110b13b1e0cSEric Biggers 	const struct hash_testvec *vecs;
111da7f033dSHerbert Xu 	unsigned int count;
112da7f033dSHerbert Xu };
113da7f033dSHerbert Xu 
1147647d6ceSJarod Wilson struct cprng_test_suite {
115b13b1e0cSEric Biggers 	const struct cprng_testvec *vecs;
1167647d6ceSJarod Wilson 	unsigned int count;
1177647d6ceSJarod Wilson };
1187647d6ceSJarod Wilson 
11964d1cdfbSStephan Mueller struct drbg_test_suite {
120b13b1e0cSEric Biggers 	const struct drbg_testvec *vecs;
12164d1cdfbSStephan Mueller 	unsigned int count;
12264d1cdfbSStephan Mueller };
12364d1cdfbSStephan Mueller 
124946cc463STadeusz Struk struct akcipher_test_suite {
125b13b1e0cSEric Biggers 	const struct akcipher_testvec *vecs;
126946cc463STadeusz Struk 	unsigned int count;
127946cc463STadeusz Struk };
128946cc463STadeusz Struk 
129802c7f1cSSalvatore Benedetto struct kpp_test_suite {
130b13b1e0cSEric Biggers 	const struct kpp_testvec *vecs;
131802c7f1cSSalvatore Benedetto 	unsigned int count;
132802c7f1cSSalvatore Benedetto };
133802c7f1cSSalvatore Benedetto 
134da7f033dSHerbert Xu struct alg_test_desc {
135da7f033dSHerbert Xu 	const char *alg;
136da7f033dSHerbert Xu 	int (*test)(const struct alg_test_desc *desc, const char *driver,
137da7f033dSHerbert Xu 		    u32 type, u32 mask);
138a1915d51SJarod Wilson 	int fips_allowed;	/* set if alg is allowed in fips mode */
139da7f033dSHerbert Xu 
140da7f033dSHerbert Xu 	union {
141da7f033dSHerbert Xu 		struct aead_test_suite aead;
142da7f033dSHerbert Xu 		struct cipher_test_suite cipher;
143da7f033dSHerbert Xu 		struct comp_test_suite comp;
144da7f033dSHerbert Xu 		struct hash_test_suite hash;
1457647d6ceSJarod Wilson 		struct cprng_test_suite cprng;
14664d1cdfbSStephan Mueller 		struct drbg_test_suite drbg;
147946cc463STadeusz Struk 		struct akcipher_test_suite akcipher;
148802c7f1cSSalvatore Benedetto 		struct kpp_test_suite kpp;
149da7f033dSHerbert Xu 	} suite;
150da7f033dSHerbert Xu };
151da7f033dSHerbert Xu 
152b13b1e0cSEric Biggers static const unsigned int IDX[8] = {
153b13b1e0cSEric Biggers 	IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
154da7f033dSHerbert Xu 
155da7f033dSHerbert Xu static void hexdump(unsigned char *buf, unsigned int len)
156da7f033dSHerbert Xu {
157da7f033dSHerbert Xu 	print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
158da7f033dSHerbert Xu 			16, 1,
159da7f033dSHerbert Xu 			buf, len, false);
160da7f033dSHerbert Xu }
161da7f033dSHerbert Xu 
1623f47a03dSEric Biggers static int __testmgr_alloc_buf(char *buf[XBUFSIZE], int order)
163f8b0d4d0SHerbert Xu {
164f8b0d4d0SHerbert Xu 	int i;
165f8b0d4d0SHerbert Xu 
166f8b0d4d0SHerbert Xu 	for (i = 0; i < XBUFSIZE; i++) {
1673f47a03dSEric Biggers 		buf[i] = (char *)__get_free_pages(GFP_KERNEL, order);
168f8b0d4d0SHerbert Xu 		if (!buf[i])
169f8b0d4d0SHerbert Xu 			goto err_free_buf;
170f8b0d4d0SHerbert Xu 	}
171f8b0d4d0SHerbert Xu 
172f8b0d4d0SHerbert Xu 	return 0;
173f8b0d4d0SHerbert Xu 
174f8b0d4d0SHerbert Xu err_free_buf:
175f8b0d4d0SHerbert Xu 	while (i-- > 0)
1763f47a03dSEric Biggers 		free_pages((unsigned long)buf[i], order);
177f8b0d4d0SHerbert Xu 
178f8b0d4d0SHerbert Xu 	return -ENOMEM;
179f8b0d4d0SHerbert Xu }
180f8b0d4d0SHerbert Xu 
1813f47a03dSEric Biggers static int testmgr_alloc_buf(char *buf[XBUFSIZE])
1823f47a03dSEric Biggers {
1833f47a03dSEric Biggers 	return __testmgr_alloc_buf(buf, 0);
1843f47a03dSEric Biggers }
1853f47a03dSEric Biggers 
1863f47a03dSEric Biggers static void __testmgr_free_buf(char *buf[XBUFSIZE], int order)
187f8b0d4d0SHerbert Xu {
188f8b0d4d0SHerbert Xu 	int i;
189f8b0d4d0SHerbert Xu 
190f8b0d4d0SHerbert Xu 	for (i = 0; i < XBUFSIZE; i++)
1913f47a03dSEric Biggers 		free_pages((unsigned long)buf[i], order);
1923f47a03dSEric Biggers }
1933f47a03dSEric Biggers 
1943f47a03dSEric Biggers static void testmgr_free_buf(char *buf[XBUFSIZE])
1953f47a03dSEric Biggers {
1963f47a03dSEric Biggers 	__testmgr_free_buf(buf, 0);
1973f47a03dSEric Biggers }
1983f47a03dSEric Biggers 
1993f47a03dSEric Biggers #define TESTMGR_POISON_BYTE	0xfe
2003f47a03dSEric Biggers #define TESTMGR_POISON_LEN	16
2013f47a03dSEric Biggers 
2023f47a03dSEric Biggers static inline void testmgr_poison(void *addr, size_t len)
2033f47a03dSEric Biggers {
2043f47a03dSEric Biggers 	memset(addr, TESTMGR_POISON_BYTE, len);
2053f47a03dSEric Biggers }
2063f47a03dSEric Biggers 
2073f47a03dSEric Biggers /* Is the memory region still fully poisoned? */
2083f47a03dSEric Biggers static inline bool testmgr_is_poison(const void *addr, size_t len)
2093f47a03dSEric Biggers {
2103f47a03dSEric Biggers 	return memchr_inv(addr, TESTMGR_POISON_BYTE, len) == NULL;
2113f47a03dSEric Biggers }
2123f47a03dSEric Biggers 
2133f47a03dSEric Biggers /* flush type for hash algorithms */
2143f47a03dSEric Biggers enum flush_type {
2153f47a03dSEric Biggers 	/* merge with update of previous buffer(s) */
2163f47a03dSEric Biggers 	FLUSH_TYPE_NONE = 0,
2173f47a03dSEric Biggers 
2183f47a03dSEric Biggers 	/* update with previous buffer(s) before doing this one */
2193f47a03dSEric Biggers 	FLUSH_TYPE_FLUSH,
2203f47a03dSEric Biggers 
2213f47a03dSEric Biggers 	/* likewise, but also export and re-import the intermediate state */
2223f47a03dSEric Biggers 	FLUSH_TYPE_REIMPORT,
2233f47a03dSEric Biggers };
2243f47a03dSEric Biggers 
2253f47a03dSEric Biggers /* finalization function for hash algorithms */
2263f47a03dSEric Biggers enum finalization_type {
2273f47a03dSEric Biggers 	FINALIZATION_TYPE_FINAL,	/* use final() */
2283f47a03dSEric Biggers 	FINALIZATION_TYPE_FINUP,	/* use finup() */
2293f47a03dSEric Biggers 	FINALIZATION_TYPE_DIGEST,	/* use digest() */
2303f47a03dSEric Biggers };
2313f47a03dSEric Biggers 
2323f47a03dSEric Biggers #define TEST_SG_TOTAL	10000
2333f47a03dSEric Biggers 
2343f47a03dSEric Biggers /**
2353f47a03dSEric Biggers  * struct test_sg_division - description of a scatterlist entry
2363f47a03dSEric Biggers  *
2373f47a03dSEric Biggers  * This struct describes one entry of a scatterlist being constructed to check a
2383f47a03dSEric Biggers  * crypto test vector.
2393f47a03dSEric Biggers  *
2403f47a03dSEric Biggers  * @proportion_of_total: length of this chunk relative to the total length,
2413f47a03dSEric Biggers  *			 given as a proportion out of TEST_SG_TOTAL so that it
2423f47a03dSEric Biggers  *			 scales to fit any test vector
2433f47a03dSEric Biggers  * @offset: byte offset into a 2-page buffer at which this chunk will start
2443f47a03dSEric Biggers  * @offset_relative_to_alignmask: if true, add the algorithm's alignmask to the
2453f47a03dSEric Biggers  *				  @offset
2463f47a03dSEric Biggers  * @flush_type: for hashes, whether an update() should be done now vs.
2473f47a03dSEric Biggers  *		continuing to accumulate data
2483f47a03dSEric Biggers  */
2493f47a03dSEric Biggers struct test_sg_division {
2503f47a03dSEric Biggers 	unsigned int proportion_of_total;
2513f47a03dSEric Biggers 	unsigned int offset;
2523f47a03dSEric Biggers 	bool offset_relative_to_alignmask;
2533f47a03dSEric Biggers 	enum flush_type flush_type;
2543f47a03dSEric Biggers };
2553f47a03dSEric Biggers 
2563f47a03dSEric Biggers /**
2573f47a03dSEric Biggers  * struct testvec_config - configuration for testing a crypto test vector
2583f47a03dSEric Biggers  *
2593f47a03dSEric Biggers  * This struct describes the data layout and other parameters with which each
2603f47a03dSEric Biggers  * crypto test vector can be tested.
2613f47a03dSEric Biggers  *
2623f47a03dSEric Biggers  * @name: name of this config, logged for debugging purposes if a test fails
2633f47a03dSEric Biggers  * @inplace: operate on the data in-place, if applicable for the algorithm type?
2643f47a03dSEric Biggers  * @req_flags: extra request_flags, e.g. CRYPTO_TFM_REQ_MAY_SLEEP
2653f47a03dSEric Biggers  * @src_divs: description of how to arrange the source scatterlist
2663f47a03dSEric Biggers  * @dst_divs: description of how to arrange the dst scatterlist, if applicable
2673f47a03dSEric Biggers  *	      for the algorithm type.  Defaults to @src_divs if unset.
2683f47a03dSEric Biggers  * @iv_offset: misalignment of the IV in the range [0..MAX_ALGAPI_ALIGNMASK+1],
2693f47a03dSEric Biggers  *	       where 0 is aligned to a 2*(MAX_ALGAPI_ALIGNMASK+1) byte boundary
2703f47a03dSEric Biggers  * @iv_offset_relative_to_alignmask: if true, add the algorithm's alignmask to
2713f47a03dSEric Biggers  *				     the @iv_offset
2723f47a03dSEric Biggers  * @finalization_type: what finalization function to use for hashes
2733f47a03dSEric Biggers  */
2743f47a03dSEric Biggers struct testvec_config {
2753f47a03dSEric Biggers 	const char *name;
2763f47a03dSEric Biggers 	bool inplace;
2773f47a03dSEric Biggers 	u32 req_flags;
2783f47a03dSEric Biggers 	struct test_sg_division src_divs[XBUFSIZE];
2793f47a03dSEric Biggers 	struct test_sg_division dst_divs[XBUFSIZE];
2803f47a03dSEric Biggers 	unsigned int iv_offset;
2813f47a03dSEric Biggers 	bool iv_offset_relative_to_alignmask;
2823f47a03dSEric Biggers 	enum finalization_type finalization_type;
2833f47a03dSEric Biggers };
2843f47a03dSEric Biggers 
2853f47a03dSEric Biggers #define TESTVEC_CONFIG_NAMELEN	192
2863f47a03dSEric Biggers 
2873f47a03dSEric Biggers static unsigned int count_test_sg_divisions(const struct test_sg_division *divs)
2883f47a03dSEric Biggers {
2893f47a03dSEric Biggers 	unsigned int remaining = TEST_SG_TOTAL;
2903f47a03dSEric Biggers 	unsigned int ndivs = 0;
2913f47a03dSEric Biggers 
2923f47a03dSEric Biggers 	do {
2933f47a03dSEric Biggers 		remaining -= divs[ndivs++].proportion_of_total;
2943f47a03dSEric Biggers 	} while (remaining);
2953f47a03dSEric Biggers 
2963f47a03dSEric Biggers 	return ndivs;
2973f47a03dSEric Biggers }
2983f47a03dSEric Biggers 
2993f47a03dSEric Biggers static bool valid_sg_divisions(const struct test_sg_division *divs,
3003f47a03dSEric Biggers 			       unsigned int count, bool *any_flushes_ret)
3013f47a03dSEric Biggers {
3023f47a03dSEric Biggers 	unsigned int total = 0;
3033f47a03dSEric Biggers 	unsigned int i;
3043f47a03dSEric Biggers 
3053f47a03dSEric Biggers 	for (i = 0; i < count && total != TEST_SG_TOTAL; i++) {
3063f47a03dSEric Biggers 		if (divs[i].proportion_of_total <= 0 ||
3073f47a03dSEric Biggers 		    divs[i].proportion_of_total > TEST_SG_TOTAL - total)
3083f47a03dSEric Biggers 			return false;
3093f47a03dSEric Biggers 		total += divs[i].proportion_of_total;
3103f47a03dSEric Biggers 		if (divs[i].flush_type != FLUSH_TYPE_NONE)
3113f47a03dSEric Biggers 			*any_flushes_ret = true;
3123f47a03dSEric Biggers 	}
3133f47a03dSEric Biggers 	return total == TEST_SG_TOTAL &&
3143f47a03dSEric Biggers 		memchr_inv(&divs[i], 0, (count - i) * sizeof(divs[0])) == NULL;
3153f47a03dSEric Biggers }
3163f47a03dSEric Biggers 
3173f47a03dSEric Biggers /*
3183f47a03dSEric Biggers  * Check whether the given testvec_config is valid.  This isn't strictly needed
3193f47a03dSEric Biggers  * since every testvec_config should be valid, but check anyway so that people
3203f47a03dSEric Biggers  * don't unknowingly add broken configs that don't do what they wanted.
3213f47a03dSEric Biggers  */
3223f47a03dSEric Biggers static bool valid_testvec_config(const struct testvec_config *cfg)
3233f47a03dSEric Biggers {
3243f47a03dSEric Biggers 	bool any_flushes = false;
3253f47a03dSEric Biggers 
3263f47a03dSEric Biggers 	if (cfg->name == NULL)
3273f47a03dSEric Biggers 		return false;
3283f47a03dSEric Biggers 
3293f47a03dSEric Biggers 	if (!valid_sg_divisions(cfg->src_divs, ARRAY_SIZE(cfg->src_divs),
3303f47a03dSEric Biggers 				&any_flushes))
3313f47a03dSEric Biggers 		return false;
3323f47a03dSEric Biggers 
3333f47a03dSEric Biggers 	if (cfg->dst_divs[0].proportion_of_total) {
3343f47a03dSEric Biggers 		if (!valid_sg_divisions(cfg->dst_divs,
3353f47a03dSEric Biggers 					ARRAY_SIZE(cfg->dst_divs),
3363f47a03dSEric Biggers 					&any_flushes))
3373f47a03dSEric Biggers 			return false;
3383f47a03dSEric Biggers 	} else {
3393f47a03dSEric Biggers 		if (memchr_inv(cfg->dst_divs, 0, sizeof(cfg->dst_divs)))
3403f47a03dSEric Biggers 			return false;
3413f47a03dSEric Biggers 		/* defaults to dst_divs=src_divs */
3423f47a03dSEric Biggers 	}
3433f47a03dSEric Biggers 
3443f47a03dSEric Biggers 	if (cfg->iv_offset +
3453f47a03dSEric Biggers 	    (cfg->iv_offset_relative_to_alignmask ? MAX_ALGAPI_ALIGNMASK : 0) >
3463f47a03dSEric Biggers 	    MAX_ALGAPI_ALIGNMASK + 1)
3473f47a03dSEric Biggers 		return false;
3483f47a03dSEric Biggers 
3493f47a03dSEric Biggers 	if (any_flushes && cfg->finalization_type == FINALIZATION_TYPE_DIGEST)
3503f47a03dSEric Biggers 		return false;
3513f47a03dSEric Biggers 
3523f47a03dSEric Biggers 	return true;
3533f47a03dSEric Biggers }
3543f47a03dSEric Biggers 
3553f47a03dSEric Biggers struct test_sglist {
3563f47a03dSEric Biggers 	char *bufs[XBUFSIZE];
3573f47a03dSEric Biggers 	struct scatterlist sgl[XBUFSIZE];
3583f47a03dSEric Biggers 	struct scatterlist sgl_saved[XBUFSIZE];
3593f47a03dSEric Biggers 	struct scatterlist *sgl_ptr;
3603f47a03dSEric Biggers 	unsigned int nents;
3613f47a03dSEric Biggers };
3623f47a03dSEric Biggers 
3633f47a03dSEric Biggers static int init_test_sglist(struct test_sglist *tsgl)
3643f47a03dSEric Biggers {
3653f47a03dSEric Biggers 	return __testmgr_alloc_buf(tsgl->bufs, 1 /* two pages per buffer */);
3663f47a03dSEric Biggers }
3673f47a03dSEric Biggers 
3683f47a03dSEric Biggers static void destroy_test_sglist(struct test_sglist *tsgl)
3693f47a03dSEric Biggers {
3703f47a03dSEric Biggers 	return __testmgr_free_buf(tsgl->bufs, 1 /* two pages per buffer */);
3713f47a03dSEric Biggers }
3723f47a03dSEric Biggers 
3733f47a03dSEric Biggers /**
3743f47a03dSEric Biggers  * build_test_sglist() - build a scatterlist for a crypto test
3753f47a03dSEric Biggers  *
3763f47a03dSEric Biggers  * @tsgl: the scatterlist to build.  @tsgl->bufs[] contains an array of 2-page
3773f47a03dSEric Biggers  *	  buffers which the scatterlist @tsgl->sgl[] will be made to point into.
3783f47a03dSEric Biggers  * @divs: the layout specification on which the scatterlist will be based
3793f47a03dSEric Biggers  * @alignmask: the algorithm's alignmask
3803f47a03dSEric Biggers  * @total_len: the total length of the scatterlist to build in bytes
3813f47a03dSEric Biggers  * @data: if non-NULL, the buffers will be filled with this data until it ends.
3823f47a03dSEric Biggers  *	  Otherwise the buffers will be poisoned.  In both cases, some bytes
3833f47a03dSEric Biggers  *	  past the end of each buffer will be poisoned to help detect overruns.
3843f47a03dSEric Biggers  * @out_divs: if non-NULL, the test_sg_division to which each scatterlist entry
3853f47a03dSEric Biggers  *	      corresponds will be returned here.  This will match @divs except
3863f47a03dSEric Biggers  *	      that divisions resolving to a length of 0 are omitted as they are
3873f47a03dSEric Biggers  *	      not included in the scatterlist.
3883f47a03dSEric Biggers  *
3893f47a03dSEric Biggers  * Return: 0 or a -errno value
3903f47a03dSEric Biggers  */
3913f47a03dSEric Biggers static int build_test_sglist(struct test_sglist *tsgl,
3923f47a03dSEric Biggers 			     const struct test_sg_division *divs,
3933f47a03dSEric Biggers 			     const unsigned int alignmask,
3943f47a03dSEric Biggers 			     const unsigned int total_len,
3953f47a03dSEric Biggers 			     struct iov_iter *data,
3963f47a03dSEric Biggers 			     const struct test_sg_division *out_divs[XBUFSIZE])
3973f47a03dSEric Biggers {
3983f47a03dSEric Biggers 	struct {
3993f47a03dSEric Biggers 		const struct test_sg_division *div;
4003f47a03dSEric Biggers 		size_t length;
4013f47a03dSEric Biggers 	} partitions[XBUFSIZE];
4023f47a03dSEric Biggers 	const unsigned int ndivs = count_test_sg_divisions(divs);
4033f47a03dSEric Biggers 	unsigned int len_remaining = total_len;
4043f47a03dSEric Biggers 	unsigned int i;
4053f47a03dSEric Biggers 
4063f47a03dSEric Biggers 	BUILD_BUG_ON(ARRAY_SIZE(partitions) != ARRAY_SIZE(tsgl->sgl));
4073f47a03dSEric Biggers 	if (WARN_ON(ndivs > ARRAY_SIZE(partitions)))
4083f47a03dSEric Biggers 		return -EINVAL;
4093f47a03dSEric Biggers 
4103f47a03dSEric Biggers 	/* Calculate the (div, length) pairs */
4113f47a03dSEric Biggers 	tsgl->nents = 0;
4123f47a03dSEric Biggers 	for (i = 0; i < ndivs; i++) {
4133f47a03dSEric Biggers 		unsigned int len_this_sg =
4143f47a03dSEric Biggers 			min(len_remaining,
4153f47a03dSEric Biggers 			    (total_len * divs[i].proportion_of_total +
4163f47a03dSEric Biggers 			     TEST_SG_TOTAL / 2) / TEST_SG_TOTAL);
4173f47a03dSEric Biggers 
4183f47a03dSEric Biggers 		if (len_this_sg != 0) {
4193f47a03dSEric Biggers 			partitions[tsgl->nents].div = &divs[i];
4203f47a03dSEric Biggers 			partitions[tsgl->nents].length = len_this_sg;
4213f47a03dSEric Biggers 			tsgl->nents++;
4223f47a03dSEric Biggers 			len_remaining -= len_this_sg;
4233f47a03dSEric Biggers 		}
4243f47a03dSEric Biggers 	}
4253f47a03dSEric Biggers 	if (tsgl->nents == 0) {
4263f47a03dSEric Biggers 		partitions[tsgl->nents].div = &divs[0];
4273f47a03dSEric Biggers 		partitions[tsgl->nents].length = 0;
4283f47a03dSEric Biggers 		tsgl->nents++;
4293f47a03dSEric Biggers 	}
4303f47a03dSEric Biggers 	partitions[tsgl->nents - 1].length += len_remaining;
4313f47a03dSEric Biggers 
4323f47a03dSEric Biggers 	/* Set up the sgl entries and fill the data or poison */
4333f47a03dSEric Biggers 	sg_init_table(tsgl->sgl, tsgl->nents);
4343f47a03dSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
4353f47a03dSEric Biggers 		unsigned int offset = partitions[i].div->offset;
4363f47a03dSEric Biggers 		void *addr;
4373f47a03dSEric Biggers 
4383f47a03dSEric Biggers 		if (partitions[i].div->offset_relative_to_alignmask)
4393f47a03dSEric Biggers 			offset += alignmask;
4403f47a03dSEric Biggers 
4413f47a03dSEric Biggers 		while (offset + partitions[i].length + TESTMGR_POISON_LEN >
4423f47a03dSEric Biggers 		       2 * PAGE_SIZE) {
4433f47a03dSEric Biggers 			if (WARN_ON(offset <= 0))
4443f47a03dSEric Biggers 				return -EINVAL;
4453f47a03dSEric Biggers 			offset /= 2;
4463f47a03dSEric Biggers 		}
4473f47a03dSEric Biggers 
4483f47a03dSEric Biggers 		addr = &tsgl->bufs[i][offset];
4493f47a03dSEric Biggers 		sg_set_buf(&tsgl->sgl[i], addr, partitions[i].length);
4503f47a03dSEric Biggers 
4513f47a03dSEric Biggers 		if (out_divs)
4523f47a03dSEric Biggers 			out_divs[i] = partitions[i].div;
4533f47a03dSEric Biggers 
4543f47a03dSEric Biggers 		if (data) {
4553f47a03dSEric Biggers 			size_t copy_len, copied;
4563f47a03dSEric Biggers 
4573f47a03dSEric Biggers 			copy_len = min(partitions[i].length, data->count);
4583f47a03dSEric Biggers 			copied = copy_from_iter(addr, copy_len, data);
4593f47a03dSEric Biggers 			if (WARN_ON(copied != copy_len))
4603f47a03dSEric Biggers 				return -EINVAL;
4613f47a03dSEric Biggers 			testmgr_poison(addr + copy_len, partitions[i].length +
4623f47a03dSEric Biggers 				       TESTMGR_POISON_LEN - copy_len);
4633f47a03dSEric Biggers 		} else {
4643f47a03dSEric Biggers 			testmgr_poison(addr, partitions[i].length +
4653f47a03dSEric Biggers 				       TESTMGR_POISON_LEN);
4663f47a03dSEric Biggers 		}
4673f47a03dSEric Biggers 	}
4683f47a03dSEric Biggers 
4693f47a03dSEric Biggers 	sg_mark_end(&tsgl->sgl[tsgl->nents - 1]);
4703f47a03dSEric Biggers 	tsgl->sgl_ptr = tsgl->sgl;
4713f47a03dSEric Biggers 	memcpy(tsgl->sgl_saved, tsgl->sgl, tsgl->nents * sizeof(tsgl->sgl[0]));
4723f47a03dSEric Biggers 	return 0;
4733f47a03dSEric Biggers }
4743f47a03dSEric Biggers 
4753f47a03dSEric Biggers /*
4763f47a03dSEric Biggers  * Verify that a scatterlist crypto operation produced the correct output.
4773f47a03dSEric Biggers  *
4783f47a03dSEric Biggers  * @tsgl: scatterlist containing the actual output
4793f47a03dSEric Biggers  * @expected_output: buffer containing the expected output
4803f47a03dSEric Biggers  * @len_to_check: length of @expected_output in bytes
4813f47a03dSEric Biggers  * @unchecked_prefix_len: number of ignored bytes in @tsgl prior to real result
4823f47a03dSEric Biggers  * @check_poison: verify that the poison bytes after each chunk are intact?
4833f47a03dSEric Biggers  *
4843f47a03dSEric Biggers  * Return: 0 if correct, -EINVAL if incorrect, -EOVERFLOW if buffer overrun.
4853f47a03dSEric Biggers  */
4863f47a03dSEric Biggers static int verify_correct_output(const struct test_sglist *tsgl,
4873f47a03dSEric Biggers 				 const char *expected_output,
4883f47a03dSEric Biggers 				 unsigned int len_to_check,
4893f47a03dSEric Biggers 				 unsigned int unchecked_prefix_len,
4903f47a03dSEric Biggers 				 bool check_poison)
4913f47a03dSEric Biggers {
4923f47a03dSEric Biggers 	unsigned int i;
4933f47a03dSEric Biggers 
4943f47a03dSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
4953f47a03dSEric Biggers 		struct scatterlist *sg = &tsgl->sgl_ptr[i];
4963f47a03dSEric Biggers 		unsigned int len = sg->length;
4973f47a03dSEric Biggers 		unsigned int offset = sg->offset;
4983f47a03dSEric Biggers 		const char *actual_output;
4993f47a03dSEric Biggers 
5003f47a03dSEric Biggers 		if (unchecked_prefix_len) {
5013f47a03dSEric Biggers 			if (unchecked_prefix_len >= len) {
5023f47a03dSEric Biggers 				unchecked_prefix_len -= len;
5033f47a03dSEric Biggers 				continue;
5043f47a03dSEric Biggers 			}
5053f47a03dSEric Biggers 			offset += unchecked_prefix_len;
5063f47a03dSEric Biggers 			len -= unchecked_prefix_len;
5073f47a03dSEric Biggers 			unchecked_prefix_len = 0;
5083f47a03dSEric Biggers 		}
5093f47a03dSEric Biggers 		len = min(len, len_to_check);
5103f47a03dSEric Biggers 		actual_output = page_address(sg_page(sg)) + offset;
5113f47a03dSEric Biggers 		if (memcmp(expected_output, actual_output, len) != 0)
5123f47a03dSEric Biggers 			return -EINVAL;
5133f47a03dSEric Biggers 		if (check_poison &&
5143f47a03dSEric Biggers 		    !testmgr_is_poison(actual_output + len, TESTMGR_POISON_LEN))
5153f47a03dSEric Biggers 			return -EOVERFLOW;
5163f47a03dSEric Biggers 		len_to_check -= len;
5173f47a03dSEric Biggers 		expected_output += len;
5183f47a03dSEric Biggers 	}
5193f47a03dSEric Biggers 	if (WARN_ON(len_to_check != 0))
5203f47a03dSEric Biggers 		return -EINVAL;
5213f47a03dSEric Biggers 	return 0;
5223f47a03dSEric Biggers }
5233f47a03dSEric Biggers 
5243f47a03dSEric Biggers static bool is_test_sglist_corrupted(const struct test_sglist *tsgl)
5253f47a03dSEric Biggers {
5263f47a03dSEric Biggers 	unsigned int i;
5273f47a03dSEric Biggers 
5283f47a03dSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
5293f47a03dSEric Biggers 		if (tsgl->sgl[i].page_link != tsgl->sgl_saved[i].page_link)
5303f47a03dSEric Biggers 			return true;
5313f47a03dSEric Biggers 		if (tsgl->sgl[i].offset != tsgl->sgl_saved[i].offset)
5323f47a03dSEric Biggers 			return true;
5333f47a03dSEric Biggers 		if (tsgl->sgl[i].length != tsgl->sgl_saved[i].length)
5343f47a03dSEric Biggers 			return true;
5353f47a03dSEric Biggers 	}
5363f47a03dSEric Biggers 	return false;
5373f47a03dSEric Biggers }
5383f47a03dSEric Biggers 
5393f47a03dSEric Biggers struct cipher_test_sglists {
5403f47a03dSEric Biggers 	struct test_sglist src;
5413f47a03dSEric Biggers 	struct test_sglist dst;
5423f47a03dSEric Biggers };
5433f47a03dSEric Biggers 
5443f47a03dSEric Biggers static struct cipher_test_sglists *alloc_cipher_test_sglists(void)
5453f47a03dSEric Biggers {
5463f47a03dSEric Biggers 	struct cipher_test_sglists *tsgls;
5473f47a03dSEric Biggers 
5483f47a03dSEric Biggers 	tsgls = kmalloc(sizeof(*tsgls), GFP_KERNEL);
5493f47a03dSEric Biggers 	if (!tsgls)
5503f47a03dSEric Biggers 		return NULL;
5513f47a03dSEric Biggers 
5523f47a03dSEric Biggers 	if (init_test_sglist(&tsgls->src) != 0)
5533f47a03dSEric Biggers 		goto fail_kfree;
5543f47a03dSEric Biggers 	if (init_test_sglist(&tsgls->dst) != 0)
5553f47a03dSEric Biggers 		goto fail_destroy_src;
5563f47a03dSEric Biggers 
5573f47a03dSEric Biggers 	return tsgls;
5583f47a03dSEric Biggers 
5593f47a03dSEric Biggers fail_destroy_src:
5603f47a03dSEric Biggers 	destroy_test_sglist(&tsgls->src);
5613f47a03dSEric Biggers fail_kfree:
5623f47a03dSEric Biggers 	kfree(tsgls);
5633f47a03dSEric Biggers 	return NULL;
5643f47a03dSEric Biggers }
5653f47a03dSEric Biggers 
5663f47a03dSEric Biggers static void free_cipher_test_sglists(struct cipher_test_sglists *tsgls)
5673f47a03dSEric Biggers {
5683f47a03dSEric Biggers 	if (tsgls) {
5693f47a03dSEric Biggers 		destroy_test_sglist(&tsgls->src);
5703f47a03dSEric Biggers 		destroy_test_sglist(&tsgls->dst);
5713f47a03dSEric Biggers 		kfree(tsgls);
5723f47a03dSEric Biggers 	}
5733f47a03dSEric Biggers }
5743f47a03dSEric Biggers 
5753f47a03dSEric Biggers /* Build the src and dst scatterlists for an skcipher or AEAD test */
5763f47a03dSEric Biggers static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls,
5773f47a03dSEric Biggers 				     const struct testvec_config *cfg,
5783f47a03dSEric Biggers 				     unsigned int alignmask,
5793f47a03dSEric Biggers 				     unsigned int src_total_len,
5803f47a03dSEric Biggers 				     unsigned int dst_total_len,
5813f47a03dSEric Biggers 				     const struct kvec *inputs,
5823f47a03dSEric Biggers 				     unsigned int nr_inputs)
5833f47a03dSEric Biggers {
5843f47a03dSEric Biggers 	struct iov_iter input;
5853f47a03dSEric Biggers 	int err;
5863f47a03dSEric Biggers 
5873f47a03dSEric Biggers 	iov_iter_kvec(&input, WRITE, inputs, nr_inputs, src_total_len);
5883f47a03dSEric Biggers 	err = build_test_sglist(&tsgls->src, cfg->src_divs, alignmask,
5893f47a03dSEric Biggers 				cfg->inplace ?
5903f47a03dSEric Biggers 					max(dst_total_len, src_total_len) :
5913f47a03dSEric Biggers 					src_total_len,
5923f47a03dSEric Biggers 				&input, NULL);
5933f47a03dSEric Biggers 	if (err)
5943f47a03dSEric Biggers 		return err;
5953f47a03dSEric Biggers 
5963f47a03dSEric Biggers 	if (cfg->inplace) {
5973f47a03dSEric Biggers 		tsgls->dst.sgl_ptr = tsgls->src.sgl;
5983f47a03dSEric Biggers 		tsgls->dst.nents = tsgls->src.nents;
5993f47a03dSEric Biggers 		return 0;
6003f47a03dSEric Biggers 	}
6013f47a03dSEric Biggers 	return build_test_sglist(&tsgls->dst,
6023f47a03dSEric Biggers 				 cfg->dst_divs[0].proportion_of_total ?
6033f47a03dSEric Biggers 					cfg->dst_divs : cfg->src_divs,
6043f47a03dSEric Biggers 				 alignmask, dst_total_len, NULL, NULL);
605f8b0d4d0SHerbert Xu }
606f8b0d4d0SHerbert Xu 
60725f9dddbSEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
60825f9dddbSEric Biggers static char *generate_random_sgl_divisions(struct test_sg_division *divs,
60925f9dddbSEric Biggers 					   size_t max_divs, char *p, char *end,
61025f9dddbSEric Biggers 					   bool gen_flushes)
61125f9dddbSEric Biggers {
61225f9dddbSEric Biggers 	struct test_sg_division *div = divs;
61325f9dddbSEric Biggers 	unsigned int remaining = TEST_SG_TOTAL;
61425f9dddbSEric Biggers 
61525f9dddbSEric Biggers 	do {
61625f9dddbSEric Biggers 		unsigned int this_len;
61725f9dddbSEric Biggers 
61825f9dddbSEric Biggers 		if (div == &divs[max_divs - 1] || prandom_u32() % 2 == 0)
61925f9dddbSEric Biggers 			this_len = remaining;
62025f9dddbSEric Biggers 		else
62125f9dddbSEric Biggers 			this_len = 1 + (prandom_u32() % remaining);
62225f9dddbSEric Biggers 		div->proportion_of_total = this_len;
62325f9dddbSEric Biggers 
62425f9dddbSEric Biggers 		if (prandom_u32() % 4 == 0)
62525f9dddbSEric Biggers 			div->offset = (PAGE_SIZE - 128) + (prandom_u32() % 128);
62625f9dddbSEric Biggers 		else if (prandom_u32() % 2 == 0)
62725f9dddbSEric Biggers 			div->offset = prandom_u32() % 32;
62825f9dddbSEric Biggers 		else
62925f9dddbSEric Biggers 			div->offset = prandom_u32() % PAGE_SIZE;
63025f9dddbSEric Biggers 		if (prandom_u32() % 8 == 0)
63125f9dddbSEric Biggers 			div->offset_relative_to_alignmask = true;
63225f9dddbSEric Biggers 
63325f9dddbSEric Biggers 		div->flush_type = FLUSH_TYPE_NONE;
63425f9dddbSEric Biggers 		if (gen_flushes) {
63525f9dddbSEric Biggers 			switch (prandom_u32() % 4) {
63625f9dddbSEric Biggers 			case 0:
63725f9dddbSEric Biggers 				div->flush_type = FLUSH_TYPE_REIMPORT;
63825f9dddbSEric Biggers 				break;
63925f9dddbSEric Biggers 			case 1:
64025f9dddbSEric Biggers 				div->flush_type = FLUSH_TYPE_FLUSH;
64125f9dddbSEric Biggers 				break;
64225f9dddbSEric Biggers 			}
64325f9dddbSEric Biggers 		}
64425f9dddbSEric Biggers 
64525f9dddbSEric Biggers 		BUILD_BUG_ON(TEST_SG_TOTAL != 10000); /* for "%u.%u%%" */
64625f9dddbSEric Biggers 		p += scnprintf(p, end - p, "%s%u.%u%%@%s+%u%s",
64725f9dddbSEric Biggers 			       div->flush_type == FLUSH_TYPE_NONE ? "" :
64825f9dddbSEric Biggers 			       div->flush_type == FLUSH_TYPE_FLUSH ?
64925f9dddbSEric Biggers 			       "<flush> " : "<reimport> ",
65025f9dddbSEric Biggers 			       this_len / 100, this_len % 100,
65125f9dddbSEric Biggers 			       div->offset_relative_to_alignmask ?
65225f9dddbSEric Biggers 					"alignmask" : "",
65325f9dddbSEric Biggers 			       div->offset, this_len == remaining ? "" : ", ");
65425f9dddbSEric Biggers 		remaining -= this_len;
65525f9dddbSEric Biggers 		div++;
65625f9dddbSEric Biggers 	} while (remaining);
65725f9dddbSEric Biggers 
65825f9dddbSEric Biggers 	return p;
65925f9dddbSEric Biggers }
66025f9dddbSEric Biggers 
66125f9dddbSEric Biggers /* Generate a random testvec_config for fuzz testing */
66225f9dddbSEric Biggers static void generate_random_testvec_config(struct testvec_config *cfg,
66325f9dddbSEric Biggers 					   char *name, size_t max_namelen)
66425f9dddbSEric Biggers {
66525f9dddbSEric Biggers 	char *p = name;
66625f9dddbSEric Biggers 	char * const end = name + max_namelen;
66725f9dddbSEric Biggers 
66825f9dddbSEric Biggers 	memset(cfg, 0, sizeof(*cfg));
66925f9dddbSEric Biggers 
67025f9dddbSEric Biggers 	cfg->name = name;
67125f9dddbSEric Biggers 
67225f9dddbSEric Biggers 	p += scnprintf(p, end - p, "random:");
67325f9dddbSEric Biggers 
67425f9dddbSEric Biggers 	if (prandom_u32() % 2 == 0) {
67525f9dddbSEric Biggers 		cfg->inplace = true;
67625f9dddbSEric Biggers 		p += scnprintf(p, end - p, " inplace");
67725f9dddbSEric Biggers 	}
67825f9dddbSEric Biggers 
67925f9dddbSEric Biggers 	if (prandom_u32() % 2 == 0) {
68025f9dddbSEric Biggers 		cfg->req_flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
68125f9dddbSEric Biggers 		p += scnprintf(p, end - p, " may_sleep");
68225f9dddbSEric Biggers 	}
68325f9dddbSEric Biggers 
68425f9dddbSEric Biggers 	switch (prandom_u32() % 4) {
68525f9dddbSEric Biggers 	case 0:
68625f9dddbSEric Biggers 		cfg->finalization_type = FINALIZATION_TYPE_FINAL;
68725f9dddbSEric Biggers 		p += scnprintf(p, end - p, " use_final");
68825f9dddbSEric Biggers 		break;
68925f9dddbSEric Biggers 	case 1:
69025f9dddbSEric Biggers 		cfg->finalization_type = FINALIZATION_TYPE_FINUP;
69125f9dddbSEric Biggers 		p += scnprintf(p, end - p, " use_finup");
69225f9dddbSEric Biggers 		break;
69325f9dddbSEric Biggers 	default:
69425f9dddbSEric Biggers 		cfg->finalization_type = FINALIZATION_TYPE_DIGEST;
69525f9dddbSEric Biggers 		p += scnprintf(p, end - p, " use_digest");
69625f9dddbSEric Biggers 		break;
69725f9dddbSEric Biggers 	}
69825f9dddbSEric Biggers 
69925f9dddbSEric Biggers 	p += scnprintf(p, end - p, " src_divs=[");
70025f9dddbSEric Biggers 	p = generate_random_sgl_divisions(cfg->src_divs,
70125f9dddbSEric Biggers 					  ARRAY_SIZE(cfg->src_divs), p, end,
70225f9dddbSEric Biggers 					  (cfg->finalization_type !=
70325f9dddbSEric Biggers 					   FINALIZATION_TYPE_DIGEST));
70425f9dddbSEric Biggers 	p += scnprintf(p, end - p, "]");
70525f9dddbSEric Biggers 
70625f9dddbSEric Biggers 	if (!cfg->inplace && prandom_u32() % 2 == 0) {
70725f9dddbSEric Biggers 		p += scnprintf(p, end - p, " dst_divs=[");
70825f9dddbSEric Biggers 		p = generate_random_sgl_divisions(cfg->dst_divs,
70925f9dddbSEric Biggers 						  ARRAY_SIZE(cfg->dst_divs),
71025f9dddbSEric Biggers 						  p, end, false);
71125f9dddbSEric Biggers 		p += scnprintf(p, end - p, "]");
71225f9dddbSEric Biggers 	}
71325f9dddbSEric Biggers 
71425f9dddbSEric Biggers 	if (prandom_u32() % 2 == 0) {
71525f9dddbSEric Biggers 		cfg->iv_offset = 1 + (prandom_u32() % MAX_ALGAPI_ALIGNMASK);
71625f9dddbSEric Biggers 		p += scnprintf(p, end - p, " iv_offset=%u", cfg->iv_offset);
71725f9dddbSEric Biggers 	}
71825f9dddbSEric Biggers 
71925f9dddbSEric Biggers 	WARN_ON_ONCE(!valid_testvec_config(cfg));
72025f9dddbSEric Biggers }
72125f9dddbSEric Biggers #endif /* CONFIG_CRYPTO_MANAGER_EXTRA_TESTS */
72225f9dddbSEric Biggers 
723466d7b9fSKamil Konieczny static int ahash_guard_result(char *result, char c, int size)
724466d7b9fSKamil Konieczny {
725466d7b9fSKamil Konieczny 	int i;
726466d7b9fSKamil Konieczny 
727466d7b9fSKamil Konieczny 	for (i = 0; i < size; i++) {
728466d7b9fSKamil Konieczny 		if (result[i] != c)
729466d7b9fSKamil Konieczny 			return -EINVAL;
730466d7b9fSKamil Konieczny 	}
731466d7b9fSKamil Konieczny 
732466d7b9fSKamil Konieczny 	return 0;
733466d7b9fSKamil Konieczny }
734466d7b9fSKamil Konieczny 
735018ba95cSWang, Rui Y static int ahash_partial_update(struct ahash_request **preq,
736b13b1e0cSEric Biggers 	struct crypto_ahash *tfm, const struct hash_testvec *template,
737018ba95cSWang, Rui Y 	void *hash_buff, int k, int temp, struct scatterlist *sg,
7387f397136SGilad Ben-Yossef 	const char *algo, char *result, struct crypto_wait *wait)
739018ba95cSWang, Rui Y {
740018ba95cSWang, Rui Y 	char *state;
741018ba95cSWang, Rui Y 	struct ahash_request *req;
742018ba95cSWang, Rui Y 	int statesize, ret = -EINVAL;
743da1729ceSJoey Pabalinas 	static const unsigned char guard[] = { 0x00, 0xba, 0xad, 0x00 };
744466d7b9fSKamil Konieczny 	int digestsize = crypto_ahash_digestsize(tfm);
745018ba95cSWang, Rui Y 
746018ba95cSWang, Rui Y 	req = *preq;
747018ba95cSWang, Rui Y 	statesize = crypto_ahash_statesize(
748018ba95cSWang, Rui Y 			crypto_ahash_reqtfm(req));
7497bcb87bcSJan Stancek 	state = kmalloc(statesize + sizeof(guard), GFP_KERNEL);
750018ba95cSWang, Rui Y 	if (!state) {
751cf3f9609SGilad Ben-Yossef 		pr_err("alg: hash: Failed to alloc state for %s\n", algo);
752018ba95cSWang, Rui Y 		goto out_nostate;
753018ba95cSWang, Rui Y 	}
7547bcb87bcSJan Stancek 	memcpy(state + statesize, guard, sizeof(guard));
755466d7b9fSKamil Konieczny 	memset(result, 1, digestsize);
756018ba95cSWang, Rui Y 	ret = crypto_ahash_export(req, state);
7577bcb87bcSJan Stancek 	WARN_ON(memcmp(state + statesize, guard, sizeof(guard)));
758018ba95cSWang, Rui Y 	if (ret) {
759cf3f9609SGilad Ben-Yossef 		pr_err("alg: hash: Failed to export() for %s\n", algo);
760018ba95cSWang, Rui Y 		goto out;
761018ba95cSWang, Rui Y 	}
762466d7b9fSKamil Konieczny 	ret = ahash_guard_result(result, 1, digestsize);
763466d7b9fSKamil Konieczny 	if (ret) {
764466d7b9fSKamil Konieczny 		pr_err("alg: hash: Failed, export used req->result for %s\n",
765466d7b9fSKamil Konieczny 		       algo);
766466d7b9fSKamil Konieczny 		goto out;
767466d7b9fSKamil Konieczny 	}
768018ba95cSWang, Rui Y 	ahash_request_free(req);
769018ba95cSWang, Rui Y 	req = ahash_request_alloc(tfm, GFP_KERNEL);
770018ba95cSWang, Rui Y 	if (!req) {
771018ba95cSWang, Rui Y 		pr_err("alg: hash: Failed to alloc request for %s\n", algo);
772018ba95cSWang, Rui Y 		goto out_noreq;
773018ba95cSWang, Rui Y 	}
774018ba95cSWang, Rui Y 	ahash_request_set_callback(req,
775018ba95cSWang, Rui Y 		CRYPTO_TFM_REQ_MAY_BACKLOG,
7767f397136SGilad Ben-Yossef 		crypto_req_done, wait);
777018ba95cSWang, Rui Y 
778018ba95cSWang, Rui Y 	memcpy(hash_buff, template->plaintext + temp,
779018ba95cSWang, Rui Y 		template->tap[k]);
780018ba95cSWang, Rui Y 	sg_init_one(&sg[0], hash_buff, template->tap[k]);
781018ba95cSWang, Rui Y 	ahash_request_set_crypt(req, sg, result, template->tap[k]);
782018ba95cSWang, Rui Y 	ret = crypto_ahash_import(req, state);
783018ba95cSWang, Rui Y 	if (ret) {
784018ba95cSWang, Rui Y 		pr_err("alg: hash: Failed to import() for %s\n", algo);
785018ba95cSWang, Rui Y 		goto out;
786018ba95cSWang, Rui Y 	}
787466d7b9fSKamil Konieczny 	ret = ahash_guard_result(result, 1, digestsize);
788466d7b9fSKamil Konieczny 	if (ret) {
789466d7b9fSKamil Konieczny 		pr_err("alg: hash: Failed, import used req->result for %s\n",
790466d7b9fSKamil Konieczny 		       algo);
791466d7b9fSKamil Konieczny 		goto out;
792466d7b9fSKamil Konieczny 	}
7937f397136SGilad Ben-Yossef 	ret = crypto_wait_req(crypto_ahash_update(req), wait);
794018ba95cSWang, Rui Y 	if (ret)
795018ba95cSWang, Rui Y 		goto out;
796018ba95cSWang, Rui Y 	*preq = req;
797018ba95cSWang, Rui Y 	ret = 0;
798018ba95cSWang, Rui Y 	goto out_noreq;
799018ba95cSWang, Rui Y out:
800018ba95cSWang, Rui Y 	ahash_request_free(req);
801018ba95cSWang, Rui Y out_noreq:
802018ba95cSWang, Rui Y 	kfree(state);
803018ba95cSWang, Rui Y out_nostate:
804018ba95cSWang, Rui Y 	return ret;
805018ba95cSWang, Rui Y }
806018ba95cSWang, Rui Y 
80776715095SGilad Ben-Yossef enum hash_test {
80876715095SGilad Ben-Yossef 	HASH_TEST_DIGEST,
80976715095SGilad Ben-Yossef 	HASH_TEST_FINAL,
81076715095SGilad Ben-Yossef 	HASH_TEST_FINUP
81176715095SGilad Ben-Yossef };
81276715095SGilad Ben-Yossef 
813b13b1e0cSEric Biggers static int __test_hash(struct crypto_ahash *tfm,
814b13b1e0cSEric Biggers 		       const struct hash_testvec *template, unsigned int tcount,
81576715095SGilad Ben-Yossef 		       enum hash_test test_type, const int align_offset)
816da7f033dSHerbert Xu {
817da7f033dSHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm));
818e93acd6fSAndrew Lutomirski 	size_t digest_size = crypto_ahash_digestsize(tfm);
819da7f033dSHerbert Xu 	unsigned int i, j, k, temp;
820da7f033dSHerbert Xu 	struct scatterlist sg[8];
82129b77e5dSHoria Geanta 	char *result;
82229b77e5dSHoria Geanta 	char *key;
823da7f033dSHerbert Xu 	struct ahash_request *req;
8247f397136SGilad Ben-Yossef 	struct crypto_wait wait;
825da7f033dSHerbert Xu 	void *hash_buff;
826f8b0d4d0SHerbert Xu 	char *xbuf[XBUFSIZE];
827f8b0d4d0SHerbert Xu 	int ret = -ENOMEM;
828f8b0d4d0SHerbert Xu 
829e93acd6fSAndrew Lutomirski 	result = kmalloc(digest_size, GFP_KERNEL);
83029b77e5dSHoria Geanta 	if (!result)
83129b77e5dSHoria Geanta 		return ret;
83229b77e5dSHoria Geanta 	key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
83329b77e5dSHoria Geanta 	if (!key)
83429b77e5dSHoria Geanta 		goto out_nobuf;
835f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(xbuf))
836f8b0d4d0SHerbert Xu 		goto out_nobuf;
837da7f033dSHerbert Xu 
8387f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
839da7f033dSHerbert Xu 
840da7f033dSHerbert Xu 	req = ahash_request_alloc(tfm, GFP_KERNEL);
841da7f033dSHerbert Xu 	if (!req) {
842da7f033dSHerbert Xu 		printk(KERN_ERR "alg: hash: Failed to allocate request for "
843da7f033dSHerbert Xu 		       "%s\n", algo);
844da7f033dSHerbert Xu 		goto out_noreq;
845da7f033dSHerbert Xu 	}
846da7f033dSHerbert Xu 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
8477f397136SGilad Ben-Yossef 				   crypto_req_done, &wait);
848da7f033dSHerbert Xu 
849a0cfae59SHerbert Xu 	j = 0;
850da7f033dSHerbert Xu 	for (i = 0; i < tcount; i++) {
851a0cfae59SHerbert Xu 		if (template[i].np)
852a0cfae59SHerbert Xu 			continue;
853a0cfae59SHerbert Xu 
854da5ffe11SJussi Kivilinna 		ret = -EINVAL;
855da5ffe11SJussi Kivilinna 		if (WARN_ON(align_offset + template[i].psize > PAGE_SIZE))
856da5ffe11SJussi Kivilinna 			goto out;
857da5ffe11SJussi Kivilinna 
858a0cfae59SHerbert Xu 		j++;
859e93acd6fSAndrew Lutomirski 		memset(result, 0, digest_size);
860da7f033dSHerbert Xu 
861da7f033dSHerbert Xu 		hash_buff = xbuf[0];
862da5ffe11SJussi Kivilinna 		hash_buff += align_offset;
863da7f033dSHerbert Xu 
864da7f033dSHerbert Xu 		memcpy(hash_buff, template[i].plaintext, template[i].psize);
865da7f033dSHerbert Xu 		sg_init_one(&sg[0], hash_buff, template[i].psize);
866da7f033dSHerbert Xu 
867da7f033dSHerbert Xu 		if (template[i].ksize) {
868da7f033dSHerbert Xu 			crypto_ahash_clear_flags(tfm, ~0);
86929b77e5dSHoria Geanta 			if (template[i].ksize > MAX_KEYLEN) {
87029b77e5dSHoria Geanta 				pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
87129b77e5dSHoria Geanta 				       j, algo, template[i].ksize, MAX_KEYLEN);
87229b77e5dSHoria Geanta 				ret = -EINVAL;
87329b77e5dSHoria Geanta 				goto out;
87429b77e5dSHoria Geanta 			}
87529b77e5dSHoria Geanta 			memcpy(key, template[i].key, template[i].ksize);
87629b77e5dSHoria Geanta 			ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
877da7f033dSHerbert Xu 			if (ret) {
878da7f033dSHerbert Xu 				printk(KERN_ERR "alg: hash: setkey failed on "
879a0cfae59SHerbert Xu 				       "test %d for %s: ret=%d\n", j, algo,
880da7f033dSHerbert Xu 				       -ret);
881da7f033dSHerbert Xu 				goto out;
882da7f033dSHerbert Xu 			}
883da7f033dSHerbert Xu 		}
884da7f033dSHerbert Xu 
885da7f033dSHerbert Xu 		ahash_request_set_crypt(req, sg, result, template[i].psize);
88676715095SGilad Ben-Yossef 		switch (test_type) {
88776715095SGilad Ben-Yossef 		case HASH_TEST_DIGEST:
8887f397136SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
889a8f1a052SDavid S. Miller 			if (ret) {
890a8f1a052SDavid S. Miller 				pr_err("alg: hash: digest failed on test %d "
891a0cfae59SHerbert Xu 				       "for %s: ret=%d\n", j, algo, -ret);
892da7f033dSHerbert Xu 				goto out;
893da7f033dSHerbert Xu 			}
89476715095SGilad Ben-Yossef 			break;
89576715095SGilad Ben-Yossef 
89676715095SGilad Ben-Yossef 		case HASH_TEST_FINAL:
897466d7b9fSKamil Konieczny 			memset(result, 1, digest_size);
8987f397136SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_init(req), &wait);
899a8f1a052SDavid S. Miller 			if (ret) {
900cf3f9609SGilad Ben-Yossef 				pr_err("alg: hash: init failed on test %d "
901a8f1a052SDavid S. Miller 				       "for %s: ret=%d\n", j, algo, -ret);
902a8f1a052SDavid S. Miller 				goto out;
903a8f1a052SDavid S. Miller 			}
904466d7b9fSKamil Konieczny 			ret = ahash_guard_result(result, 1, digest_size);
905466d7b9fSKamil Konieczny 			if (ret) {
906466d7b9fSKamil Konieczny 				pr_err("alg: hash: init failed on test %d "
907466d7b9fSKamil Konieczny 				       "for %s: used req->result\n", j, algo);
908466d7b9fSKamil Konieczny 				goto out;
909466d7b9fSKamil Konieczny 			}
9107f397136SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_update(req), &wait);
911a8f1a052SDavid S. Miller 			if (ret) {
912cf3f9609SGilad Ben-Yossef 				pr_err("alg: hash: update failed on test %d "
913a8f1a052SDavid S. Miller 				       "for %s: ret=%d\n", j, algo, -ret);
914a8f1a052SDavid S. Miller 				goto out;
915a8f1a052SDavid S. Miller 			}
916466d7b9fSKamil Konieczny 			ret = ahash_guard_result(result, 1, digest_size);
917466d7b9fSKamil Konieczny 			if (ret) {
918466d7b9fSKamil Konieczny 				pr_err("alg: hash: update failed on test %d "
919466d7b9fSKamil Konieczny 				       "for %s: used req->result\n", j, algo);
920466d7b9fSKamil Konieczny 				goto out;
921466d7b9fSKamil Konieczny 			}
9227f397136SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_final(req), &wait);
923a8f1a052SDavid S. Miller 			if (ret) {
924cf3f9609SGilad Ben-Yossef 				pr_err("alg: hash: final failed on test %d "
925a8f1a052SDavid S. Miller 				       "for %s: ret=%d\n", j, algo, -ret);
926a8f1a052SDavid S. Miller 				goto out;
927a8f1a052SDavid S. Miller 			}
92876715095SGilad Ben-Yossef 			break;
92976715095SGilad Ben-Yossef 
93076715095SGilad Ben-Yossef 		case HASH_TEST_FINUP:
93176715095SGilad Ben-Yossef 			memset(result, 1, digest_size);
93276715095SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_init(req), &wait);
93376715095SGilad Ben-Yossef 			if (ret) {
93476715095SGilad Ben-Yossef 				pr_err("alg: hash: init failed on test %d "
93576715095SGilad Ben-Yossef 				       "for %s: ret=%d\n", j, algo, -ret);
93676715095SGilad Ben-Yossef 				goto out;
93776715095SGilad Ben-Yossef 			}
93876715095SGilad Ben-Yossef 			ret = ahash_guard_result(result, 1, digest_size);
93976715095SGilad Ben-Yossef 			if (ret) {
94076715095SGilad Ben-Yossef 				pr_err("alg: hash: init failed on test %d "
94176715095SGilad Ben-Yossef 				       "for %s: used req->result\n", j, algo);
94276715095SGilad Ben-Yossef 				goto out;
94376715095SGilad Ben-Yossef 			}
94476715095SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_finup(req), &wait);
94576715095SGilad Ben-Yossef 			if (ret) {
94676715095SGilad Ben-Yossef 				pr_err("alg: hash: final failed on test %d "
94776715095SGilad Ben-Yossef 				       "for %s: ret=%d\n", j, algo, -ret);
94876715095SGilad Ben-Yossef 				goto out;
94976715095SGilad Ben-Yossef 			}
95076715095SGilad Ben-Yossef 			break;
951a8f1a052SDavid S. Miller 		}
952da7f033dSHerbert Xu 
953da7f033dSHerbert Xu 		if (memcmp(result, template[i].digest,
954da7f033dSHerbert Xu 			   crypto_ahash_digestsize(tfm))) {
955da7f033dSHerbert Xu 			printk(KERN_ERR "alg: hash: Test %d failed for %s\n",
956a0cfae59SHerbert Xu 			       j, algo);
957da7f033dSHerbert Xu 			hexdump(result, crypto_ahash_digestsize(tfm));
958da7f033dSHerbert Xu 			ret = -EINVAL;
959da7f033dSHerbert Xu 			goto out;
960da7f033dSHerbert Xu 		}
961da7f033dSHerbert Xu 	}
962da7f033dSHerbert Xu 
96376715095SGilad Ben-Yossef 	if (test_type)
96476715095SGilad Ben-Yossef 		goto out;
96576715095SGilad Ben-Yossef 
966da7f033dSHerbert Xu 	j = 0;
967da7f033dSHerbert Xu 	for (i = 0; i < tcount; i++) {
968da5ffe11SJussi Kivilinna 		/* alignment tests are only done with continuous buffers */
969da5ffe11SJussi Kivilinna 		if (align_offset != 0)
970da5ffe11SJussi Kivilinna 			break;
971da5ffe11SJussi Kivilinna 
9725f2b424eSCristian Stoica 		if (!template[i].np)
9735f2b424eSCristian Stoica 			continue;
9745f2b424eSCristian Stoica 
975da7f033dSHerbert Xu 		j++;
976e93acd6fSAndrew Lutomirski 		memset(result, 0, digest_size);
977da7f033dSHerbert Xu 
978da7f033dSHerbert Xu 		temp = 0;
979da7f033dSHerbert Xu 		sg_init_table(sg, template[i].np);
980fd57f22aSHerbert Xu 		ret = -EINVAL;
981da7f033dSHerbert Xu 		for (k = 0; k < template[i].np; k++) {
982fd57f22aSHerbert Xu 			if (WARN_ON(offset_in_page(IDX[k]) +
983fd57f22aSHerbert Xu 				    template[i].tap[k] > PAGE_SIZE))
984fd57f22aSHerbert Xu 				goto out;
985da7f033dSHerbert Xu 			sg_set_buf(&sg[k],
986da7f033dSHerbert Xu 				   memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
987da7f033dSHerbert Xu 					  offset_in_page(IDX[k]),
988da7f033dSHerbert Xu 					  template[i].plaintext + temp,
989da7f033dSHerbert Xu 					  template[i].tap[k]),
990da7f033dSHerbert Xu 				   template[i].tap[k]);
991da7f033dSHerbert Xu 			temp += template[i].tap[k];
992da7f033dSHerbert Xu 		}
993da7f033dSHerbert Xu 
994da7f033dSHerbert Xu 		if (template[i].ksize) {
99529b77e5dSHoria Geanta 			if (template[i].ksize > MAX_KEYLEN) {
99629b77e5dSHoria Geanta 				pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
9975f2b424eSCristian Stoica 				       j, algo, template[i].ksize, MAX_KEYLEN);
99829b77e5dSHoria Geanta 				ret = -EINVAL;
99929b77e5dSHoria Geanta 				goto out;
100029b77e5dSHoria Geanta 			}
1001da7f033dSHerbert Xu 			crypto_ahash_clear_flags(tfm, ~0);
100229b77e5dSHoria Geanta 			memcpy(key, template[i].key, template[i].ksize);
10035f2b424eSCristian Stoica 			ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
1004da7f033dSHerbert Xu 
1005da7f033dSHerbert Xu 			if (ret) {
1006da7f033dSHerbert Xu 				printk(KERN_ERR "alg: hash: setkey "
1007da7f033dSHerbert Xu 				       "failed on chunking test %d "
10085f2b424eSCristian Stoica 				       "for %s: ret=%d\n", j, algo, -ret);
1009da7f033dSHerbert Xu 				goto out;
1010da7f033dSHerbert Xu 			}
1011da7f033dSHerbert Xu 		}
1012da7f033dSHerbert Xu 
10135f2b424eSCristian Stoica 		ahash_request_set_crypt(req, sg, result, template[i].psize);
10147f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
10157f397136SGilad Ben-Yossef 		if (ret) {
10167f397136SGilad Ben-Yossef 			pr_err("alg: hash: digest failed on chunking test %d for %s: ret=%d\n",
10177f397136SGilad Ben-Yossef 			       j, algo, -ret);
1018da7f033dSHerbert Xu 			goto out;
1019da7f033dSHerbert Xu 		}
1020da7f033dSHerbert Xu 
1021da7f033dSHerbert Xu 		if (memcmp(result, template[i].digest,
1022da7f033dSHerbert Xu 			   crypto_ahash_digestsize(tfm))) {
1023da7f033dSHerbert Xu 			printk(KERN_ERR "alg: hash: Chunking test %d "
1024da7f033dSHerbert Xu 			       "failed for %s\n", j, algo);
1025da7f033dSHerbert Xu 			hexdump(result, crypto_ahash_digestsize(tfm));
1026da7f033dSHerbert Xu 			ret = -EINVAL;
1027da7f033dSHerbert Xu 			goto out;
1028da7f033dSHerbert Xu 		}
1029da7f033dSHerbert Xu 	}
1030da7f033dSHerbert Xu 
1031018ba95cSWang, Rui Y 	/* partial update exercise */
1032018ba95cSWang, Rui Y 	j = 0;
1033018ba95cSWang, Rui Y 	for (i = 0; i < tcount; i++) {
1034018ba95cSWang, Rui Y 		/* alignment tests are only done with continuous buffers */
1035018ba95cSWang, Rui Y 		if (align_offset != 0)
1036018ba95cSWang, Rui Y 			break;
1037018ba95cSWang, Rui Y 
1038018ba95cSWang, Rui Y 		if (template[i].np < 2)
1039018ba95cSWang, Rui Y 			continue;
1040018ba95cSWang, Rui Y 
1041018ba95cSWang, Rui Y 		j++;
1042e93acd6fSAndrew Lutomirski 		memset(result, 0, digest_size);
1043018ba95cSWang, Rui Y 
1044018ba95cSWang, Rui Y 		ret = -EINVAL;
1045018ba95cSWang, Rui Y 		hash_buff = xbuf[0];
1046018ba95cSWang, Rui Y 		memcpy(hash_buff, template[i].plaintext,
1047018ba95cSWang, Rui Y 			template[i].tap[0]);
1048018ba95cSWang, Rui Y 		sg_init_one(&sg[0], hash_buff, template[i].tap[0]);
1049018ba95cSWang, Rui Y 
1050018ba95cSWang, Rui Y 		if (template[i].ksize) {
1051018ba95cSWang, Rui Y 			crypto_ahash_clear_flags(tfm, ~0);
1052018ba95cSWang, Rui Y 			if (template[i].ksize > MAX_KEYLEN) {
1053018ba95cSWang, Rui Y 				pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
1054018ba95cSWang, Rui Y 					j, algo, template[i].ksize, MAX_KEYLEN);
1055018ba95cSWang, Rui Y 				ret = -EINVAL;
1056018ba95cSWang, Rui Y 				goto out;
1057018ba95cSWang, Rui Y 			}
1058018ba95cSWang, Rui Y 			memcpy(key, template[i].key, template[i].ksize);
1059018ba95cSWang, Rui Y 			ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
1060018ba95cSWang, Rui Y 			if (ret) {
1061018ba95cSWang, Rui Y 				pr_err("alg: hash: setkey failed on test %d for %s: ret=%d\n",
1062018ba95cSWang, Rui Y 					j, algo, -ret);
1063018ba95cSWang, Rui Y 				goto out;
1064018ba95cSWang, Rui Y 			}
1065018ba95cSWang, Rui Y 		}
1066018ba95cSWang, Rui Y 
1067018ba95cSWang, Rui Y 		ahash_request_set_crypt(req, sg, result, template[i].tap[0]);
10687f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_ahash_init(req), &wait);
1069018ba95cSWang, Rui Y 		if (ret) {
1070cf3f9609SGilad Ben-Yossef 			pr_err("alg: hash: init failed on test %d for %s: ret=%d\n",
1071018ba95cSWang, Rui Y 				j, algo, -ret);
1072018ba95cSWang, Rui Y 			goto out;
1073018ba95cSWang, Rui Y 		}
10747f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_ahash_update(req), &wait);
1075018ba95cSWang, Rui Y 		if (ret) {
1076cf3f9609SGilad Ben-Yossef 			pr_err("alg: hash: update failed on test %d for %s: ret=%d\n",
1077018ba95cSWang, Rui Y 				j, algo, -ret);
1078018ba95cSWang, Rui Y 			goto out;
1079018ba95cSWang, Rui Y 		}
1080018ba95cSWang, Rui Y 
1081018ba95cSWang, Rui Y 		temp = template[i].tap[0];
1082018ba95cSWang, Rui Y 		for (k = 1; k < template[i].np; k++) {
1083018ba95cSWang, Rui Y 			ret = ahash_partial_update(&req, tfm, &template[i],
1084018ba95cSWang, Rui Y 				hash_buff, k, temp, &sg[0], algo, result,
10857f397136SGilad Ben-Yossef 				&wait);
1086018ba95cSWang, Rui Y 			if (ret) {
1087cf3f9609SGilad Ben-Yossef 				pr_err("alg: hash: partial update failed on test %d for %s: ret=%d\n",
1088018ba95cSWang, Rui Y 					j, algo, -ret);
1089018ba95cSWang, Rui Y 				goto out_noreq;
1090018ba95cSWang, Rui Y 			}
1091018ba95cSWang, Rui Y 			temp += template[i].tap[k];
1092018ba95cSWang, Rui Y 		}
10937f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_ahash_final(req), &wait);
1094018ba95cSWang, Rui Y 		if (ret) {
1095cf3f9609SGilad Ben-Yossef 			pr_err("alg: hash: final failed on test %d for %s: ret=%d\n",
1096018ba95cSWang, Rui Y 				j, algo, -ret);
1097018ba95cSWang, Rui Y 			goto out;
1098018ba95cSWang, Rui Y 		}
1099018ba95cSWang, Rui Y 		if (memcmp(result, template[i].digest,
1100018ba95cSWang, Rui Y 			   crypto_ahash_digestsize(tfm))) {
1101018ba95cSWang, Rui Y 			pr_err("alg: hash: Partial Test %d failed for %s\n",
1102018ba95cSWang, Rui Y 			       j, algo);
1103018ba95cSWang, Rui Y 			hexdump(result, crypto_ahash_digestsize(tfm));
1104018ba95cSWang, Rui Y 			ret = -EINVAL;
1105018ba95cSWang, Rui Y 			goto out;
1106018ba95cSWang, Rui Y 		}
1107018ba95cSWang, Rui Y 	}
1108018ba95cSWang, Rui Y 
1109da7f033dSHerbert Xu 	ret = 0;
1110da7f033dSHerbert Xu 
1111da7f033dSHerbert Xu out:
1112da7f033dSHerbert Xu 	ahash_request_free(req);
1113da7f033dSHerbert Xu out_noreq:
1114f8b0d4d0SHerbert Xu 	testmgr_free_buf(xbuf);
1115f8b0d4d0SHerbert Xu out_nobuf:
111629b77e5dSHoria Geanta 	kfree(key);
111729b77e5dSHoria Geanta 	kfree(result);
1118da7f033dSHerbert Xu 	return ret;
1119da7f033dSHerbert Xu }
1120da7f033dSHerbert Xu 
1121b13b1e0cSEric Biggers static int test_hash(struct crypto_ahash *tfm,
1122b13b1e0cSEric Biggers 		     const struct hash_testvec *template,
112376715095SGilad Ben-Yossef 		     unsigned int tcount, enum hash_test test_type)
1124da5ffe11SJussi Kivilinna {
1125da5ffe11SJussi Kivilinna 	unsigned int alignmask;
1126da5ffe11SJussi Kivilinna 	int ret;
1127da5ffe11SJussi Kivilinna 
112876715095SGilad Ben-Yossef 	ret = __test_hash(tfm, template, tcount, test_type, 0);
1129da5ffe11SJussi Kivilinna 	if (ret)
1130da5ffe11SJussi Kivilinna 		return ret;
1131da5ffe11SJussi Kivilinna 
1132da5ffe11SJussi Kivilinna 	/* test unaligned buffers, check with one byte offset */
113376715095SGilad Ben-Yossef 	ret = __test_hash(tfm, template, tcount, test_type, 1);
1134da5ffe11SJussi Kivilinna 	if (ret)
1135da5ffe11SJussi Kivilinna 		return ret;
1136da5ffe11SJussi Kivilinna 
1137da5ffe11SJussi Kivilinna 	alignmask = crypto_tfm_alg_alignmask(&tfm->base);
1138da5ffe11SJussi Kivilinna 	if (alignmask) {
1139da5ffe11SJussi Kivilinna 		/* Check if alignment mask for tfm is correctly set. */
114076715095SGilad Ben-Yossef 		ret = __test_hash(tfm, template, tcount, test_type,
1141da5ffe11SJussi Kivilinna 				  alignmask + 1);
1142da5ffe11SJussi Kivilinna 		if (ret)
1143da5ffe11SJussi Kivilinna 			return ret;
1144da5ffe11SJussi Kivilinna 	}
1145da5ffe11SJussi Kivilinna 
1146da5ffe11SJussi Kivilinna 	return 0;
1147da5ffe11SJussi Kivilinna }
1148da5ffe11SJussi Kivilinna 
1149d8a32ac2SJussi Kivilinna static int __test_aead(struct crypto_aead *tfm, int enc,
1150b13b1e0cSEric Biggers 		       const struct aead_testvec *template, unsigned int tcount,
115158dcf548SJussi Kivilinna 		       const bool diff_dst, const int align_offset)
1152da7f033dSHerbert Xu {
1153da7f033dSHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm));
1154da7f033dSHerbert Xu 	unsigned int i, j, k, n, temp;
1155f8b0d4d0SHerbert Xu 	int ret = -ENOMEM;
1156da7f033dSHerbert Xu 	char *q;
1157da7f033dSHerbert Xu 	char *key;
1158da7f033dSHerbert Xu 	struct aead_request *req;
1159d8a32ac2SJussi Kivilinna 	struct scatterlist *sg;
1160d8a32ac2SJussi Kivilinna 	struct scatterlist *sgout;
1161d8a32ac2SJussi Kivilinna 	const char *e, *d;
11627f397136SGilad Ben-Yossef 	struct crypto_wait wait;
1163424a5da6SCristian Stoica 	unsigned int authsize, iv_len;
11649bac019dSTadeusz Struk 	char *iv;
1165f8b0d4d0SHerbert Xu 	char *xbuf[XBUFSIZE];
1166d8a32ac2SJussi Kivilinna 	char *xoutbuf[XBUFSIZE];
1167f8b0d4d0SHerbert Xu 	char *axbuf[XBUFSIZE];
1168f8b0d4d0SHerbert Xu 
11699bac019dSTadeusz Struk 	iv = kzalloc(MAX_IVLEN, GFP_KERNEL);
11709bac019dSTadeusz Struk 	if (!iv)
11719bac019dSTadeusz Struk 		return ret;
117229b77e5dSHoria Geanta 	key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
117329b77e5dSHoria Geanta 	if (!key)
117429b77e5dSHoria Geanta 		goto out_noxbuf;
1175f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(xbuf))
1176f8b0d4d0SHerbert Xu 		goto out_noxbuf;
1177f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(axbuf))
1178f8b0d4d0SHerbert Xu 		goto out_noaxbuf;
1179d8a32ac2SJussi Kivilinna 	if (diff_dst && testmgr_alloc_buf(xoutbuf))
1180d8a32ac2SJussi Kivilinna 		goto out_nooutbuf;
1181d8a32ac2SJussi Kivilinna 
1182d8a32ac2SJussi Kivilinna 	/* avoid "the frame size is larger than 1024 bytes" compiler warning */
11836da2ec56SKees Cook 	sg = kmalloc(array3_size(sizeof(*sg), 8, (diff_dst ? 4 : 2)),
11846da2ec56SKees Cook 		     GFP_KERNEL);
1185d8a32ac2SJussi Kivilinna 	if (!sg)
1186d8a32ac2SJussi Kivilinna 		goto out_nosg;
11878a525fcdSHerbert Xu 	sgout = &sg[16];
1188d8a32ac2SJussi Kivilinna 
1189d8a32ac2SJussi Kivilinna 	if (diff_dst)
1190d8a32ac2SJussi Kivilinna 		d = "-ddst";
1191d8a32ac2SJussi Kivilinna 	else
1192d8a32ac2SJussi Kivilinna 		d = "";
1193d8a32ac2SJussi Kivilinna 
1194da7f033dSHerbert Xu 	if (enc == ENCRYPT)
1195da7f033dSHerbert Xu 		e = "encryption";
1196da7f033dSHerbert Xu 	else
1197da7f033dSHerbert Xu 		e = "decryption";
1198da7f033dSHerbert Xu 
11997f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
1200da7f033dSHerbert Xu 
1201da7f033dSHerbert Xu 	req = aead_request_alloc(tfm, GFP_KERNEL);
1202da7f033dSHerbert Xu 	if (!req) {
1203d8a32ac2SJussi Kivilinna 		pr_err("alg: aead%s: Failed to allocate request for %s\n",
1204d8a32ac2SJussi Kivilinna 		       d, algo);
1205da7f033dSHerbert Xu 		goto out;
1206da7f033dSHerbert Xu 	}
1207da7f033dSHerbert Xu 
1208da7f033dSHerbert Xu 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
12097f397136SGilad Ben-Yossef 				  crypto_req_done, &wait);
1210da7f033dSHerbert Xu 
1211abfa7f43SJerome Marchand 	iv_len = crypto_aead_ivsize(tfm);
1212abfa7f43SJerome Marchand 
1213da7f033dSHerbert Xu 	for (i = 0, j = 0; i < tcount; i++) {
1214a0d608eeSEric Biggers 		const char *input, *expected_output;
1215a0d608eeSEric Biggers 		unsigned int inlen, outlen;
1216a0d608eeSEric Biggers 		char *inbuf, *outbuf, *assocbuf;
1217a0d608eeSEric Biggers 
121805b1d338SCristian Stoica 		if (template[i].np)
121905b1d338SCristian Stoica 			continue;
1220a0d608eeSEric Biggers 		if (enc) {
1221a0d608eeSEric Biggers 			if (template[i].novrfy)
12225bc3de58SEric Biggers 				continue;
1223a0d608eeSEric Biggers 			input = template[i].ptext;
1224a0d608eeSEric Biggers 			inlen = template[i].plen;
1225a0d608eeSEric Biggers 			expected_output = template[i].ctext;
1226a0d608eeSEric Biggers 			outlen = template[i].clen;
1227a0d608eeSEric Biggers 		} else {
1228a0d608eeSEric Biggers 			input = template[i].ctext;
1229a0d608eeSEric Biggers 			inlen = template[i].clen;
1230a0d608eeSEric Biggers 			expected_output = template[i].ptext;
1231a0d608eeSEric Biggers 			outlen = template[i].plen;
1232a0d608eeSEric Biggers 		}
123305b1d338SCristian Stoica 
1234da7f033dSHerbert Xu 		j++;
1235da7f033dSHerbert Xu 
123658dcf548SJussi Kivilinna 		/* some templates have no input data but they will
1237da7f033dSHerbert Xu 		 * touch input
1238da7f033dSHerbert Xu 		 */
1239a0d608eeSEric Biggers 		inbuf = xbuf[0] + align_offset;
1240a0d608eeSEric Biggers 		assocbuf = axbuf[0];
1241da7f033dSHerbert Xu 
1242fd57f22aSHerbert Xu 		ret = -EINVAL;
1243a0d608eeSEric Biggers 		if (WARN_ON(align_offset + template[i].clen > PAGE_SIZE ||
1244a0d608eeSEric Biggers 			    template[i].alen > PAGE_SIZE))
1245fd57f22aSHerbert Xu 			goto out;
1246fd57f22aSHerbert Xu 
1247a0d608eeSEric Biggers 		memcpy(inbuf, input, inlen);
1248a0d608eeSEric Biggers 		memcpy(assocbuf, template[i].assoc, template[i].alen);
1249da7f033dSHerbert Xu 		if (template[i].iv)
1250424a5da6SCristian Stoica 			memcpy(iv, template[i].iv, iv_len);
1251da7f033dSHerbert Xu 		else
1252424a5da6SCristian Stoica 			memset(iv, 0, iv_len);
1253da7f033dSHerbert Xu 
1254da7f033dSHerbert Xu 		crypto_aead_clear_flags(tfm, ~0);
1255da7f033dSHerbert Xu 		if (template[i].wk)
1256231baecdSEric Biggers 			crypto_aead_set_flags(tfm,
1257231baecdSEric Biggers 					      CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
1258da7f033dSHerbert Xu 
125929b77e5dSHoria Geanta 		if (template[i].klen > MAX_KEYLEN) {
126029b77e5dSHoria Geanta 			pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
126129b77e5dSHoria Geanta 			       d, j, algo, template[i].klen,
126229b77e5dSHoria Geanta 			       MAX_KEYLEN);
126329b77e5dSHoria Geanta 			ret = -EINVAL;
126429b77e5dSHoria Geanta 			goto out;
126529b77e5dSHoria Geanta 		}
126629b77e5dSHoria Geanta 		memcpy(key, template[i].key, template[i].klen);
1267da7f033dSHerbert Xu 
126805b1d338SCristian Stoica 		ret = crypto_aead_setkey(tfm, key, template[i].klen);
12690fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
1270d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: setkey failed on test %d for %s: flags=%x\n",
1271d8a32ac2SJussi Kivilinna 			       d, j, algo, crypto_aead_get_flags(tfm));
1272da7f033dSHerbert Xu 			goto out;
1273da7f033dSHerbert Xu 		} else if (ret)
1274da7f033dSHerbert Xu 			continue;
1275da7f033dSHerbert Xu 
1276a0d608eeSEric Biggers 		authsize = template[i].clen - template[i].plen;
1277da7f033dSHerbert Xu 		ret = crypto_aead_setauthsize(tfm, authsize);
1278da7f033dSHerbert Xu 		if (ret) {
1279d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: Failed to set authsize to %u on test %d for %s\n",
1280d8a32ac2SJussi Kivilinna 			       d, authsize, j, algo);
1281da7f033dSHerbert Xu 			goto out;
1282da7f033dSHerbert Xu 		}
1283da7f033dSHerbert Xu 
12848a525fcdSHerbert Xu 		k = !!template[i].alen;
12858a525fcdSHerbert Xu 		sg_init_table(sg, k + 1);
1286a0d608eeSEric Biggers 		sg_set_buf(&sg[0], assocbuf, template[i].alen);
1287a0d608eeSEric Biggers 		sg_set_buf(&sg[k], inbuf, template[i].clen);
1288a0d608eeSEric Biggers 		outbuf = inbuf;
1289d8a32ac2SJussi Kivilinna 
12908a525fcdSHerbert Xu 		if (diff_dst) {
12918a525fcdSHerbert Xu 			sg_init_table(sgout, k + 1);
1292a0d608eeSEric Biggers 			sg_set_buf(&sgout[0], assocbuf, template[i].alen);
12938a525fcdSHerbert Xu 
1294a0d608eeSEric Biggers 			outbuf = xoutbuf[0] + align_offset;
1295a0d608eeSEric Biggers 			sg_set_buf(&sgout[k], outbuf, template[i].clen);
12968a525fcdSHerbert Xu 		}
1297da7f033dSHerbert Xu 
1298a0d608eeSEric Biggers 		aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg, inlen,
1299a0d608eeSEric Biggers 				       iv);
1300da7f033dSHerbert Xu 
13018a525fcdSHerbert Xu 		aead_request_set_ad(req, template[i].alen);
1302da7f033dSHerbert Xu 
13037f397136SGilad Ben-Yossef 		ret = crypto_wait_req(enc ? crypto_aead_encrypt(req)
13047f397136SGilad Ben-Yossef 				      : crypto_aead_decrypt(req), &wait);
1305da7f033dSHerbert Xu 
1306da7f033dSHerbert Xu 		switch (ret) {
1307da7f033dSHerbert Xu 		case 0:
1308e44a1b44SJarod Wilson 			if (template[i].novrfy) {
1309e44a1b44SJarod Wilson 				/* verification was supposed to fail */
1310d8a32ac2SJussi Kivilinna 				pr_err("alg: aead%s: %s failed on test %d for %s: ret was 0, expected -EBADMSG\n",
1311d8a32ac2SJussi Kivilinna 				       d, e, j, algo);
1312e44a1b44SJarod Wilson 				/* so really, we got a bad message */
1313e44a1b44SJarod Wilson 				ret = -EBADMSG;
1314e44a1b44SJarod Wilson 				goto out;
1315e44a1b44SJarod Wilson 			}
1316da7f033dSHerbert Xu 			break;
1317e44a1b44SJarod Wilson 		case -EBADMSG:
1318e44a1b44SJarod Wilson 			if (template[i].novrfy)
1319e44a1b44SJarod Wilson 				/* verification failure was expected */
1320e44a1b44SJarod Wilson 				continue;
1321da7f033dSHerbert Xu 			/* fall through */
1322da7f033dSHerbert Xu 		default:
1323d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: %s failed on test %d for %s: ret=%d\n",
1324d8a32ac2SJussi Kivilinna 			       d, e, j, algo, -ret);
1325da7f033dSHerbert Xu 			goto out;
1326da7f033dSHerbert Xu 		}
1327da7f033dSHerbert Xu 
1328a0d608eeSEric Biggers 		if (memcmp(outbuf, expected_output, outlen)) {
1329d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: Test %d failed on %s for %s\n",
1330d8a32ac2SJussi Kivilinna 			       d, j, e, algo);
1331a0d608eeSEric Biggers 			hexdump(outbuf, outlen);
1332da7f033dSHerbert Xu 			ret = -EINVAL;
1333da7f033dSHerbert Xu 			goto out;
1334da7f033dSHerbert Xu 		}
1335da7f033dSHerbert Xu 	}
1336da7f033dSHerbert Xu 
1337da7f033dSHerbert Xu 	for (i = 0, j = 0; i < tcount; i++) {
1338a0d608eeSEric Biggers 		const char *input, *expected_output;
1339a0d608eeSEric Biggers 		unsigned int inlen, outlen;
1340a0d608eeSEric Biggers 
134158dcf548SJussi Kivilinna 		/* alignment tests are only done with continuous buffers */
134258dcf548SJussi Kivilinna 		if (align_offset != 0)
134358dcf548SJussi Kivilinna 			break;
134458dcf548SJussi Kivilinna 
134505b1d338SCristian Stoica 		if (!template[i].np)
134605b1d338SCristian Stoica 			continue;
134705b1d338SCristian Stoica 
1348a0d608eeSEric Biggers 		if (enc) {
1349a0d608eeSEric Biggers 			if (template[i].novrfy)
13505bc3de58SEric Biggers 				continue;
1351a0d608eeSEric Biggers 			input = template[i].ptext;
1352a0d608eeSEric Biggers 			inlen = template[i].plen;
1353a0d608eeSEric Biggers 			expected_output = template[i].ctext;
1354a0d608eeSEric Biggers 			outlen = template[i].clen;
1355a0d608eeSEric Biggers 		} else {
1356a0d608eeSEric Biggers 			input = template[i].ctext;
1357a0d608eeSEric Biggers 			inlen = template[i].clen;
1358a0d608eeSEric Biggers 			expected_output = template[i].ptext;
1359a0d608eeSEric Biggers 			outlen = template[i].plen;
1360a0d608eeSEric Biggers 		}
13615bc3de58SEric Biggers 
1362da7f033dSHerbert Xu 		j++;
1363da7f033dSHerbert Xu 
1364da7f033dSHerbert Xu 		if (template[i].iv)
1365abfa7f43SJerome Marchand 			memcpy(iv, template[i].iv, iv_len);
1366da7f033dSHerbert Xu 		else
1367da7f033dSHerbert Xu 			memset(iv, 0, MAX_IVLEN);
1368da7f033dSHerbert Xu 
1369da7f033dSHerbert Xu 		crypto_aead_clear_flags(tfm, ~0);
1370da7f033dSHerbert Xu 		if (template[i].wk)
1371231baecdSEric Biggers 			crypto_aead_set_flags(tfm,
1372231baecdSEric Biggers 					      CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
137329b77e5dSHoria Geanta 		if (template[i].klen > MAX_KEYLEN) {
137429b77e5dSHoria Geanta 			pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
137505b1d338SCristian Stoica 			       d, j, algo, template[i].klen, MAX_KEYLEN);
137629b77e5dSHoria Geanta 			ret = -EINVAL;
137729b77e5dSHoria Geanta 			goto out;
137829b77e5dSHoria Geanta 		}
137929b77e5dSHoria Geanta 		memcpy(key, template[i].key, template[i].klen);
1380da7f033dSHerbert Xu 
1381da7f033dSHerbert Xu 		ret = crypto_aead_setkey(tfm, key, template[i].klen);
13820fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
1383d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: setkey failed on chunk test %d for %s: flags=%x\n",
1384d8a32ac2SJussi Kivilinna 			       d, j, algo, crypto_aead_get_flags(tfm));
1385da7f033dSHerbert Xu 			goto out;
1386da7f033dSHerbert Xu 		} else if (ret)
1387da7f033dSHerbert Xu 			continue;
1388da7f033dSHerbert Xu 
1389a0d608eeSEric Biggers 		authsize = template[i].clen - template[i].plen;
1390da7f033dSHerbert Xu 
1391da7f033dSHerbert Xu 		ret = -EINVAL;
13928a525fcdSHerbert Xu 		sg_init_table(sg, template[i].anp + template[i].np);
1393d8a32ac2SJussi Kivilinna 		if (diff_dst)
13948a525fcdSHerbert Xu 			sg_init_table(sgout, template[i].anp + template[i].np);
13958a525fcdSHerbert Xu 
13968a525fcdSHerbert Xu 		ret = -EINVAL;
13978a525fcdSHerbert Xu 		for (k = 0, temp = 0; k < template[i].anp; k++) {
13988a525fcdSHerbert Xu 			if (WARN_ON(offset_in_page(IDX[k]) +
13998a525fcdSHerbert Xu 				    template[i].atap[k] > PAGE_SIZE))
14008a525fcdSHerbert Xu 				goto out;
14018a525fcdSHerbert Xu 			sg_set_buf(&sg[k],
14028a525fcdSHerbert Xu 				   memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
14038a525fcdSHerbert Xu 					  offset_in_page(IDX[k]),
14048a525fcdSHerbert Xu 					  template[i].assoc + temp,
14058a525fcdSHerbert Xu 					  template[i].atap[k]),
14068a525fcdSHerbert Xu 				   template[i].atap[k]);
14078a525fcdSHerbert Xu 			if (diff_dst)
14088a525fcdSHerbert Xu 				sg_set_buf(&sgout[k],
14098a525fcdSHerbert Xu 					   axbuf[IDX[k] >> PAGE_SHIFT] +
14108a525fcdSHerbert Xu 					   offset_in_page(IDX[k]),
14118a525fcdSHerbert Xu 					   template[i].atap[k]);
14128a525fcdSHerbert Xu 			temp += template[i].atap[k];
14138a525fcdSHerbert Xu 		}
14148a525fcdSHerbert Xu 
1415da7f033dSHerbert Xu 		for (k = 0, temp = 0; k < template[i].np; k++) {
1416a0d608eeSEric Biggers 			n = template[i].tap[k];
1417a0d608eeSEric Biggers 			if (k == template[i].np - 1 && !enc)
1418a0d608eeSEric Biggers 				n += authsize;
1419a0d608eeSEric Biggers 
1420a0d608eeSEric Biggers 			if (WARN_ON(offset_in_page(IDX[k]) + n > PAGE_SIZE))
1421da7f033dSHerbert Xu 				goto out;
1422da7f033dSHerbert Xu 
142305b1d338SCristian Stoica 			q = xbuf[IDX[k] >> PAGE_SHIFT] + offset_in_page(IDX[k]);
1424a0d608eeSEric Biggers 			memcpy(q, input + temp, n);
1425a0d608eeSEric Biggers 			sg_set_buf(&sg[template[i].anp + k], q, n);
1426d8a32ac2SJussi Kivilinna 
1427d8a32ac2SJussi Kivilinna 			if (diff_dst) {
1428d8a32ac2SJussi Kivilinna 				q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
1429d8a32ac2SJussi Kivilinna 				    offset_in_page(IDX[k]);
1430d8a32ac2SJussi Kivilinna 
1431a0d608eeSEric Biggers 				memset(q, 0, n);
1432d8a32ac2SJussi Kivilinna 
1433a0d608eeSEric Biggers 				sg_set_buf(&sgout[template[i].anp + k], q, n);
1434d8a32ac2SJussi Kivilinna 			}
1435d8a32ac2SJussi Kivilinna 
14368ec25c51SHoria Geanta 			if (k == template[i].np - 1 && enc)
14378ec25c51SHoria Geanta 				n += authsize;
14388ec25c51SHoria Geanta 			if (offset_in_page(q) + n < PAGE_SIZE)
14398ec25c51SHoria Geanta 				q[n] = 0;
14408ec25c51SHoria Geanta 
1441a0d608eeSEric Biggers 			temp += n;
1442da7f033dSHerbert Xu 		}
1443da7f033dSHerbert Xu 
1444da7f033dSHerbert Xu 		ret = crypto_aead_setauthsize(tfm, authsize);
1445da7f033dSHerbert Xu 		if (ret) {
1446d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: Failed to set authsize to %u on chunk test %d for %s\n",
1447d8a32ac2SJussi Kivilinna 			       d, authsize, j, algo);
1448da7f033dSHerbert Xu 			goto out;
1449da7f033dSHerbert Xu 		}
1450da7f033dSHerbert Xu 
1451da7f033dSHerbert Xu 		if (enc) {
14528a525fcdSHerbert Xu 			if (WARN_ON(sg[template[i].anp + k - 1].offset +
14538a525fcdSHerbert Xu 				    sg[template[i].anp + k - 1].length +
14548a525fcdSHerbert Xu 				    authsize > PAGE_SIZE)) {
1455da7f033dSHerbert Xu 				ret = -EINVAL;
1456da7f033dSHerbert Xu 				goto out;
1457da7f033dSHerbert Xu 			}
1458da7f033dSHerbert Xu 
1459d8a32ac2SJussi Kivilinna 			if (diff_dst)
14608a525fcdSHerbert Xu 				sgout[template[i].anp + k - 1].length +=
14618a525fcdSHerbert Xu 					authsize;
14628a525fcdSHerbert Xu 			sg[template[i].anp + k - 1].length += authsize;
1463da7f033dSHerbert Xu 		}
1464da7f033dSHerbert Xu 
1465d8a32ac2SJussi Kivilinna 		aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
1466a0d608eeSEric Biggers 				       inlen, iv);
1467da7f033dSHerbert Xu 
14688a525fcdSHerbert Xu 		aead_request_set_ad(req, template[i].alen);
1469da7f033dSHerbert Xu 
14707f397136SGilad Ben-Yossef 		ret = crypto_wait_req(enc ? crypto_aead_encrypt(req)
14717f397136SGilad Ben-Yossef 				      : crypto_aead_decrypt(req), &wait);
1472da7f033dSHerbert Xu 
1473da7f033dSHerbert Xu 		switch (ret) {
1474da7f033dSHerbert Xu 		case 0:
1475e44a1b44SJarod Wilson 			if (template[i].novrfy) {
1476e44a1b44SJarod Wilson 				/* verification was supposed to fail */
1477d8a32ac2SJussi Kivilinna 				pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret was 0, expected -EBADMSG\n",
1478d8a32ac2SJussi Kivilinna 				       d, e, j, algo);
1479e44a1b44SJarod Wilson 				/* so really, we got a bad message */
1480e44a1b44SJarod Wilson 				ret = -EBADMSG;
1481e44a1b44SJarod Wilson 				goto out;
1482e44a1b44SJarod Wilson 			}
1483da7f033dSHerbert Xu 			break;
1484e44a1b44SJarod Wilson 		case -EBADMSG:
1485e44a1b44SJarod Wilson 			if (template[i].novrfy)
1486e44a1b44SJarod Wilson 				/* verification failure was expected */
1487e44a1b44SJarod Wilson 				continue;
1488da7f033dSHerbert Xu 			/* fall through */
1489da7f033dSHerbert Xu 		default:
1490d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret=%d\n",
1491d8a32ac2SJussi Kivilinna 			       d, e, j, algo, -ret);
1492da7f033dSHerbert Xu 			goto out;
1493da7f033dSHerbert Xu 		}
1494da7f033dSHerbert Xu 
1495da7f033dSHerbert Xu 		ret = -EINVAL;
1496da7f033dSHerbert Xu 		for (k = 0, temp = 0; k < template[i].np; k++) {
1497d8a32ac2SJussi Kivilinna 			if (diff_dst)
1498d8a32ac2SJussi Kivilinna 				q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
1499d8a32ac2SJussi Kivilinna 				    offset_in_page(IDX[k]);
1500d8a32ac2SJussi Kivilinna 			else
1501da7f033dSHerbert Xu 				q = xbuf[IDX[k] >> PAGE_SHIFT] +
1502da7f033dSHerbert Xu 				    offset_in_page(IDX[k]);
1503da7f033dSHerbert Xu 
1504da7f033dSHerbert Xu 			n = template[i].tap[k];
1505a0d608eeSEric Biggers 			if (k == template[i].np - 1 && enc)
1506a0d608eeSEric Biggers 				n += authsize;
1507da7f033dSHerbert Xu 
1508a0d608eeSEric Biggers 			if (memcmp(q, expected_output + temp, n)) {
1509d8a32ac2SJussi Kivilinna 				pr_err("alg: aead%s: Chunk test %d failed on %s at page %u for %s\n",
1510d8a32ac2SJussi Kivilinna 				       d, j, e, k, algo);
1511da7f033dSHerbert Xu 				hexdump(q, n);
1512da7f033dSHerbert Xu 				goto out;
1513da7f033dSHerbert Xu 			}
1514da7f033dSHerbert Xu 
1515da7f033dSHerbert Xu 			q += n;
1516da7f033dSHerbert Xu 			if (k == template[i].np - 1 && !enc) {
1517a0d608eeSEric Biggers 				if (!diff_dst && memcmp(q, input + temp + n,
1518a0d608eeSEric Biggers 							authsize))
1519da7f033dSHerbert Xu 					n = authsize;
1520da7f033dSHerbert Xu 				else
1521da7f033dSHerbert Xu 					n = 0;
1522da7f033dSHerbert Xu 			} else {
152305b1d338SCristian Stoica 				for (n = 0; offset_in_page(q + n) && q[n]; n++)
1524da7f033dSHerbert Xu 					;
1525da7f033dSHerbert Xu 			}
1526da7f033dSHerbert Xu 			if (n) {
1527d8a32ac2SJussi Kivilinna 				pr_err("alg: aead%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
1528d8a32ac2SJussi Kivilinna 				       d, j, e, k, algo, n);
1529da7f033dSHerbert Xu 				hexdump(q, n);
1530da7f033dSHerbert Xu 				goto out;
1531da7f033dSHerbert Xu 			}
1532da7f033dSHerbert Xu 
1533da7f033dSHerbert Xu 			temp += template[i].tap[k];
1534da7f033dSHerbert Xu 		}
1535da7f033dSHerbert Xu 	}
1536da7f033dSHerbert Xu 
1537da7f033dSHerbert Xu 	ret = 0;
1538da7f033dSHerbert Xu 
1539da7f033dSHerbert Xu out:
1540da7f033dSHerbert Xu 	aead_request_free(req);
1541d8a32ac2SJussi Kivilinna 	kfree(sg);
1542d8a32ac2SJussi Kivilinna out_nosg:
1543d8a32ac2SJussi Kivilinna 	if (diff_dst)
1544d8a32ac2SJussi Kivilinna 		testmgr_free_buf(xoutbuf);
1545d8a32ac2SJussi Kivilinna out_nooutbuf:
1546f8b0d4d0SHerbert Xu 	testmgr_free_buf(axbuf);
1547f8b0d4d0SHerbert Xu out_noaxbuf:
1548f8b0d4d0SHerbert Xu 	testmgr_free_buf(xbuf);
1549f8b0d4d0SHerbert Xu out_noxbuf:
155029b77e5dSHoria Geanta 	kfree(key);
15519bac019dSTadeusz Struk 	kfree(iv);
1552da7f033dSHerbert Xu 	return ret;
1553da7f033dSHerbert Xu }
1554da7f033dSHerbert Xu 
1555d8a32ac2SJussi Kivilinna static int test_aead(struct crypto_aead *tfm, int enc,
1556b13b1e0cSEric Biggers 		     const struct aead_testvec *template, unsigned int tcount)
1557d8a32ac2SJussi Kivilinna {
155858dcf548SJussi Kivilinna 	unsigned int alignmask;
1559d8a32ac2SJussi Kivilinna 	int ret;
1560d8a32ac2SJussi Kivilinna 
1561d8a32ac2SJussi Kivilinna 	/* test 'dst == src' case */
156258dcf548SJussi Kivilinna 	ret = __test_aead(tfm, enc, template, tcount, false, 0);
1563d8a32ac2SJussi Kivilinna 	if (ret)
1564d8a32ac2SJussi Kivilinna 		return ret;
1565d8a32ac2SJussi Kivilinna 
1566d8a32ac2SJussi Kivilinna 	/* test 'dst != src' case */
156758dcf548SJussi Kivilinna 	ret = __test_aead(tfm, enc, template, tcount, true, 0);
156858dcf548SJussi Kivilinna 	if (ret)
156958dcf548SJussi Kivilinna 		return ret;
157058dcf548SJussi Kivilinna 
157158dcf548SJussi Kivilinna 	/* test unaligned buffers, check with one byte offset */
157258dcf548SJussi Kivilinna 	ret = __test_aead(tfm, enc, template, tcount, true, 1);
157358dcf548SJussi Kivilinna 	if (ret)
157458dcf548SJussi Kivilinna 		return ret;
157558dcf548SJussi Kivilinna 
157658dcf548SJussi Kivilinna 	alignmask = crypto_tfm_alg_alignmask(&tfm->base);
157758dcf548SJussi Kivilinna 	if (alignmask) {
157858dcf548SJussi Kivilinna 		/* Check if alignment mask for tfm is correctly set. */
157958dcf548SJussi Kivilinna 		ret = __test_aead(tfm, enc, template, tcount, true,
158058dcf548SJussi Kivilinna 				  alignmask + 1);
158158dcf548SJussi Kivilinna 		if (ret)
158258dcf548SJussi Kivilinna 			return ret;
158358dcf548SJussi Kivilinna 	}
158458dcf548SJussi Kivilinna 
158558dcf548SJussi Kivilinna 	return 0;
1586d8a32ac2SJussi Kivilinna }
1587d8a32ac2SJussi Kivilinna 
15881aa4ecd9SHerbert Xu static int test_cipher(struct crypto_cipher *tfm, int enc,
1589b13b1e0cSEric Biggers 		       const struct cipher_testvec *template,
1590b13b1e0cSEric Biggers 		       unsigned int tcount)
15911aa4ecd9SHerbert Xu {
15921aa4ecd9SHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
15931aa4ecd9SHerbert Xu 	unsigned int i, j, k;
15941aa4ecd9SHerbert Xu 	char *q;
15951aa4ecd9SHerbert Xu 	const char *e;
159692a4c9feSEric Biggers 	const char *input, *result;
15971aa4ecd9SHerbert Xu 	void *data;
1598f8b0d4d0SHerbert Xu 	char *xbuf[XBUFSIZE];
1599f8b0d4d0SHerbert Xu 	int ret = -ENOMEM;
1600f8b0d4d0SHerbert Xu 
1601f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(xbuf))
1602f8b0d4d0SHerbert Xu 		goto out_nobuf;
16031aa4ecd9SHerbert Xu 
16041aa4ecd9SHerbert Xu 	if (enc == ENCRYPT)
16051aa4ecd9SHerbert Xu 	        e = "encryption";
16061aa4ecd9SHerbert Xu 	else
16071aa4ecd9SHerbert Xu 		e = "decryption";
16081aa4ecd9SHerbert Xu 
16091aa4ecd9SHerbert Xu 	j = 0;
16101aa4ecd9SHerbert Xu 	for (i = 0; i < tcount; i++) {
16111aa4ecd9SHerbert Xu 		if (template[i].np)
16121aa4ecd9SHerbert Xu 			continue;
16131aa4ecd9SHerbert Xu 
161410faa8c0SStephan Mueller 		if (fips_enabled && template[i].fips_skip)
161510faa8c0SStephan Mueller 			continue;
161610faa8c0SStephan Mueller 
161792a4c9feSEric Biggers 		input  = enc ? template[i].ptext : template[i].ctext;
161892a4c9feSEric Biggers 		result = enc ? template[i].ctext : template[i].ptext;
16191aa4ecd9SHerbert Xu 		j++;
16201aa4ecd9SHerbert Xu 
1621fd57f22aSHerbert Xu 		ret = -EINVAL;
162292a4c9feSEric Biggers 		if (WARN_ON(template[i].len > PAGE_SIZE))
1623fd57f22aSHerbert Xu 			goto out;
1624fd57f22aSHerbert Xu 
16251aa4ecd9SHerbert Xu 		data = xbuf[0];
162692a4c9feSEric Biggers 		memcpy(data, input, template[i].len);
16271aa4ecd9SHerbert Xu 
16281aa4ecd9SHerbert Xu 		crypto_cipher_clear_flags(tfm, ~0);
16291aa4ecd9SHerbert Xu 		if (template[i].wk)
1630231baecdSEric Biggers 			crypto_cipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
16311aa4ecd9SHerbert Xu 
16321aa4ecd9SHerbert Xu 		ret = crypto_cipher_setkey(tfm, template[i].key,
16331aa4ecd9SHerbert Xu 					   template[i].klen);
16340fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
16351aa4ecd9SHerbert Xu 			printk(KERN_ERR "alg: cipher: setkey failed "
16361aa4ecd9SHerbert Xu 			       "on test %d for %s: flags=%x\n", j,
16371aa4ecd9SHerbert Xu 			       algo, crypto_cipher_get_flags(tfm));
16381aa4ecd9SHerbert Xu 			goto out;
16391aa4ecd9SHerbert Xu 		} else if (ret)
16401aa4ecd9SHerbert Xu 			continue;
16411aa4ecd9SHerbert Xu 
164292a4c9feSEric Biggers 		for (k = 0; k < template[i].len;
16431aa4ecd9SHerbert Xu 		     k += crypto_cipher_blocksize(tfm)) {
16441aa4ecd9SHerbert Xu 			if (enc)
16451aa4ecd9SHerbert Xu 				crypto_cipher_encrypt_one(tfm, data + k,
16461aa4ecd9SHerbert Xu 							  data + k);
16471aa4ecd9SHerbert Xu 			else
16481aa4ecd9SHerbert Xu 				crypto_cipher_decrypt_one(tfm, data + k,
16491aa4ecd9SHerbert Xu 							  data + k);
16501aa4ecd9SHerbert Xu 		}
16511aa4ecd9SHerbert Xu 
16521aa4ecd9SHerbert Xu 		q = data;
165392a4c9feSEric Biggers 		if (memcmp(q, result, template[i].len)) {
16541aa4ecd9SHerbert Xu 			printk(KERN_ERR "alg: cipher: Test %d failed "
16551aa4ecd9SHerbert Xu 			       "on %s for %s\n", j, e, algo);
165692a4c9feSEric Biggers 			hexdump(q, template[i].len);
16571aa4ecd9SHerbert Xu 			ret = -EINVAL;
16581aa4ecd9SHerbert Xu 			goto out;
16591aa4ecd9SHerbert Xu 		}
16601aa4ecd9SHerbert Xu 	}
16611aa4ecd9SHerbert Xu 
16621aa4ecd9SHerbert Xu 	ret = 0;
16631aa4ecd9SHerbert Xu 
16641aa4ecd9SHerbert Xu out:
1665f8b0d4d0SHerbert Xu 	testmgr_free_buf(xbuf);
1666f8b0d4d0SHerbert Xu out_nobuf:
16671aa4ecd9SHerbert Xu 	return ret;
16681aa4ecd9SHerbert Xu }
16691aa4ecd9SHerbert Xu 
167012773d93SHerbert Xu static int __test_skcipher(struct crypto_skcipher *tfm, int enc,
1671b13b1e0cSEric Biggers 			   const struct cipher_testvec *template,
1672b13b1e0cSEric Biggers 			   unsigned int tcount,
16733a338f20SJussi Kivilinna 			   const bool diff_dst, const int align_offset)
1674da7f033dSHerbert Xu {
1675da7f033dSHerbert Xu 	const char *algo =
167612773d93SHerbert Xu 		crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm));
1677da7f033dSHerbert Xu 	unsigned int i, j, k, n, temp;
1678da7f033dSHerbert Xu 	char *q;
167912773d93SHerbert Xu 	struct skcipher_request *req;
1680da7f033dSHerbert Xu 	struct scatterlist sg[8];
168108d6af8cSJussi Kivilinna 	struct scatterlist sgout[8];
168208d6af8cSJussi Kivilinna 	const char *e, *d;
16837f397136SGilad Ben-Yossef 	struct crypto_wait wait;
168492a4c9feSEric Biggers 	const char *input, *result;
1685da7f033dSHerbert Xu 	void *data;
1686da7f033dSHerbert Xu 	char iv[MAX_IVLEN];
1687f8b0d4d0SHerbert Xu 	char *xbuf[XBUFSIZE];
168808d6af8cSJussi Kivilinna 	char *xoutbuf[XBUFSIZE];
1689f8b0d4d0SHerbert Xu 	int ret = -ENOMEM;
169084cba178SAndrey Ryabinin 	unsigned int ivsize = crypto_skcipher_ivsize(tfm);
1691f8b0d4d0SHerbert Xu 
1692f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(xbuf))
1693f8b0d4d0SHerbert Xu 		goto out_nobuf;
1694da7f033dSHerbert Xu 
169508d6af8cSJussi Kivilinna 	if (diff_dst && testmgr_alloc_buf(xoutbuf))
169608d6af8cSJussi Kivilinna 		goto out_nooutbuf;
169708d6af8cSJussi Kivilinna 
169808d6af8cSJussi Kivilinna 	if (diff_dst)
169908d6af8cSJussi Kivilinna 		d = "-ddst";
170008d6af8cSJussi Kivilinna 	else
170108d6af8cSJussi Kivilinna 		d = "";
170208d6af8cSJussi Kivilinna 
1703da7f033dSHerbert Xu 	if (enc == ENCRYPT)
1704da7f033dSHerbert Xu 	        e = "encryption";
1705da7f033dSHerbert Xu 	else
1706da7f033dSHerbert Xu 		e = "decryption";
1707da7f033dSHerbert Xu 
17087f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
1709da7f033dSHerbert Xu 
171012773d93SHerbert Xu 	req = skcipher_request_alloc(tfm, GFP_KERNEL);
1711da7f033dSHerbert Xu 	if (!req) {
171208d6af8cSJussi Kivilinna 		pr_err("alg: skcipher%s: Failed to allocate request for %s\n",
171308d6af8cSJussi Kivilinna 		       d, algo);
1714da7f033dSHerbert Xu 		goto out;
1715da7f033dSHerbert Xu 	}
1716da7f033dSHerbert Xu 
171712773d93SHerbert Xu 	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
17187f397136SGilad Ben-Yossef 				      crypto_req_done, &wait);
1719da7f033dSHerbert Xu 
1720da7f033dSHerbert Xu 	j = 0;
1721da7f033dSHerbert Xu 	for (i = 0; i < tcount; i++) {
1722bbb9a7ddSCristian Stoica 		if (template[i].np && !template[i].also_non_np)
1723bbb9a7ddSCristian Stoica 			continue;
1724bbb9a7ddSCristian Stoica 
172510faa8c0SStephan Mueller 		if (fips_enabled && template[i].fips_skip)
172610faa8c0SStephan Mueller 			continue;
172710faa8c0SStephan Mueller 
172892a4c9feSEric Biggers 		if (template[i].iv && !(template[i].generates_iv && enc))
172984cba178SAndrey Ryabinin 			memcpy(iv, template[i].iv, ivsize);
1730da7f033dSHerbert Xu 		else
1731da7f033dSHerbert Xu 			memset(iv, 0, MAX_IVLEN);
1732da7f033dSHerbert Xu 
173392a4c9feSEric Biggers 		input  = enc ? template[i].ptext : template[i].ctext;
173492a4c9feSEric Biggers 		result = enc ? template[i].ctext : template[i].ptext;
1735da7f033dSHerbert Xu 		j++;
1736fd57f22aSHerbert Xu 		ret = -EINVAL;
173792a4c9feSEric Biggers 		if (WARN_ON(align_offset + template[i].len > PAGE_SIZE))
1738fd57f22aSHerbert Xu 			goto out;
1739fd57f22aSHerbert Xu 
1740da7f033dSHerbert Xu 		data = xbuf[0];
17413a338f20SJussi Kivilinna 		data += align_offset;
174292a4c9feSEric Biggers 		memcpy(data, input, template[i].len);
1743da7f033dSHerbert Xu 
174412773d93SHerbert Xu 		crypto_skcipher_clear_flags(tfm, ~0);
1745da7f033dSHerbert Xu 		if (template[i].wk)
1746231baecdSEric Biggers 			crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
1747da7f033dSHerbert Xu 
174812773d93SHerbert Xu 		ret = crypto_skcipher_setkey(tfm, template[i].key,
1749da7f033dSHerbert Xu 					     template[i].klen);
17500fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
175108d6af8cSJussi Kivilinna 			pr_err("alg: skcipher%s: setkey failed on test %d for %s: flags=%x\n",
175212773d93SHerbert Xu 			       d, j, algo, crypto_skcipher_get_flags(tfm));
1753da7f033dSHerbert Xu 			goto out;
1754da7f033dSHerbert Xu 		} else if (ret)
1755da7f033dSHerbert Xu 			continue;
1756da7f033dSHerbert Xu 
175792a4c9feSEric Biggers 		sg_init_one(&sg[0], data, template[i].len);
175808d6af8cSJussi Kivilinna 		if (diff_dst) {
175908d6af8cSJussi Kivilinna 			data = xoutbuf[0];
17603a338f20SJussi Kivilinna 			data += align_offset;
176192a4c9feSEric Biggers 			sg_init_one(&sgout[0], data, template[i].len);
176208d6af8cSJussi Kivilinna 		}
1763da7f033dSHerbert Xu 
176412773d93SHerbert Xu 		skcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
176592a4c9feSEric Biggers 					   template[i].len, iv);
17667f397136SGilad Ben-Yossef 		ret = crypto_wait_req(enc ? crypto_skcipher_encrypt(req) :
17677f397136SGilad Ben-Yossef 				      crypto_skcipher_decrypt(req), &wait);
1768da7f033dSHerbert Xu 
17697f397136SGilad Ben-Yossef 		if (ret) {
177008d6af8cSJussi Kivilinna 			pr_err("alg: skcipher%s: %s failed on test %d for %s: ret=%d\n",
177108d6af8cSJussi Kivilinna 			       d, e, j, algo, -ret);
1772da7f033dSHerbert Xu 			goto out;
1773da7f033dSHerbert Xu 		}
1774da7f033dSHerbert Xu 
1775da7f033dSHerbert Xu 		q = data;
177692a4c9feSEric Biggers 		if (memcmp(q, result, template[i].len)) {
17778a826a34SBoris BREZILLON 			pr_err("alg: skcipher%s: Test %d failed (invalid result) on %s for %s\n",
177808d6af8cSJussi Kivilinna 			       d, j, e, algo);
177992a4c9feSEric Biggers 			hexdump(q, template[i].len);
1780da7f033dSHerbert Xu 			ret = -EINVAL;
1781da7f033dSHerbert Xu 			goto out;
1782da7f033dSHerbert Xu 		}
17838a826a34SBoris BREZILLON 
178492a4c9feSEric Biggers 		if (template[i].generates_iv && enc &&
178592a4c9feSEric Biggers 		    memcmp(iv, template[i].iv, crypto_skcipher_ivsize(tfm))) {
17868a826a34SBoris BREZILLON 			pr_err("alg: skcipher%s: Test %d failed (invalid output IV) on %s for %s\n",
17878a826a34SBoris BREZILLON 			       d, j, e, algo);
17888a826a34SBoris BREZILLON 			hexdump(iv, crypto_skcipher_ivsize(tfm));
17898a826a34SBoris BREZILLON 			ret = -EINVAL;
17908a826a34SBoris BREZILLON 			goto out;
17918a826a34SBoris BREZILLON 		}
1792da7f033dSHerbert Xu 	}
1793da7f033dSHerbert Xu 
1794da7f033dSHerbert Xu 	j = 0;
1795da7f033dSHerbert Xu 	for (i = 0; i < tcount; i++) {
17963a338f20SJussi Kivilinna 		/* alignment tests are only done with continuous buffers */
17973a338f20SJussi Kivilinna 		if (align_offset != 0)
17983a338f20SJussi Kivilinna 			break;
1799da7f033dSHerbert Xu 
1800bbb9a7ddSCristian Stoica 		if (!template[i].np)
1801bbb9a7ddSCristian Stoica 			continue;
1802bbb9a7ddSCristian Stoica 
180310faa8c0SStephan Mueller 		if (fips_enabled && template[i].fips_skip)
180410faa8c0SStephan Mueller 			continue;
180510faa8c0SStephan Mueller 
180692a4c9feSEric Biggers 		if (template[i].iv && !(template[i].generates_iv && enc))
180784cba178SAndrey Ryabinin 			memcpy(iv, template[i].iv, ivsize);
1808da7f033dSHerbert Xu 		else
1809da7f033dSHerbert Xu 			memset(iv, 0, MAX_IVLEN);
1810da7f033dSHerbert Xu 
181192a4c9feSEric Biggers 		input  = enc ? template[i].ptext : template[i].ctext;
181292a4c9feSEric Biggers 		result = enc ? template[i].ctext : template[i].ptext;
1813da7f033dSHerbert Xu 		j++;
181412773d93SHerbert Xu 		crypto_skcipher_clear_flags(tfm, ~0);
1815da7f033dSHerbert Xu 		if (template[i].wk)
1816231baecdSEric Biggers 			crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
1817da7f033dSHerbert Xu 
181812773d93SHerbert Xu 		ret = crypto_skcipher_setkey(tfm, template[i].key,
1819da7f033dSHerbert Xu 					     template[i].klen);
18200fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
182108d6af8cSJussi Kivilinna 			pr_err("alg: skcipher%s: setkey failed on chunk test %d for %s: flags=%x\n",
182212773d93SHerbert Xu 			       d, j, algo, crypto_skcipher_get_flags(tfm));
1823da7f033dSHerbert Xu 			goto out;
1824da7f033dSHerbert Xu 		} else if (ret)
1825da7f033dSHerbert Xu 			continue;
1826da7f033dSHerbert Xu 
1827da7f033dSHerbert Xu 		temp = 0;
1828da7f033dSHerbert Xu 		ret = -EINVAL;
1829da7f033dSHerbert Xu 		sg_init_table(sg, template[i].np);
183008d6af8cSJussi Kivilinna 		if (diff_dst)
183108d6af8cSJussi Kivilinna 			sg_init_table(sgout, template[i].np);
1832da7f033dSHerbert Xu 		for (k = 0; k < template[i].np; k++) {
1833da7f033dSHerbert Xu 			if (WARN_ON(offset_in_page(IDX[k]) +
1834da7f033dSHerbert Xu 				    template[i].tap[k] > PAGE_SIZE))
1835da7f033dSHerbert Xu 				goto out;
1836da7f033dSHerbert Xu 
1837a1aa44a2SCristian Stoica 			q = xbuf[IDX[k] >> PAGE_SHIFT] + offset_in_page(IDX[k]);
1838da7f033dSHerbert Xu 
183992a4c9feSEric Biggers 			memcpy(q, input + temp, template[i].tap[k]);
1840da7f033dSHerbert Xu 
1841a1aa44a2SCristian Stoica 			if (offset_in_page(q) + template[i].tap[k] < PAGE_SIZE)
1842da7f033dSHerbert Xu 				q[template[i].tap[k]] = 0;
1843da7f033dSHerbert Xu 
1844da7f033dSHerbert Xu 			sg_set_buf(&sg[k], q, template[i].tap[k]);
184508d6af8cSJussi Kivilinna 			if (diff_dst) {
184608d6af8cSJussi Kivilinna 				q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
184708d6af8cSJussi Kivilinna 				    offset_in_page(IDX[k]);
184808d6af8cSJussi Kivilinna 
1849a1aa44a2SCristian Stoica 				sg_set_buf(&sgout[k], q, template[i].tap[k]);
185008d6af8cSJussi Kivilinna 
185108d6af8cSJussi Kivilinna 				memset(q, 0, template[i].tap[k]);
185208d6af8cSJussi Kivilinna 				if (offset_in_page(q) +
185308d6af8cSJussi Kivilinna 				    template[i].tap[k] < PAGE_SIZE)
185408d6af8cSJussi Kivilinna 					q[template[i].tap[k]] = 0;
185508d6af8cSJussi Kivilinna 			}
1856da7f033dSHerbert Xu 
1857da7f033dSHerbert Xu 			temp += template[i].tap[k];
1858da7f033dSHerbert Xu 		}
1859da7f033dSHerbert Xu 
186012773d93SHerbert Xu 		skcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
186192a4c9feSEric Biggers 					   template[i].len, iv);
1862da7f033dSHerbert Xu 
18637f397136SGilad Ben-Yossef 		ret = crypto_wait_req(enc ? crypto_skcipher_encrypt(req) :
18647f397136SGilad Ben-Yossef 				      crypto_skcipher_decrypt(req), &wait);
1865da7f033dSHerbert Xu 
18667f397136SGilad Ben-Yossef 		if (ret) {
186708d6af8cSJussi Kivilinna 			pr_err("alg: skcipher%s: %s failed on chunk test %d for %s: ret=%d\n",
186808d6af8cSJussi Kivilinna 			       d, e, j, algo, -ret);
1869da7f033dSHerbert Xu 			goto out;
1870da7f033dSHerbert Xu 		}
1871da7f033dSHerbert Xu 
1872da7f033dSHerbert Xu 		temp = 0;
1873da7f033dSHerbert Xu 		ret = -EINVAL;
1874da7f033dSHerbert Xu 		for (k = 0; k < template[i].np; k++) {
187508d6af8cSJussi Kivilinna 			if (diff_dst)
187608d6af8cSJussi Kivilinna 				q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
187708d6af8cSJussi Kivilinna 				    offset_in_page(IDX[k]);
187808d6af8cSJussi Kivilinna 			else
1879da7f033dSHerbert Xu 				q = xbuf[IDX[k] >> PAGE_SHIFT] +
1880da7f033dSHerbert Xu 				    offset_in_page(IDX[k]);
1881da7f033dSHerbert Xu 
188292a4c9feSEric Biggers 			if (memcmp(q, result + temp, template[i].tap[k])) {
188308d6af8cSJussi Kivilinna 				pr_err("alg: skcipher%s: Chunk test %d failed on %s at page %u for %s\n",
188408d6af8cSJussi Kivilinna 				       d, j, e, k, algo);
1885da7f033dSHerbert Xu 				hexdump(q, template[i].tap[k]);
1886da7f033dSHerbert Xu 				goto out;
1887da7f033dSHerbert Xu 			}
1888da7f033dSHerbert Xu 
1889da7f033dSHerbert Xu 			q += template[i].tap[k];
1890da7f033dSHerbert Xu 			for (n = 0; offset_in_page(q + n) && q[n]; n++)
1891da7f033dSHerbert Xu 				;
1892da7f033dSHerbert Xu 			if (n) {
189308d6af8cSJussi Kivilinna 				pr_err("alg: skcipher%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
189408d6af8cSJussi Kivilinna 				       d, j, e, k, algo, n);
1895da7f033dSHerbert Xu 				hexdump(q, n);
1896da7f033dSHerbert Xu 				goto out;
1897da7f033dSHerbert Xu 			}
1898da7f033dSHerbert Xu 			temp += template[i].tap[k];
1899da7f033dSHerbert Xu 		}
1900da7f033dSHerbert Xu 	}
1901da7f033dSHerbert Xu 
1902da7f033dSHerbert Xu 	ret = 0;
1903da7f033dSHerbert Xu 
1904da7f033dSHerbert Xu out:
190512773d93SHerbert Xu 	skcipher_request_free(req);
190608d6af8cSJussi Kivilinna 	if (diff_dst)
190708d6af8cSJussi Kivilinna 		testmgr_free_buf(xoutbuf);
190808d6af8cSJussi Kivilinna out_nooutbuf:
1909f8b0d4d0SHerbert Xu 	testmgr_free_buf(xbuf);
1910f8b0d4d0SHerbert Xu out_nobuf:
1911da7f033dSHerbert Xu 	return ret;
1912da7f033dSHerbert Xu }
1913da7f033dSHerbert Xu 
191412773d93SHerbert Xu static int test_skcipher(struct crypto_skcipher *tfm, int enc,
1915b13b1e0cSEric Biggers 			 const struct cipher_testvec *template,
1916b13b1e0cSEric Biggers 			 unsigned int tcount)
191708d6af8cSJussi Kivilinna {
19183a338f20SJussi Kivilinna 	unsigned int alignmask;
191908d6af8cSJussi Kivilinna 	int ret;
192008d6af8cSJussi Kivilinna 
192108d6af8cSJussi Kivilinna 	/* test 'dst == src' case */
19223a338f20SJussi Kivilinna 	ret = __test_skcipher(tfm, enc, template, tcount, false, 0);
192308d6af8cSJussi Kivilinna 	if (ret)
192408d6af8cSJussi Kivilinna 		return ret;
192508d6af8cSJussi Kivilinna 
192608d6af8cSJussi Kivilinna 	/* test 'dst != src' case */
19273a338f20SJussi Kivilinna 	ret = __test_skcipher(tfm, enc, template, tcount, true, 0);
19283a338f20SJussi Kivilinna 	if (ret)
19293a338f20SJussi Kivilinna 		return ret;
19303a338f20SJussi Kivilinna 
19313a338f20SJussi Kivilinna 	/* test unaligned buffers, check with one byte offset */
19323a338f20SJussi Kivilinna 	ret = __test_skcipher(tfm, enc, template, tcount, true, 1);
19333a338f20SJussi Kivilinna 	if (ret)
19343a338f20SJussi Kivilinna 		return ret;
19353a338f20SJussi Kivilinna 
19363a338f20SJussi Kivilinna 	alignmask = crypto_tfm_alg_alignmask(&tfm->base);
19373a338f20SJussi Kivilinna 	if (alignmask) {
19383a338f20SJussi Kivilinna 		/* Check if alignment mask for tfm is correctly set. */
19393a338f20SJussi Kivilinna 		ret = __test_skcipher(tfm, enc, template, tcount, true,
19403a338f20SJussi Kivilinna 				      alignmask + 1);
19413a338f20SJussi Kivilinna 		if (ret)
19423a338f20SJussi Kivilinna 			return ret;
19433a338f20SJussi Kivilinna 	}
19443a338f20SJussi Kivilinna 
19453a338f20SJussi Kivilinna 	return 0;
194608d6af8cSJussi Kivilinna }
194708d6af8cSJussi Kivilinna 
1948b13b1e0cSEric Biggers static int test_comp(struct crypto_comp *tfm,
1949b13b1e0cSEric Biggers 		     const struct comp_testvec *ctemplate,
1950b13b1e0cSEric Biggers 		     const struct comp_testvec *dtemplate,
1951b13b1e0cSEric Biggers 		     int ctcount, int dtcount)
1952da7f033dSHerbert Xu {
1953da7f033dSHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_comp_tfm(tfm));
195433607384SMahipal Challa 	char *output, *decomp_output;
1955da7f033dSHerbert Xu 	unsigned int i;
1956da7f033dSHerbert Xu 	int ret;
1957da7f033dSHerbert Xu 
195833607384SMahipal Challa 	output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
195933607384SMahipal Challa 	if (!output)
196033607384SMahipal Challa 		return -ENOMEM;
196133607384SMahipal Challa 
196233607384SMahipal Challa 	decomp_output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
196333607384SMahipal Challa 	if (!decomp_output) {
196433607384SMahipal Challa 		kfree(output);
196533607384SMahipal Challa 		return -ENOMEM;
196633607384SMahipal Challa 	}
196733607384SMahipal Challa 
1968da7f033dSHerbert Xu 	for (i = 0; i < ctcount; i++) {
1969c79cf910SGeert Uytterhoeven 		int ilen;
1970c79cf910SGeert Uytterhoeven 		unsigned int dlen = COMP_BUF_SIZE;
1971da7f033dSHerbert Xu 
197222a8118dSMichael Schupikov 		memset(output, 0, COMP_BUF_SIZE);
197322a8118dSMichael Schupikov 		memset(decomp_output, 0, COMP_BUF_SIZE);
1974da7f033dSHerbert Xu 
1975da7f033dSHerbert Xu 		ilen = ctemplate[i].inlen;
1976da7f033dSHerbert Xu 		ret = crypto_comp_compress(tfm, ctemplate[i].input,
197733607384SMahipal Challa 					   ilen, output, &dlen);
1978da7f033dSHerbert Xu 		if (ret) {
1979da7f033dSHerbert Xu 			printk(KERN_ERR "alg: comp: compression failed "
1980da7f033dSHerbert Xu 			       "on test %d for %s: ret=%d\n", i + 1, algo,
1981da7f033dSHerbert Xu 			       -ret);
1982da7f033dSHerbert Xu 			goto out;
1983da7f033dSHerbert Xu 		}
1984da7f033dSHerbert Xu 
198533607384SMahipal Challa 		ilen = dlen;
198633607384SMahipal Challa 		dlen = COMP_BUF_SIZE;
198733607384SMahipal Challa 		ret = crypto_comp_decompress(tfm, output,
198833607384SMahipal Challa 					     ilen, decomp_output, &dlen);
198933607384SMahipal Challa 		if (ret) {
199033607384SMahipal Challa 			pr_err("alg: comp: compression failed: decompress: on test %d for %s failed: ret=%d\n",
199133607384SMahipal Challa 			       i + 1, algo, -ret);
199233607384SMahipal Challa 			goto out;
199333607384SMahipal Challa 		}
199433607384SMahipal Challa 
199533607384SMahipal Challa 		if (dlen != ctemplate[i].inlen) {
1996b812eb00SGeert Uytterhoeven 			printk(KERN_ERR "alg: comp: Compression test %d "
1997b812eb00SGeert Uytterhoeven 			       "failed for %s: output len = %d\n", i + 1, algo,
1998b812eb00SGeert Uytterhoeven 			       dlen);
1999b812eb00SGeert Uytterhoeven 			ret = -EINVAL;
2000b812eb00SGeert Uytterhoeven 			goto out;
2001b812eb00SGeert Uytterhoeven 		}
2002b812eb00SGeert Uytterhoeven 
200333607384SMahipal Challa 		if (memcmp(decomp_output, ctemplate[i].input,
200433607384SMahipal Challa 			   ctemplate[i].inlen)) {
200533607384SMahipal Challa 			pr_err("alg: comp: compression failed: output differs: on test %d for %s\n",
200633607384SMahipal Challa 			       i + 1, algo);
200733607384SMahipal Challa 			hexdump(decomp_output, dlen);
2008da7f033dSHerbert Xu 			ret = -EINVAL;
2009da7f033dSHerbert Xu 			goto out;
2010da7f033dSHerbert Xu 		}
2011da7f033dSHerbert Xu 	}
2012da7f033dSHerbert Xu 
2013da7f033dSHerbert Xu 	for (i = 0; i < dtcount; i++) {
2014c79cf910SGeert Uytterhoeven 		int ilen;
2015c79cf910SGeert Uytterhoeven 		unsigned int dlen = COMP_BUF_SIZE;
2016da7f033dSHerbert Xu 
201722a8118dSMichael Schupikov 		memset(decomp_output, 0, COMP_BUF_SIZE);
2018da7f033dSHerbert Xu 
2019da7f033dSHerbert Xu 		ilen = dtemplate[i].inlen;
2020da7f033dSHerbert Xu 		ret = crypto_comp_decompress(tfm, dtemplate[i].input,
202133607384SMahipal Challa 					     ilen, decomp_output, &dlen);
2022da7f033dSHerbert Xu 		if (ret) {
2023da7f033dSHerbert Xu 			printk(KERN_ERR "alg: comp: decompression failed "
2024da7f033dSHerbert Xu 			       "on test %d for %s: ret=%d\n", i + 1, algo,
2025da7f033dSHerbert Xu 			       -ret);
2026da7f033dSHerbert Xu 			goto out;
2027da7f033dSHerbert Xu 		}
2028da7f033dSHerbert Xu 
2029b812eb00SGeert Uytterhoeven 		if (dlen != dtemplate[i].outlen) {
2030b812eb00SGeert Uytterhoeven 			printk(KERN_ERR "alg: comp: Decompression test %d "
2031b812eb00SGeert Uytterhoeven 			       "failed for %s: output len = %d\n", i + 1, algo,
2032b812eb00SGeert Uytterhoeven 			       dlen);
2033b812eb00SGeert Uytterhoeven 			ret = -EINVAL;
2034b812eb00SGeert Uytterhoeven 			goto out;
2035b812eb00SGeert Uytterhoeven 		}
2036b812eb00SGeert Uytterhoeven 
203733607384SMahipal Challa 		if (memcmp(decomp_output, dtemplate[i].output, dlen)) {
2038da7f033dSHerbert Xu 			printk(KERN_ERR "alg: comp: Decompression test %d "
2039da7f033dSHerbert Xu 			       "failed for %s\n", i + 1, algo);
204033607384SMahipal Challa 			hexdump(decomp_output, dlen);
2041da7f033dSHerbert Xu 			ret = -EINVAL;
2042da7f033dSHerbert Xu 			goto out;
2043da7f033dSHerbert Xu 		}
2044da7f033dSHerbert Xu 	}
2045da7f033dSHerbert Xu 
2046da7f033dSHerbert Xu 	ret = 0;
2047da7f033dSHerbert Xu 
2048da7f033dSHerbert Xu out:
204933607384SMahipal Challa 	kfree(decomp_output);
205033607384SMahipal Challa 	kfree(output);
2051da7f033dSHerbert Xu 	return ret;
2052da7f033dSHerbert Xu }
2053da7f033dSHerbert Xu 
2054b13b1e0cSEric Biggers static int test_acomp(struct crypto_acomp *tfm,
2055b13b1e0cSEric Biggers 			      const struct comp_testvec *ctemplate,
2056b13b1e0cSEric Biggers 		      const struct comp_testvec *dtemplate,
2057b13b1e0cSEric Biggers 		      int ctcount, int dtcount)
2058d7db7a88SGiovanni Cabiddu {
2059d7db7a88SGiovanni Cabiddu 	const char *algo = crypto_tfm_alg_driver_name(crypto_acomp_tfm(tfm));
2060d7db7a88SGiovanni Cabiddu 	unsigned int i;
2061a9943a0aSGiovanni Cabiddu 	char *output, *decomp_out;
2062d7db7a88SGiovanni Cabiddu 	int ret;
2063d7db7a88SGiovanni Cabiddu 	struct scatterlist src, dst;
2064d7db7a88SGiovanni Cabiddu 	struct acomp_req *req;
20657f397136SGilad Ben-Yossef 	struct crypto_wait wait;
2066d7db7a88SGiovanni Cabiddu 
2067eb095593SEric Biggers 	output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
2068eb095593SEric Biggers 	if (!output)
2069eb095593SEric Biggers 		return -ENOMEM;
2070eb095593SEric Biggers 
2071a9943a0aSGiovanni Cabiddu 	decomp_out = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
2072a9943a0aSGiovanni Cabiddu 	if (!decomp_out) {
2073a9943a0aSGiovanni Cabiddu 		kfree(output);
2074a9943a0aSGiovanni Cabiddu 		return -ENOMEM;
2075a9943a0aSGiovanni Cabiddu 	}
2076a9943a0aSGiovanni Cabiddu 
2077d7db7a88SGiovanni Cabiddu 	for (i = 0; i < ctcount; i++) {
2078d7db7a88SGiovanni Cabiddu 		unsigned int dlen = COMP_BUF_SIZE;
2079d7db7a88SGiovanni Cabiddu 		int ilen = ctemplate[i].inlen;
208002608e02SLaura Abbott 		void *input_vec;
2081d7db7a88SGiovanni Cabiddu 
2082d2110224SEric Biggers 		input_vec = kmemdup(ctemplate[i].input, ilen, GFP_KERNEL);
208302608e02SLaura Abbott 		if (!input_vec) {
208402608e02SLaura Abbott 			ret = -ENOMEM;
208502608e02SLaura Abbott 			goto out;
208602608e02SLaura Abbott 		}
208702608e02SLaura Abbott 
2088eb095593SEric Biggers 		memset(output, 0, dlen);
20897f397136SGilad Ben-Yossef 		crypto_init_wait(&wait);
209002608e02SLaura Abbott 		sg_init_one(&src, input_vec, ilen);
2091d7db7a88SGiovanni Cabiddu 		sg_init_one(&dst, output, dlen);
2092d7db7a88SGiovanni Cabiddu 
2093d7db7a88SGiovanni Cabiddu 		req = acomp_request_alloc(tfm);
2094d7db7a88SGiovanni Cabiddu 		if (!req) {
2095d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: request alloc failed for %s\n",
2096d7db7a88SGiovanni Cabiddu 			       algo);
209702608e02SLaura Abbott 			kfree(input_vec);
2098d7db7a88SGiovanni Cabiddu 			ret = -ENOMEM;
2099d7db7a88SGiovanni Cabiddu 			goto out;
2100d7db7a88SGiovanni Cabiddu 		}
2101d7db7a88SGiovanni Cabiddu 
2102d7db7a88SGiovanni Cabiddu 		acomp_request_set_params(req, &src, &dst, ilen, dlen);
2103d7db7a88SGiovanni Cabiddu 		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
21047f397136SGilad Ben-Yossef 					   crypto_req_done, &wait);
2105d7db7a88SGiovanni Cabiddu 
21067f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_acomp_compress(req), &wait);
2107d7db7a88SGiovanni Cabiddu 		if (ret) {
2108d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
2109d7db7a88SGiovanni Cabiddu 			       i + 1, algo, -ret);
211002608e02SLaura Abbott 			kfree(input_vec);
2111d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2112d7db7a88SGiovanni Cabiddu 			goto out;
2113d7db7a88SGiovanni Cabiddu 		}
2114d7db7a88SGiovanni Cabiddu 
2115a9943a0aSGiovanni Cabiddu 		ilen = req->dlen;
2116a9943a0aSGiovanni Cabiddu 		dlen = COMP_BUF_SIZE;
2117a9943a0aSGiovanni Cabiddu 		sg_init_one(&src, output, ilen);
2118a9943a0aSGiovanni Cabiddu 		sg_init_one(&dst, decomp_out, dlen);
21197f397136SGilad Ben-Yossef 		crypto_init_wait(&wait);
2120a9943a0aSGiovanni Cabiddu 		acomp_request_set_params(req, &src, &dst, ilen, dlen);
2121a9943a0aSGiovanni Cabiddu 
21227f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
2123a9943a0aSGiovanni Cabiddu 		if (ret) {
2124a9943a0aSGiovanni Cabiddu 			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
2125a9943a0aSGiovanni Cabiddu 			       i + 1, algo, -ret);
2126a9943a0aSGiovanni Cabiddu 			kfree(input_vec);
2127a9943a0aSGiovanni Cabiddu 			acomp_request_free(req);
2128a9943a0aSGiovanni Cabiddu 			goto out;
2129a9943a0aSGiovanni Cabiddu 		}
2130a9943a0aSGiovanni Cabiddu 
2131a9943a0aSGiovanni Cabiddu 		if (req->dlen != ctemplate[i].inlen) {
2132d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Compression test %d failed for %s: output len = %d\n",
2133d7db7a88SGiovanni Cabiddu 			       i + 1, algo, req->dlen);
2134d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
213502608e02SLaura Abbott 			kfree(input_vec);
2136d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2137d7db7a88SGiovanni Cabiddu 			goto out;
2138d7db7a88SGiovanni Cabiddu 		}
2139d7db7a88SGiovanni Cabiddu 
2140a9943a0aSGiovanni Cabiddu 		if (memcmp(input_vec, decomp_out, req->dlen)) {
2141d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Compression test %d failed for %s\n",
2142d7db7a88SGiovanni Cabiddu 			       i + 1, algo);
2143d7db7a88SGiovanni Cabiddu 			hexdump(output, req->dlen);
2144d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
214502608e02SLaura Abbott 			kfree(input_vec);
2146d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2147d7db7a88SGiovanni Cabiddu 			goto out;
2148d7db7a88SGiovanni Cabiddu 		}
2149d7db7a88SGiovanni Cabiddu 
215002608e02SLaura Abbott 		kfree(input_vec);
2151d7db7a88SGiovanni Cabiddu 		acomp_request_free(req);
2152d7db7a88SGiovanni Cabiddu 	}
2153d7db7a88SGiovanni Cabiddu 
2154d7db7a88SGiovanni Cabiddu 	for (i = 0; i < dtcount; i++) {
2155d7db7a88SGiovanni Cabiddu 		unsigned int dlen = COMP_BUF_SIZE;
2156d7db7a88SGiovanni Cabiddu 		int ilen = dtemplate[i].inlen;
215702608e02SLaura Abbott 		void *input_vec;
2158d7db7a88SGiovanni Cabiddu 
2159d2110224SEric Biggers 		input_vec = kmemdup(dtemplate[i].input, ilen, GFP_KERNEL);
216002608e02SLaura Abbott 		if (!input_vec) {
216102608e02SLaura Abbott 			ret = -ENOMEM;
216202608e02SLaura Abbott 			goto out;
216302608e02SLaura Abbott 		}
216402608e02SLaura Abbott 
2165eb095593SEric Biggers 		memset(output, 0, dlen);
21667f397136SGilad Ben-Yossef 		crypto_init_wait(&wait);
216702608e02SLaura Abbott 		sg_init_one(&src, input_vec, ilen);
2168d7db7a88SGiovanni Cabiddu 		sg_init_one(&dst, output, dlen);
2169d7db7a88SGiovanni Cabiddu 
2170d7db7a88SGiovanni Cabiddu 		req = acomp_request_alloc(tfm);
2171d7db7a88SGiovanni Cabiddu 		if (!req) {
2172d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: request alloc failed for %s\n",
2173d7db7a88SGiovanni Cabiddu 			       algo);
217402608e02SLaura Abbott 			kfree(input_vec);
2175d7db7a88SGiovanni Cabiddu 			ret = -ENOMEM;
2176d7db7a88SGiovanni Cabiddu 			goto out;
2177d7db7a88SGiovanni Cabiddu 		}
2178d7db7a88SGiovanni Cabiddu 
2179d7db7a88SGiovanni Cabiddu 		acomp_request_set_params(req, &src, &dst, ilen, dlen);
2180d7db7a88SGiovanni Cabiddu 		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
21817f397136SGilad Ben-Yossef 					   crypto_req_done, &wait);
2182d7db7a88SGiovanni Cabiddu 
21837f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
2184d7db7a88SGiovanni Cabiddu 		if (ret) {
2185d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: decompression failed on test %d for %s: ret=%d\n",
2186d7db7a88SGiovanni Cabiddu 			       i + 1, algo, -ret);
218702608e02SLaura Abbott 			kfree(input_vec);
2188d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2189d7db7a88SGiovanni Cabiddu 			goto out;
2190d7db7a88SGiovanni Cabiddu 		}
2191d7db7a88SGiovanni Cabiddu 
2192d7db7a88SGiovanni Cabiddu 		if (req->dlen != dtemplate[i].outlen) {
2193d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Decompression test %d failed for %s: output len = %d\n",
2194d7db7a88SGiovanni Cabiddu 			       i + 1, algo, req->dlen);
2195d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
219602608e02SLaura Abbott 			kfree(input_vec);
2197d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2198d7db7a88SGiovanni Cabiddu 			goto out;
2199d7db7a88SGiovanni Cabiddu 		}
2200d7db7a88SGiovanni Cabiddu 
2201d7db7a88SGiovanni Cabiddu 		if (memcmp(output, dtemplate[i].output, req->dlen)) {
2202d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Decompression test %d failed for %s\n",
2203d7db7a88SGiovanni Cabiddu 			       i + 1, algo);
2204d7db7a88SGiovanni Cabiddu 			hexdump(output, req->dlen);
2205d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
220602608e02SLaura Abbott 			kfree(input_vec);
2207d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2208d7db7a88SGiovanni Cabiddu 			goto out;
2209d7db7a88SGiovanni Cabiddu 		}
2210d7db7a88SGiovanni Cabiddu 
221102608e02SLaura Abbott 		kfree(input_vec);
2212d7db7a88SGiovanni Cabiddu 		acomp_request_free(req);
2213d7db7a88SGiovanni Cabiddu 	}
2214d7db7a88SGiovanni Cabiddu 
2215d7db7a88SGiovanni Cabiddu 	ret = 0;
2216d7db7a88SGiovanni Cabiddu 
2217d7db7a88SGiovanni Cabiddu out:
2218a9943a0aSGiovanni Cabiddu 	kfree(decomp_out);
2219eb095593SEric Biggers 	kfree(output);
2220d7db7a88SGiovanni Cabiddu 	return ret;
2221d7db7a88SGiovanni Cabiddu }
2222d7db7a88SGiovanni Cabiddu 
2223b13b1e0cSEric Biggers static int test_cprng(struct crypto_rng *tfm,
2224b13b1e0cSEric Biggers 		      const struct cprng_testvec *template,
22257647d6ceSJarod Wilson 		      unsigned int tcount)
22267647d6ceSJarod Wilson {
22277647d6ceSJarod Wilson 	const char *algo = crypto_tfm_alg_driver_name(crypto_rng_tfm(tfm));
2228fa4ef8a6SFelipe Contreras 	int err = 0, i, j, seedsize;
22297647d6ceSJarod Wilson 	u8 *seed;
22307647d6ceSJarod Wilson 	char result[32];
22317647d6ceSJarod Wilson 
22327647d6ceSJarod Wilson 	seedsize = crypto_rng_seedsize(tfm);
22337647d6ceSJarod Wilson 
22347647d6ceSJarod Wilson 	seed = kmalloc(seedsize, GFP_KERNEL);
22357647d6ceSJarod Wilson 	if (!seed) {
22367647d6ceSJarod Wilson 		printk(KERN_ERR "alg: cprng: Failed to allocate seed space "
22377647d6ceSJarod Wilson 		       "for %s\n", algo);
22387647d6ceSJarod Wilson 		return -ENOMEM;
22397647d6ceSJarod Wilson 	}
22407647d6ceSJarod Wilson 
22417647d6ceSJarod Wilson 	for (i = 0; i < tcount; i++) {
22427647d6ceSJarod Wilson 		memset(result, 0, 32);
22437647d6ceSJarod Wilson 
22447647d6ceSJarod Wilson 		memcpy(seed, template[i].v, template[i].vlen);
22457647d6ceSJarod Wilson 		memcpy(seed + template[i].vlen, template[i].key,
22467647d6ceSJarod Wilson 		       template[i].klen);
22477647d6ceSJarod Wilson 		memcpy(seed + template[i].vlen + template[i].klen,
22487647d6ceSJarod Wilson 		       template[i].dt, template[i].dtlen);
22497647d6ceSJarod Wilson 
22507647d6ceSJarod Wilson 		err = crypto_rng_reset(tfm, seed, seedsize);
22517647d6ceSJarod Wilson 		if (err) {
22527647d6ceSJarod Wilson 			printk(KERN_ERR "alg: cprng: Failed to reset rng "
22537647d6ceSJarod Wilson 			       "for %s\n", algo);
22547647d6ceSJarod Wilson 			goto out;
22557647d6ceSJarod Wilson 		}
22567647d6ceSJarod Wilson 
22577647d6ceSJarod Wilson 		for (j = 0; j < template[i].loops; j++) {
22587647d6ceSJarod Wilson 			err = crypto_rng_get_bytes(tfm, result,
22597647d6ceSJarod Wilson 						   template[i].rlen);
226019e60e13SStephan Mueller 			if (err < 0) {
22617647d6ceSJarod Wilson 				printk(KERN_ERR "alg: cprng: Failed to obtain "
22627647d6ceSJarod Wilson 				       "the correct amount of random data for "
226319e60e13SStephan Mueller 				       "%s (requested %d)\n", algo,
226419e60e13SStephan Mueller 				       template[i].rlen);
22657647d6ceSJarod Wilson 				goto out;
22667647d6ceSJarod Wilson 			}
22677647d6ceSJarod Wilson 		}
22687647d6ceSJarod Wilson 
22697647d6ceSJarod Wilson 		err = memcmp(result, template[i].result,
22707647d6ceSJarod Wilson 			     template[i].rlen);
22717647d6ceSJarod Wilson 		if (err) {
22727647d6ceSJarod Wilson 			printk(KERN_ERR "alg: cprng: Test %d failed for %s\n",
22737647d6ceSJarod Wilson 			       i, algo);
22747647d6ceSJarod Wilson 			hexdump(result, template[i].rlen);
22757647d6ceSJarod Wilson 			err = -EINVAL;
22767647d6ceSJarod Wilson 			goto out;
22777647d6ceSJarod Wilson 		}
22787647d6ceSJarod Wilson 	}
22797647d6ceSJarod Wilson 
22807647d6ceSJarod Wilson out:
22817647d6ceSJarod Wilson 	kfree(seed);
22827647d6ceSJarod Wilson 	return err;
22837647d6ceSJarod Wilson }
22847647d6ceSJarod Wilson 
2285da7f033dSHerbert Xu static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
2286da7f033dSHerbert Xu 			 u32 type, u32 mask)
2287da7f033dSHerbert Xu {
2288a0d608eeSEric Biggers 	const struct aead_test_suite *suite = &desc->suite.aead;
2289da7f033dSHerbert Xu 	struct crypto_aead *tfm;
2290a0d608eeSEric Biggers 	int err;
2291da7f033dSHerbert Xu 
2292eed93e0cSHerbert Xu 	tfm = crypto_alloc_aead(driver, type, mask);
2293da7f033dSHerbert Xu 	if (IS_ERR(tfm)) {
2294da7f033dSHerbert Xu 		printk(KERN_ERR "alg: aead: Failed to load transform for %s: "
2295da7f033dSHerbert Xu 		       "%ld\n", driver, PTR_ERR(tfm));
2296da7f033dSHerbert Xu 		return PTR_ERR(tfm);
2297da7f033dSHerbert Xu 	}
2298da7f033dSHerbert Xu 
2299a0d608eeSEric Biggers 	err = test_aead(tfm, ENCRYPT, suite->vecs, suite->count);
2300a0d608eeSEric Biggers 	if (!err)
2301a0d608eeSEric Biggers 		err = test_aead(tfm, DECRYPT, suite->vecs, suite->count);
2302da7f033dSHerbert Xu 
2303da7f033dSHerbert Xu 	crypto_free_aead(tfm);
2304da7f033dSHerbert Xu 	return err;
2305da7f033dSHerbert Xu }
2306da7f033dSHerbert Xu 
2307da7f033dSHerbert Xu static int alg_test_cipher(const struct alg_test_desc *desc,
2308da7f033dSHerbert Xu 			   const char *driver, u32 type, u32 mask)
2309da7f033dSHerbert Xu {
231092a4c9feSEric Biggers 	const struct cipher_test_suite *suite = &desc->suite.cipher;
23111aa4ecd9SHerbert Xu 	struct crypto_cipher *tfm;
231292a4c9feSEric Biggers 	int err;
2313da7f033dSHerbert Xu 
2314eed93e0cSHerbert Xu 	tfm = crypto_alloc_cipher(driver, type, mask);
2315da7f033dSHerbert Xu 	if (IS_ERR(tfm)) {
2316da7f033dSHerbert Xu 		printk(KERN_ERR "alg: cipher: Failed to load transform for "
2317da7f033dSHerbert Xu 		       "%s: %ld\n", driver, PTR_ERR(tfm));
2318da7f033dSHerbert Xu 		return PTR_ERR(tfm);
2319da7f033dSHerbert Xu 	}
2320da7f033dSHerbert Xu 
232192a4c9feSEric Biggers 	err = test_cipher(tfm, ENCRYPT, suite->vecs, suite->count);
232292a4c9feSEric Biggers 	if (!err)
232392a4c9feSEric Biggers 		err = test_cipher(tfm, DECRYPT, suite->vecs, suite->count);
2324da7f033dSHerbert Xu 
23251aa4ecd9SHerbert Xu 	crypto_free_cipher(tfm);
23261aa4ecd9SHerbert Xu 	return err;
23271aa4ecd9SHerbert Xu }
23281aa4ecd9SHerbert Xu 
23291aa4ecd9SHerbert Xu static int alg_test_skcipher(const struct alg_test_desc *desc,
23301aa4ecd9SHerbert Xu 			     const char *driver, u32 type, u32 mask)
23311aa4ecd9SHerbert Xu {
233292a4c9feSEric Biggers 	const struct cipher_test_suite *suite = &desc->suite.cipher;
233312773d93SHerbert Xu 	struct crypto_skcipher *tfm;
233492a4c9feSEric Biggers 	int err;
23351aa4ecd9SHerbert Xu 
2336eed93e0cSHerbert Xu 	tfm = crypto_alloc_skcipher(driver, type, mask);
23371aa4ecd9SHerbert Xu 	if (IS_ERR(tfm)) {
23381aa4ecd9SHerbert Xu 		printk(KERN_ERR "alg: skcipher: Failed to load transform for "
23391aa4ecd9SHerbert Xu 		       "%s: %ld\n", driver, PTR_ERR(tfm));
23401aa4ecd9SHerbert Xu 		return PTR_ERR(tfm);
23411aa4ecd9SHerbert Xu 	}
23421aa4ecd9SHerbert Xu 
234392a4c9feSEric Biggers 	err = test_skcipher(tfm, ENCRYPT, suite->vecs, suite->count);
234492a4c9feSEric Biggers 	if (!err)
234592a4c9feSEric Biggers 		err = test_skcipher(tfm, DECRYPT, suite->vecs, suite->count);
23461aa4ecd9SHerbert Xu 
234712773d93SHerbert Xu 	crypto_free_skcipher(tfm);
2348da7f033dSHerbert Xu 	return err;
2349da7f033dSHerbert Xu }
2350da7f033dSHerbert Xu 
2351da7f033dSHerbert Xu static int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
2352da7f033dSHerbert Xu 			 u32 type, u32 mask)
2353da7f033dSHerbert Xu {
2354d7db7a88SGiovanni Cabiddu 	struct crypto_comp *comp;
2355d7db7a88SGiovanni Cabiddu 	struct crypto_acomp *acomp;
2356da7f033dSHerbert Xu 	int err;
2357d7db7a88SGiovanni Cabiddu 	u32 algo_type = type & CRYPTO_ALG_TYPE_ACOMPRESS_MASK;
2358da7f033dSHerbert Xu 
2359d7db7a88SGiovanni Cabiddu 	if (algo_type == CRYPTO_ALG_TYPE_ACOMPRESS) {
2360d7db7a88SGiovanni Cabiddu 		acomp = crypto_alloc_acomp(driver, type, mask);
2361d7db7a88SGiovanni Cabiddu 		if (IS_ERR(acomp)) {
2362d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Failed to load transform for %s: %ld\n",
2363d7db7a88SGiovanni Cabiddu 			       driver, PTR_ERR(acomp));
2364d7db7a88SGiovanni Cabiddu 			return PTR_ERR(acomp);
2365d7db7a88SGiovanni Cabiddu 		}
2366d7db7a88SGiovanni Cabiddu 		err = test_acomp(acomp, desc->suite.comp.comp.vecs,
2367d7db7a88SGiovanni Cabiddu 				 desc->suite.comp.decomp.vecs,
2368d7db7a88SGiovanni Cabiddu 				 desc->suite.comp.comp.count,
2369d7db7a88SGiovanni Cabiddu 				 desc->suite.comp.decomp.count);
2370d7db7a88SGiovanni Cabiddu 		crypto_free_acomp(acomp);
2371d7db7a88SGiovanni Cabiddu 	} else {
2372d7db7a88SGiovanni Cabiddu 		comp = crypto_alloc_comp(driver, type, mask);
2373d7db7a88SGiovanni Cabiddu 		if (IS_ERR(comp)) {
2374d7db7a88SGiovanni Cabiddu 			pr_err("alg: comp: Failed to load transform for %s: %ld\n",
2375d7db7a88SGiovanni Cabiddu 			       driver, PTR_ERR(comp));
2376d7db7a88SGiovanni Cabiddu 			return PTR_ERR(comp);
2377da7f033dSHerbert Xu 		}
2378da7f033dSHerbert Xu 
2379d7db7a88SGiovanni Cabiddu 		err = test_comp(comp, desc->suite.comp.comp.vecs,
2380da7f033dSHerbert Xu 				desc->suite.comp.decomp.vecs,
2381da7f033dSHerbert Xu 				desc->suite.comp.comp.count,
2382da7f033dSHerbert Xu 				desc->suite.comp.decomp.count);
2383da7f033dSHerbert Xu 
2384d7db7a88SGiovanni Cabiddu 		crypto_free_comp(comp);
2385d7db7a88SGiovanni Cabiddu 	}
2386da7f033dSHerbert Xu 	return err;
2387da7f033dSHerbert Xu }
2388da7f033dSHerbert Xu 
23899b3abc01SEric Biggers static int __alg_test_hash(const struct hash_testvec *template,
23909b3abc01SEric Biggers 			   unsigned int tcount, const char *driver,
2391da7f033dSHerbert Xu 			   u32 type, u32 mask)
2392da7f033dSHerbert Xu {
2393da7f033dSHerbert Xu 	struct crypto_ahash *tfm;
2394da7f033dSHerbert Xu 	int err;
2395da7f033dSHerbert Xu 
2396eed93e0cSHerbert Xu 	tfm = crypto_alloc_ahash(driver, type, mask);
2397da7f033dSHerbert Xu 	if (IS_ERR(tfm)) {
2398da7f033dSHerbert Xu 		printk(KERN_ERR "alg: hash: Failed to load transform for %s: "
2399da7f033dSHerbert Xu 		       "%ld\n", driver, PTR_ERR(tfm));
2400da7f033dSHerbert Xu 		return PTR_ERR(tfm);
2401da7f033dSHerbert Xu 	}
2402da7f033dSHerbert Xu 
240376715095SGilad Ben-Yossef 	err = test_hash(tfm, template, tcount, HASH_TEST_DIGEST);
2404a8f1a052SDavid S. Miller 	if (!err)
240576715095SGilad Ben-Yossef 		err = test_hash(tfm, template, tcount, HASH_TEST_FINAL);
240676715095SGilad Ben-Yossef 	if (!err)
240776715095SGilad Ben-Yossef 		err = test_hash(tfm, template, tcount, HASH_TEST_FINUP);
2408da7f033dSHerbert Xu 	crypto_free_ahash(tfm);
2409da7f033dSHerbert Xu 	return err;
2410da7f033dSHerbert Xu }
2411da7f033dSHerbert Xu 
24129b3abc01SEric Biggers static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
24139b3abc01SEric Biggers 			 u32 type, u32 mask)
24149b3abc01SEric Biggers {
24159b3abc01SEric Biggers 	const struct hash_testvec *template = desc->suite.hash.vecs;
24169b3abc01SEric Biggers 	unsigned int tcount = desc->suite.hash.count;
24179b3abc01SEric Biggers 	unsigned int nr_unkeyed, nr_keyed;
24189b3abc01SEric Biggers 	int err;
24199b3abc01SEric Biggers 
24209b3abc01SEric Biggers 	/*
24219b3abc01SEric Biggers 	 * For OPTIONAL_KEY algorithms, we have to do all the unkeyed tests
24229b3abc01SEric Biggers 	 * first, before setting a key on the tfm.  To make this easier, we
24239b3abc01SEric Biggers 	 * require that the unkeyed test vectors (if any) are listed first.
24249b3abc01SEric Biggers 	 */
24259b3abc01SEric Biggers 
24269b3abc01SEric Biggers 	for (nr_unkeyed = 0; nr_unkeyed < tcount; nr_unkeyed++) {
24279b3abc01SEric Biggers 		if (template[nr_unkeyed].ksize)
24289b3abc01SEric Biggers 			break;
24299b3abc01SEric Biggers 	}
24309b3abc01SEric Biggers 	for (nr_keyed = 0; nr_unkeyed + nr_keyed < tcount; nr_keyed++) {
24319b3abc01SEric Biggers 		if (!template[nr_unkeyed + nr_keyed].ksize) {
24329b3abc01SEric Biggers 			pr_err("alg: hash: test vectors for %s out of order, "
24339b3abc01SEric Biggers 			       "unkeyed ones must come first\n", desc->alg);
24349b3abc01SEric Biggers 			return -EINVAL;
24359b3abc01SEric Biggers 		}
24369b3abc01SEric Biggers 	}
24379b3abc01SEric Biggers 
24389b3abc01SEric Biggers 	err = 0;
24399b3abc01SEric Biggers 	if (nr_unkeyed) {
24409b3abc01SEric Biggers 		err = __alg_test_hash(template, nr_unkeyed, driver, type, mask);
24419b3abc01SEric Biggers 		template += nr_unkeyed;
24429b3abc01SEric Biggers 	}
24439b3abc01SEric Biggers 
24449b3abc01SEric Biggers 	if (!err && nr_keyed)
24459b3abc01SEric Biggers 		err = __alg_test_hash(template, nr_keyed, driver, type, mask);
24469b3abc01SEric Biggers 
24479b3abc01SEric Biggers 	return err;
24489b3abc01SEric Biggers }
24499b3abc01SEric Biggers 
24508e3ee85eSHerbert Xu static int alg_test_crc32c(const struct alg_test_desc *desc,
24518e3ee85eSHerbert Xu 			   const char *driver, u32 type, u32 mask)
24528e3ee85eSHerbert Xu {
24538e3ee85eSHerbert Xu 	struct crypto_shash *tfm;
2454cb9dde88SEric Biggers 	__le32 val;
24558e3ee85eSHerbert Xu 	int err;
24568e3ee85eSHerbert Xu 
24578e3ee85eSHerbert Xu 	err = alg_test_hash(desc, driver, type, mask);
24588e3ee85eSHerbert Xu 	if (err)
2459eb5e6730SEric Biggers 		return err;
24608e3ee85eSHerbert Xu 
2461eed93e0cSHerbert Xu 	tfm = crypto_alloc_shash(driver, type, mask);
24628e3ee85eSHerbert Xu 	if (IS_ERR(tfm)) {
2463eb5e6730SEric Biggers 		if (PTR_ERR(tfm) == -ENOENT) {
2464eb5e6730SEric Biggers 			/*
2465eb5e6730SEric Biggers 			 * This crc32c implementation is only available through
2466eb5e6730SEric Biggers 			 * ahash API, not the shash API, so the remaining part
2467eb5e6730SEric Biggers 			 * of the test is not applicable to it.
2468eb5e6730SEric Biggers 			 */
2469eb5e6730SEric Biggers 			return 0;
2470eb5e6730SEric Biggers 		}
24718e3ee85eSHerbert Xu 		printk(KERN_ERR "alg: crc32c: Failed to load transform for %s: "
24728e3ee85eSHerbert Xu 		       "%ld\n", driver, PTR_ERR(tfm));
2473eb5e6730SEric Biggers 		return PTR_ERR(tfm);
24748e3ee85eSHerbert Xu 	}
24758e3ee85eSHerbert Xu 
24768e3ee85eSHerbert Xu 	do {
24774c5c3024SJan-Simon Möller 		SHASH_DESC_ON_STACK(shash, tfm);
24784c5c3024SJan-Simon Möller 		u32 *ctx = (u32 *)shash_desc_ctx(shash);
24798e3ee85eSHerbert Xu 
24804c5c3024SJan-Simon Möller 		shash->tfm = tfm;
24814c5c3024SJan-Simon Möller 		shash->flags = 0;
24828e3ee85eSHerbert Xu 
2483cb9dde88SEric Biggers 		*ctx = 420553207;
24844c5c3024SJan-Simon Möller 		err = crypto_shash_final(shash, (u8 *)&val);
24858e3ee85eSHerbert Xu 		if (err) {
24868e3ee85eSHerbert Xu 			printk(KERN_ERR "alg: crc32c: Operation failed for "
24878e3ee85eSHerbert Xu 			       "%s: %d\n", driver, err);
24888e3ee85eSHerbert Xu 			break;
24898e3ee85eSHerbert Xu 		}
24908e3ee85eSHerbert Xu 
2491cb9dde88SEric Biggers 		if (val != cpu_to_le32(~420553207)) {
2492cb9dde88SEric Biggers 			pr_err("alg: crc32c: Test failed for %s: %u\n",
2493cb9dde88SEric Biggers 			       driver, le32_to_cpu(val));
24948e3ee85eSHerbert Xu 			err = -EINVAL;
24958e3ee85eSHerbert Xu 		}
24968e3ee85eSHerbert Xu 	} while (0);
24978e3ee85eSHerbert Xu 
24988e3ee85eSHerbert Xu 	crypto_free_shash(tfm);
24998e3ee85eSHerbert Xu 
25008e3ee85eSHerbert Xu 	return err;
25018e3ee85eSHerbert Xu }
25028e3ee85eSHerbert Xu 
25037647d6ceSJarod Wilson static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
25047647d6ceSJarod Wilson 			  u32 type, u32 mask)
25057647d6ceSJarod Wilson {
25067647d6ceSJarod Wilson 	struct crypto_rng *rng;
25077647d6ceSJarod Wilson 	int err;
25087647d6ceSJarod Wilson 
2509eed93e0cSHerbert Xu 	rng = crypto_alloc_rng(driver, type, mask);
25107647d6ceSJarod Wilson 	if (IS_ERR(rng)) {
25117647d6ceSJarod Wilson 		printk(KERN_ERR "alg: cprng: Failed to load transform for %s: "
25127647d6ceSJarod Wilson 		       "%ld\n", driver, PTR_ERR(rng));
25137647d6ceSJarod Wilson 		return PTR_ERR(rng);
25147647d6ceSJarod Wilson 	}
25157647d6ceSJarod Wilson 
25167647d6ceSJarod Wilson 	err = test_cprng(rng, desc->suite.cprng.vecs, desc->suite.cprng.count);
25177647d6ceSJarod Wilson 
25187647d6ceSJarod Wilson 	crypto_free_rng(rng);
25197647d6ceSJarod Wilson 
25207647d6ceSJarod Wilson 	return err;
25217647d6ceSJarod Wilson }
25227647d6ceSJarod Wilson 
252364d1cdfbSStephan Mueller 
2524b13b1e0cSEric Biggers static int drbg_cavs_test(const struct drbg_testvec *test, int pr,
252564d1cdfbSStephan Mueller 			  const char *driver, u32 type, u32 mask)
252664d1cdfbSStephan Mueller {
252764d1cdfbSStephan Mueller 	int ret = -EAGAIN;
252864d1cdfbSStephan Mueller 	struct crypto_rng *drng;
252964d1cdfbSStephan Mueller 	struct drbg_test_data test_data;
253064d1cdfbSStephan Mueller 	struct drbg_string addtl, pers, testentropy;
253164d1cdfbSStephan Mueller 	unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
253264d1cdfbSStephan Mueller 
253364d1cdfbSStephan Mueller 	if (!buf)
253464d1cdfbSStephan Mueller 		return -ENOMEM;
253564d1cdfbSStephan Mueller 
2536eed93e0cSHerbert Xu 	drng = crypto_alloc_rng(driver, type, mask);
253764d1cdfbSStephan Mueller 	if (IS_ERR(drng)) {
253864d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for "
253964d1cdfbSStephan Mueller 		       "%s\n", driver);
254064d1cdfbSStephan Mueller 		kzfree(buf);
254164d1cdfbSStephan Mueller 		return -ENOMEM;
254264d1cdfbSStephan Mueller 	}
254364d1cdfbSStephan Mueller 
254464d1cdfbSStephan Mueller 	test_data.testentropy = &testentropy;
254564d1cdfbSStephan Mueller 	drbg_string_fill(&testentropy, test->entropy, test->entropylen);
254664d1cdfbSStephan Mueller 	drbg_string_fill(&pers, test->pers, test->perslen);
254764d1cdfbSStephan Mueller 	ret = crypto_drbg_reset_test(drng, &pers, &test_data);
254864d1cdfbSStephan Mueller 	if (ret) {
254964d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
255064d1cdfbSStephan Mueller 		goto outbuf;
255164d1cdfbSStephan Mueller 	}
255264d1cdfbSStephan Mueller 
255364d1cdfbSStephan Mueller 	drbg_string_fill(&addtl, test->addtla, test->addtllen);
255464d1cdfbSStephan Mueller 	if (pr) {
255564d1cdfbSStephan Mueller 		drbg_string_fill(&testentropy, test->entpra, test->entprlen);
255664d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl_test(drng,
255764d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl,	&test_data);
255864d1cdfbSStephan Mueller 	} else {
255964d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl(drng,
256064d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl);
256164d1cdfbSStephan Mueller 	}
256219e60e13SStephan Mueller 	if (ret < 0) {
256364d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: could not obtain random data for "
256464d1cdfbSStephan Mueller 		       "driver %s\n", driver);
256564d1cdfbSStephan Mueller 		goto outbuf;
256664d1cdfbSStephan Mueller 	}
256764d1cdfbSStephan Mueller 
256864d1cdfbSStephan Mueller 	drbg_string_fill(&addtl, test->addtlb, test->addtllen);
256964d1cdfbSStephan Mueller 	if (pr) {
257064d1cdfbSStephan Mueller 		drbg_string_fill(&testentropy, test->entprb, test->entprlen);
257164d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl_test(drng,
257264d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl, &test_data);
257364d1cdfbSStephan Mueller 	} else {
257464d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl(drng,
257564d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl);
257664d1cdfbSStephan Mueller 	}
257719e60e13SStephan Mueller 	if (ret < 0) {
257864d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: could not obtain random data for "
257964d1cdfbSStephan Mueller 		       "driver %s\n", driver);
258064d1cdfbSStephan Mueller 		goto outbuf;
258164d1cdfbSStephan Mueller 	}
258264d1cdfbSStephan Mueller 
258364d1cdfbSStephan Mueller 	ret = memcmp(test->expected, buf, test->expectedlen);
258464d1cdfbSStephan Mueller 
258564d1cdfbSStephan Mueller outbuf:
258664d1cdfbSStephan Mueller 	crypto_free_rng(drng);
258764d1cdfbSStephan Mueller 	kzfree(buf);
258864d1cdfbSStephan Mueller 	return ret;
258964d1cdfbSStephan Mueller }
259064d1cdfbSStephan Mueller 
259164d1cdfbSStephan Mueller 
259264d1cdfbSStephan Mueller static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
259364d1cdfbSStephan Mueller 			 u32 type, u32 mask)
259464d1cdfbSStephan Mueller {
259564d1cdfbSStephan Mueller 	int err = 0;
259664d1cdfbSStephan Mueller 	int pr = 0;
259764d1cdfbSStephan Mueller 	int i = 0;
2598b13b1e0cSEric Biggers 	const struct drbg_testvec *template = desc->suite.drbg.vecs;
259964d1cdfbSStephan Mueller 	unsigned int tcount = desc->suite.drbg.count;
260064d1cdfbSStephan Mueller 
260164d1cdfbSStephan Mueller 	if (0 == memcmp(driver, "drbg_pr_", 8))
260264d1cdfbSStephan Mueller 		pr = 1;
260364d1cdfbSStephan Mueller 
260464d1cdfbSStephan Mueller 	for (i = 0; i < tcount; i++) {
260564d1cdfbSStephan Mueller 		err = drbg_cavs_test(&template[i], pr, driver, type, mask);
260664d1cdfbSStephan Mueller 		if (err) {
260764d1cdfbSStephan Mueller 			printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
260864d1cdfbSStephan Mueller 			       i, driver);
260964d1cdfbSStephan Mueller 			err = -EINVAL;
261064d1cdfbSStephan Mueller 			break;
261164d1cdfbSStephan Mueller 		}
261264d1cdfbSStephan Mueller 	}
261364d1cdfbSStephan Mueller 	return err;
261464d1cdfbSStephan Mueller 
261564d1cdfbSStephan Mueller }
261664d1cdfbSStephan Mueller 
2617b13b1e0cSEric Biggers static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
2618802c7f1cSSalvatore Benedetto 		       const char *alg)
2619802c7f1cSSalvatore Benedetto {
2620802c7f1cSSalvatore Benedetto 	struct kpp_request *req;
2621802c7f1cSSalvatore Benedetto 	void *input_buf = NULL;
2622802c7f1cSSalvatore Benedetto 	void *output_buf = NULL;
262347d3fd39STudor-Dan Ambarus 	void *a_public = NULL;
262447d3fd39STudor-Dan Ambarus 	void *a_ss = NULL;
262547d3fd39STudor-Dan Ambarus 	void *shared_secret = NULL;
26267f397136SGilad Ben-Yossef 	struct crypto_wait wait;
2627802c7f1cSSalvatore Benedetto 	unsigned int out_len_max;
2628802c7f1cSSalvatore Benedetto 	int err = -ENOMEM;
2629802c7f1cSSalvatore Benedetto 	struct scatterlist src, dst;
2630802c7f1cSSalvatore Benedetto 
2631802c7f1cSSalvatore Benedetto 	req = kpp_request_alloc(tfm, GFP_KERNEL);
2632802c7f1cSSalvatore Benedetto 	if (!req)
2633802c7f1cSSalvatore Benedetto 		return err;
2634802c7f1cSSalvatore Benedetto 
26357f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
2636802c7f1cSSalvatore Benedetto 
2637802c7f1cSSalvatore Benedetto 	err = crypto_kpp_set_secret(tfm, vec->secret, vec->secret_size);
2638802c7f1cSSalvatore Benedetto 	if (err < 0)
2639802c7f1cSSalvatore Benedetto 		goto free_req;
2640802c7f1cSSalvatore Benedetto 
2641802c7f1cSSalvatore Benedetto 	out_len_max = crypto_kpp_maxsize(tfm);
2642802c7f1cSSalvatore Benedetto 	output_buf = kzalloc(out_len_max, GFP_KERNEL);
2643802c7f1cSSalvatore Benedetto 	if (!output_buf) {
2644802c7f1cSSalvatore Benedetto 		err = -ENOMEM;
2645802c7f1cSSalvatore Benedetto 		goto free_req;
2646802c7f1cSSalvatore Benedetto 	}
2647802c7f1cSSalvatore Benedetto 
2648802c7f1cSSalvatore Benedetto 	/* Use appropriate parameter as base */
2649802c7f1cSSalvatore Benedetto 	kpp_request_set_input(req, NULL, 0);
2650802c7f1cSSalvatore Benedetto 	sg_init_one(&dst, output_buf, out_len_max);
2651802c7f1cSSalvatore Benedetto 	kpp_request_set_output(req, &dst, out_len_max);
2652802c7f1cSSalvatore Benedetto 	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
26537f397136SGilad Ben-Yossef 				 crypto_req_done, &wait);
2654802c7f1cSSalvatore Benedetto 
265547d3fd39STudor-Dan Ambarus 	/* Compute party A's public key */
26567f397136SGilad Ben-Yossef 	err = crypto_wait_req(crypto_kpp_generate_public_key(req), &wait);
2657802c7f1cSSalvatore Benedetto 	if (err) {
265847d3fd39STudor-Dan Ambarus 		pr_err("alg: %s: Party A: generate public key test failed. err %d\n",
2659802c7f1cSSalvatore Benedetto 		       alg, err);
2660802c7f1cSSalvatore Benedetto 		goto free_output;
2661802c7f1cSSalvatore Benedetto 	}
266247d3fd39STudor-Dan Ambarus 
266347d3fd39STudor-Dan Ambarus 	if (vec->genkey) {
266447d3fd39STudor-Dan Ambarus 		/* Save party A's public key */
2665e3d90e52SChristopher Diaz Riveros 		a_public = kmemdup(sg_virt(req->dst), out_len_max, GFP_KERNEL);
266647d3fd39STudor-Dan Ambarus 		if (!a_public) {
266747d3fd39STudor-Dan Ambarus 			err = -ENOMEM;
266847d3fd39STudor-Dan Ambarus 			goto free_output;
266947d3fd39STudor-Dan Ambarus 		}
267047d3fd39STudor-Dan Ambarus 	} else {
2671802c7f1cSSalvatore Benedetto 		/* Verify calculated public key */
2672802c7f1cSSalvatore Benedetto 		if (memcmp(vec->expected_a_public, sg_virt(req->dst),
2673802c7f1cSSalvatore Benedetto 			   vec->expected_a_public_size)) {
267447d3fd39STudor-Dan Ambarus 			pr_err("alg: %s: Party A: generate public key test failed. Invalid output\n",
2675802c7f1cSSalvatore Benedetto 			       alg);
2676802c7f1cSSalvatore Benedetto 			err = -EINVAL;
2677802c7f1cSSalvatore Benedetto 			goto free_output;
2678802c7f1cSSalvatore Benedetto 		}
267947d3fd39STudor-Dan Ambarus 	}
2680802c7f1cSSalvatore Benedetto 
2681802c7f1cSSalvatore Benedetto 	/* Calculate shared secret key by using counter part (b) public key. */
2682e3d90e52SChristopher Diaz Riveros 	input_buf = kmemdup(vec->b_public, vec->b_public_size, GFP_KERNEL);
2683802c7f1cSSalvatore Benedetto 	if (!input_buf) {
2684802c7f1cSSalvatore Benedetto 		err = -ENOMEM;
2685802c7f1cSSalvatore Benedetto 		goto free_output;
2686802c7f1cSSalvatore Benedetto 	}
2687802c7f1cSSalvatore Benedetto 
2688802c7f1cSSalvatore Benedetto 	sg_init_one(&src, input_buf, vec->b_public_size);
2689802c7f1cSSalvatore Benedetto 	sg_init_one(&dst, output_buf, out_len_max);
2690802c7f1cSSalvatore Benedetto 	kpp_request_set_input(req, &src, vec->b_public_size);
2691802c7f1cSSalvatore Benedetto 	kpp_request_set_output(req, &dst, out_len_max);
2692802c7f1cSSalvatore Benedetto 	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
26937f397136SGilad Ben-Yossef 				 crypto_req_done, &wait);
26947f397136SGilad Ben-Yossef 	err = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait);
2695802c7f1cSSalvatore Benedetto 	if (err) {
269647d3fd39STudor-Dan Ambarus 		pr_err("alg: %s: Party A: compute shared secret test failed. err %d\n",
2697802c7f1cSSalvatore Benedetto 		       alg, err);
2698802c7f1cSSalvatore Benedetto 		goto free_all;
2699802c7f1cSSalvatore Benedetto 	}
270047d3fd39STudor-Dan Ambarus 
270147d3fd39STudor-Dan Ambarus 	if (vec->genkey) {
270247d3fd39STudor-Dan Ambarus 		/* Save the shared secret obtained by party A */
2703e3d90e52SChristopher Diaz Riveros 		a_ss = kmemdup(sg_virt(req->dst), vec->expected_ss_size, GFP_KERNEL);
270447d3fd39STudor-Dan Ambarus 		if (!a_ss) {
270547d3fd39STudor-Dan Ambarus 			err = -ENOMEM;
270647d3fd39STudor-Dan Ambarus 			goto free_all;
270747d3fd39STudor-Dan Ambarus 		}
270847d3fd39STudor-Dan Ambarus 
270947d3fd39STudor-Dan Ambarus 		/*
271047d3fd39STudor-Dan Ambarus 		 * Calculate party B's shared secret by using party A's
271147d3fd39STudor-Dan Ambarus 		 * public key.
271247d3fd39STudor-Dan Ambarus 		 */
271347d3fd39STudor-Dan Ambarus 		err = crypto_kpp_set_secret(tfm, vec->b_secret,
271447d3fd39STudor-Dan Ambarus 					    vec->b_secret_size);
271547d3fd39STudor-Dan Ambarus 		if (err < 0)
271647d3fd39STudor-Dan Ambarus 			goto free_all;
271747d3fd39STudor-Dan Ambarus 
271847d3fd39STudor-Dan Ambarus 		sg_init_one(&src, a_public, vec->expected_a_public_size);
271947d3fd39STudor-Dan Ambarus 		sg_init_one(&dst, output_buf, out_len_max);
272047d3fd39STudor-Dan Ambarus 		kpp_request_set_input(req, &src, vec->expected_a_public_size);
272147d3fd39STudor-Dan Ambarus 		kpp_request_set_output(req, &dst, out_len_max);
272247d3fd39STudor-Dan Ambarus 		kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
27237f397136SGilad Ben-Yossef 					 crypto_req_done, &wait);
27247f397136SGilad Ben-Yossef 		err = crypto_wait_req(crypto_kpp_compute_shared_secret(req),
27257f397136SGilad Ben-Yossef 				      &wait);
272647d3fd39STudor-Dan Ambarus 		if (err) {
272747d3fd39STudor-Dan Ambarus 			pr_err("alg: %s: Party B: compute shared secret failed. err %d\n",
272847d3fd39STudor-Dan Ambarus 			       alg, err);
272947d3fd39STudor-Dan Ambarus 			goto free_all;
273047d3fd39STudor-Dan Ambarus 		}
273147d3fd39STudor-Dan Ambarus 
273247d3fd39STudor-Dan Ambarus 		shared_secret = a_ss;
273347d3fd39STudor-Dan Ambarus 	} else {
273447d3fd39STudor-Dan Ambarus 		shared_secret = (void *)vec->expected_ss;
273547d3fd39STudor-Dan Ambarus 	}
273647d3fd39STudor-Dan Ambarus 
2737802c7f1cSSalvatore Benedetto 	/*
2738802c7f1cSSalvatore Benedetto 	 * verify shared secret from which the user will derive
2739802c7f1cSSalvatore Benedetto 	 * secret key by executing whatever hash it has chosen
2740802c7f1cSSalvatore Benedetto 	 */
274147d3fd39STudor-Dan Ambarus 	if (memcmp(shared_secret, sg_virt(req->dst),
2742802c7f1cSSalvatore Benedetto 		   vec->expected_ss_size)) {
2743802c7f1cSSalvatore Benedetto 		pr_err("alg: %s: compute shared secret test failed. Invalid output\n",
2744802c7f1cSSalvatore Benedetto 		       alg);
2745802c7f1cSSalvatore Benedetto 		err = -EINVAL;
2746802c7f1cSSalvatore Benedetto 	}
2747802c7f1cSSalvatore Benedetto 
2748802c7f1cSSalvatore Benedetto free_all:
274947d3fd39STudor-Dan Ambarus 	kfree(a_ss);
2750802c7f1cSSalvatore Benedetto 	kfree(input_buf);
2751802c7f1cSSalvatore Benedetto free_output:
275247d3fd39STudor-Dan Ambarus 	kfree(a_public);
2753802c7f1cSSalvatore Benedetto 	kfree(output_buf);
2754802c7f1cSSalvatore Benedetto free_req:
2755802c7f1cSSalvatore Benedetto 	kpp_request_free(req);
2756802c7f1cSSalvatore Benedetto 	return err;
2757802c7f1cSSalvatore Benedetto }
2758802c7f1cSSalvatore Benedetto 
2759802c7f1cSSalvatore Benedetto static int test_kpp(struct crypto_kpp *tfm, const char *alg,
2760b13b1e0cSEric Biggers 		    const struct kpp_testvec *vecs, unsigned int tcount)
2761802c7f1cSSalvatore Benedetto {
2762802c7f1cSSalvatore Benedetto 	int ret, i;
2763802c7f1cSSalvatore Benedetto 
2764802c7f1cSSalvatore Benedetto 	for (i = 0; i < tcount; i++) {
2765802c7f1cSSalvatore Benedetto 		ret = do_test_kpp(tfm, vecs++, alg);
2766802c7f1cSSalvatore Benedetto 		if (ret) {
2767802c7f1cSSalvatore Benedetto 			pr_err("alg: %s: test failed on vector %d, err=%d\n",
2768802c7f1cSSalvatore Benedetto 			       alg, i + 1, ret);
2769802c7f1cSSalvatore Benedetto 			return ret;
2770802c7f1cSSalvatore Benedetto 		}
2771802c7f1cSSalvatore Benedetto 	}
2772802c7f1cSSalvatore Benedetto 	return 0;
2773802c7f1cSSalvatore Benedetto }
2774802c7f1cSSalvatore Benedetto 
2775802c7f1cSSalvatore Benedetto static int alg_test_kpp(const struct alg_test_desc *desc, const char *driver,
2776802c7f1cSSalvatore Benedetto 			u32 type, u32 mask)
2777802c7f1cSSalvatore Benedetto {
2778802c7f1cSSalvatore Benedetto 	struct crypto_kpp *tfm;
2779802c7f1cSSalvatore Benedetto 	int err = 0;
2780802c7f1cSSalvatore Benedetto 
2781eed93e0cSHerbert Xu 	tfm = crypto_alloc_kpp(driver, type, mask);
2782802c7f1cSSalvatore Benedetto 	if (IS_ERR(tfm)) {
2783802c7f1cSSalvatore Benedetto 		pr_err("alg: kpp: Failed to load tfm for %s: %ld\n",
2784802c7f1cSSalvatore Benedetto 		       driver, PTR_ERR(tfm));
2785802c7f1cSSalvatore Benedetto 		return PTR_ERR(tfm);
2786802c7f1cSSalvatore Benedetto 	}
2787802c7f1cSSalvatore Benedetto 	if (desc->suite.kpp.vecs)
2788802c7f1cSSalvatore Benedetto 		err = test_kpp(tfm, desc->alg, desc->suite.kpp.vecs,
2789802c7f1cSSalvatore Benedetto 			       desc->suite.kpp.count);
2790802c7f1cSSalvatore Benedetto 
2791802c7f1cSSalvatore Benedetto 	crypto_free_kpp(tfm);
2792802c7f1cSSalvatore Benedetto 	return err;
2793802c7f1cSSalvatore Benedetto }
2794802c7f1cSSalvatore Benedetto 
279550d2b643SHerbert Xu static int test_akcipher_one(struct crypto_akcipher *tfm,
2796b13b1e0cSEric Biggers 			     const struct akcipher_testvec *vecs)
2797946cc463STadeusz Struk {
2798df27b26fSHerbert Xu 	char *xbuf[XBUFSIZE];
2799946cc463STadeusz Struk 	struct akcipher_request *req;
2800946cc463STadeusz Struk 	void *outbuf_enc = NULL;
2801946cc463STadeusz Struk 	void *outbuf_dec = NULL;
28027f397136SGilad Ben-Yossef 	struct crypto_wait wait;
2803946cc463STadeusz Struk 	unsigned int out_len_max, out_len = 0;
2804946cc463STadeusz Struk 	int err = -ENOMEM;
280522287b0bSTadeusz Struk 	struct scatterlist src, dst, src_tab[2];
28060507de94SVitaly Chikunov 	const char *m, *c;
28070507de94SVitaly Chikunov 	unsigned int m_size, c_size;
28080507de94SVitaly Chikunov 	const char *op;
2809946cc463STadeusz Struk 
2810df27b26fSHerbert Xu 	if (testmgr_alloc_buf(xbuf))
2811df27b26fSHerbert Xu 		return err;
2812df27b26fSHerbert Xu 
2813946cc463STadeusz Struk 	req = akcipher_request_alloc(tfm, GFP_KERNEL);
2814946cc463STadeusz Struk 	if (!req)
2815df27b26fSHerbert Xu 		goto free_xbuf;
2816946cc463STadeusz Struk 
28177f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
281822287b0bSTadeusz Struk 
281922287b0bSTadeusz Struk 	if (vecs->public_key_vec)
282022287b0bSTadeusz Struk 		err = crypto_akcipher_set_pub_key(tfm, vecs->key,
282122287b0bSTadeusz Struk 						  vecs->key_len);
282222287b0bSTadeusz Struk 	else
282322287b0bSTadeusz Struk 		err = crypto_akcipher_set_priv_key(tfm, vecs->key,
282422287b0bSTadeusz Struk 						   vecs->key_len);
2825946cc463STadeusz Struk 	if (err)
2826946cc463STadeusz Struk 		goto free_req;
2827946cc463STadeusz Struk 
282857763f5eSSalvatore Benedetto 	err = -ENOMEM;
282922287b0bSTadeusz Struk 	out_len_max = crypto_akcipher_maxsize(tfm);
28300507de94SVitaly Chikunov 
28310507de94SVitaly Chikunov 	/*
28320507de94SVitaly Chikunov 	 * First run test which do not require a private key, such as
28330507de94SVitaly Chikunov 	 * encrypt or verify.
28340507de94SVitaly Chikunov 	 */
2835946cc463STadeusz Struk 	outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
2836946cc463STadeusz Struk 	if (!outbuf_enc)
2837946cc463STadeusz Struk 		goto free_req;
2838946cc463STadeusz Struk 
28390507de94SVitaly Chikunov 	if (!vecs->siggen_sigver_test) {
28400507de94SVitaly Chikunov 		m = vecs->m;
28410507de94SVitaly Chikunov 		m_size = vecs->m_size;
28420507de94SVitaly Chikunov 		c = vecs->c;
28430507de94SVitaly Chikunov 		c_size = vecs->c_size;
28440507de94SVitaly Chikunov 		op = "encrypt";
28450507de94SVitaly Chikunov 	} else {
28460507de94SVitaly Chikunov 		/* Swap args so we could keep plaintext (digest)
28470507de94SVitaly Chikunov 		 * in vecs->m, and cooked signature in vecs->c.
28480507de94SVitaly Chikunov 		 */
28490507de94SVitaly Chikunov 		m = vecs->c; /* signature */
28500507de94SVitaly Chikunov 		m_size = vecs->c_size;
28510507de94SVitaly Chikunov 		c = vecs->m; /* digest */
28520507de94SVitaly Chikunov 		c_size = vecs->m_size;
28530507de94SVitaly Chikunov 		op = "verify";
28540507de94SVitaly Chikunov 	}
2855df27b26fSHerbert Xu 
28560507de94SVitaly Chikunov 	if (WARN_ON(m_size > PAGE_SIZE))
28570507de94SVitaly Chikunov 		goto free_all;
28580507de94SVitaly Chikunov 	memcpy(xbuf[0], m, m_size);
2859df27b26fSHerbert Xu 
286022287b0bSTadeusz Struk 	sg_init_table(src_tab, 2);
2861df27b26fSHerbert Xu 	sg_set_buf(&src_tab[0], xbuf[0], 8);
28620507de94SVitaly Chikunov 	sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8);
286322287b0bSTadeusz Struk 	sg_init_one(&dst, outbuf_enc, out_len_max);
28640507de94SVitaly Chikunov 	akcipher_request_set_crypt(req, src_tab, &dst, m_size,
286522287b0bSTadeusz Struk 				   out_len_max);
2866946cc463STadeusz Struk 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
28677f397136SGilad Ben-Yossef 				      crypto_req_done, &wait);
2868946cc463STadeusz Struk 
28697f397136SGilad Ben-Yossef 	err = crypto_wait_req(vecs->siggen_sigver_test ?
28700507de94SVitaly Chikunov 			      /* Run asymmetric signature verification */
28710507de94SVitaly Chikunov 			      crypto_akcipher_verify(req) :
28721207107cSStephan Mueller 			      /* Run asymmetric encrypt */
28737f397136SGilad Ben-Yossef 			      crypto_akcipher_encrypt(req), &wait);
2874946cc463STadeusz Struk 	if (err) {
28750507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
2876946cc463STadeusz Struk 		goto free_all;
2877946cc463STadeusz Struk 	}
28780507de94SVitaly Chikunov 	if (req->dst_len != c_size) {
28790507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output len\n",
28800507de94SVitaly Chikunov 		       op);
2881946cc463STadeusz Struk 		err = -EINVAL;
2882946cc463STadeusz Struk 		goto free_all;
2883946cc463STadeusz Struk 	}
2884946cc463STadeusz Struk 	/* verify that encrypted message is equal to expected */
28850507de94SVitaly Chikunov 	if (memcmp(c, outbuf_enc, c_size)) {
28860507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output\n", op);
28870507de94SVitaly Chikunov 		hexdump(outbuf_enc, c_size);
2888946cc463STadeusz Struk 		err = -EINVAL;
2889946cc463STadeusz Struk 		goto free_all;
2890946cc463STadeusz Struk 	}
28910507de94SVitaly Chikunov 
28920507de94SVitaly Chikunov 	/*
28930507de94SVitaly Chikunov 	 * Don't invoke (decrypt or sign) test which require a private key
28940507de94SVitaly Chikunov 	 * for vectors with only a public key.
28950507de94SVitaly Chikunov 	 */
2896946cc463STadeusz Struk 	if (vecs->public_key_vec) {
2897946cc463STadeusz Struk 		err = 0;
2898946cc463STadeusz Struk 		goto free_all;
2899946cc463STadeusz Struk 	}
2900946cc463STadeusz Struk 	outbuf_dec = kzalloc(out_len_max, GFP_KERNEL);
2901946cc463STadeusz Struk 	if (!outbuf_dec) {
2902946cc463STadeusz Struk 		err = -ENOMEM;
2903946cc463STadeusz Struk 		goto free_all;
2904946cc463STadeusz Struk 	}
2905df27b26fSHerbert Xu 
29060507de94SVitaly Chikunov 	op = vecs->siggen_sigver_test ? "sign" : "decrypt";
29070507de94SVitaly Chikunov 	if (WARN_ON(c_size > PAGE_SIZE))
2908df27b26fSHerbert Xu 		goto free_all;
29090507de94SVitaly Chikunov 	memcpy(xbuf[0], c, c_size);
2910df27b26fSHerbert Xu 
29110507de94SVitaly Chikunov 	sg_init_one(&src, xbuf[0], c_size);
291222287b0bSTadeusz Struk 	sg_init_one(&dst, outbuf_dec, out_len_max);
29137f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
29140507de94SVitaly Chikunov 	akcipher_request_set_crypt(req, &src, &dst, c_size, out_len_max);
2915946cc463STadeusz Struk 
29167f397136SGilad Ben-Yossef 	err = crypto_wait_req(vecs->siggen_sigver_test ?
29170507de94SVitaly Chikunov 			      /* Run asymmetric signature generation */
29180507de94SVitaly Chikunov 			      crypto_akcipher_sign(req) :
29191207107cSStephan Mueller 			      /* Run asymmetric decrypt */
29207f397136SGilad Ben-Yossef 			      crypto_akcipher_decrypt(req), &wait);
2921946cc463STadeusz Struk 	if (err) {
29220507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
2923946cc463STadeusz Struk 		goto free_all;
2924946cc463STadeusz Struk 	}
2925946cc463STadeusz Struk 	out_len = req->dst_len;
29260507de94SVitaly Chikunov 	if (out_len < m_size) {
29270507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output len %u\n",
29280507de94SVitaly Chikunov 		       op, out_len);
2929946cc463STadeusz Struk 		err = -EINVAL;
2930946cc463STadeusz Struk 		goto free_all;
2931946cc463STadeusz Struk 	}
2932946cc463STadeusz Struk 	/* verify that decrypted message is equal to the original msg */
29330507de94SVitaly Chikunov 	if (memchr_inv(outbuf_dec, 0, out_len - m_size) ||
29340507de94SVitaly Chikunov 	    memcmp(m, outbuf_dec + out_len - m_size, m_size)) {
29350507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output\n", op);
293650d2b643SHerbert Xu 		hexdump(outbuf_dec, out_len);
2937946cc463STadeusz Struk 		err = -EINVAL;
2938946cc463STadeusz Struk 	}
2939946cc463STadeusz Struk free_all:
2940946cc463STadeusz Struk 	kfree(outbuf_dec);
2941946cc463STadeusz Struk 	kfree(outbuf_enc);
2942946cc463STadeusz Struk free_req:
2943946cc463STadeusz Struk 	akcipher_request_free(req);
2944df27b26fSHerbert Xu free_xbuf:
2945df27b26fSHerbert Xu 	testmgr_free_buf(xbuf);
2946946cc463STadeusz Struk 	return err;
2947946cc463STadeusz Struk }
2948946cc463STadeusz Struk 
294950d2b643SHerbert Xu static int test_akcipher(struct crypto_akcipher *tfm, const char *alg,
2950b13b1e0cSEric Biggers 			 const struct akcipher_testvec *vecs,
2951b13b1e0cSEric Biggers 			 unsigned int tcount)
2952946cc463STadeusz Struk {
295315226e48SHerbert Xu 	const char *algo =
295415226e48SHerbert Xu 		crypto_tfm_alg_driver_name(crypto_akcipher_tfm(tfm));
2955946cc463STadeusz Struk 	int ret, i;
2956946cc463STadeusz Struk 
2957946cc463STadeusz Struk 	for (i = 0; i < tcount; i++) {
295850d2b643SHerbert Xu 		ret = test_akcipher_one(tfm, vecs++);
295950d2b643SHerbert Xu 		if (!ret)
296050d2b643SHerbert Xu 			continue;
296150d2b643SHerbert Xu 
296215226e48SHerbert Xu 		pr_err("alg: akcipher: test %d failed for %s, err=%d\n",
296315226e48SHerbert Xu 		       i + 1, algo, ret);
2964946cc463STadeusz Struk 		return ret;
2965946cc463STadeusz Struk 	}
2966946cc463STadeusz Struk 	return 0;
2967946cc463STadeusz Struk }
2968946cc463STadeusz Struk 
2969946cc463STadeusz Struk static int alg_test_akcipher(const struct alg_test_desc *desc,
2970946cc463STadeusz Struk 			     const char *driver, u32 type, u32 mask)
2971946cc463STadeusz Struk {
2972946cc463STadeusz Struk 	struct crypto_akcipher *tfm;
2973946cc463STadeusz Struk 	int err = 0;
2974946cc463STadeusz Struk 
2975eed93e0cSHerbert Xu 	tfm = crypto_alloc_akcipher(driver, type, mask);
2976946cc463STadeusz Struk 	if (IS_ERR(tfm)) {
2977946cc463STadeusz Struk 		pr_err("alg: akcipher: Failed to load tfm for %s: %ld\n",
2978946cc463STadeusz Struk 		       driver, PTR_ERR(tfm));
2979946cc463STadeusz Struk 		return PTR_ERR(tfm);
2980946cc463STadeusz Struk 	}
2981946cc463STadeusz Struk 	if (desc->suite.akcipher.vecs)
2982946cc463STadeusz Struk 		err = test_akcipher(tfm, desc->alg, desc->suite.akcipher.vecs,
2983946cc463STadeusz Struk 				    desc->suite.akcipher.count);
2984946cc463STadeusz Struk 
2985946cc463STadeusz Struk 	crypto_free_akcipher(tfm);
2986946cc463STadeusz Struk 	return err;
2987946cc463STadeusz Struk }
2988946cc463STadeusz Struk 
2989863b557aSYouquan, Song static int alg_test_null(const struct alg_test_desc *desc,
2990863b557aSYouquan, Song 			     const char *driver, u32 type, u32 mask)
2991863b557aSYouquan, Song {
2992863b557aSYouquan, Song 	return 0;
2993863b557aSYouquan, Song }
2994863b557aSYouquan, Song 
299521c8e720SArd Biesheuvel #define __VECS(tv)	{ .vecs = tv, .count = ARRAY_SIZE(tv) }
299621c8e720SArd Biesheuvel 
2997da7f033dSHerbert Xu /* Please keep this list sorted by algorithm name. */
2998da7f033dSHerbert Xu static const struct alg_test_desc alg_test_descs[] = {
2999da7f033dSHerbert Xu 	{
3000059c2a4dSEric Biggers 		.alg = "adiantum(xchacha12,aes)",
3001059c2a4dSEric Biggers 		.test = alg_test_skcipher,
3002059c2a4dSEric Biggers 		.suite = {
3003059c2a4dSEric Biggers 			.cipher = __VECS(adiantum_xchacha12_aes_tv_template)
3004059c2a4dSEric Biggers 		},
3005059c2a4dSEric Biggers 	}, {
3006059c2a4dSEric Biggers 		.alg = "adiantum(xchacha20,aes)",
3007059c2a4dSEric Biggers 		.test = alg_test_skcipher,
3008059c2a4dSEric Biggers 		.suite = {
3009059c2a4dSEric Biggers 			.cipher = __VECS(adiantum_xchacha20_aes_tv_template)
3010059c2a4dSEric Biggers 		},
3011059c2a4dSEric Biggers 	}, {
3012b87dc203SOndrej Mosnacek 		.alg = "aegis128",
3013b87dc203SOndrej Mosnacek 		.test = alg_test_aead,
3014b87dc203SOndrej Mosnacek 		.suite = {
3015a0d608eeSEric Biggers 			.aead = __VECS(aegis128_tv_template)
3016b87dc203SOndrej Mosnacek 		}
3017b87dc203SOndrej Mosnacek 	}, {
3018b87dc203SOndrej Mosnacek 		.alg = "aegis128l",
3019b87dc203SOndrej Mosnacek 		.test = alg_test_aead,
3020b87dc203SOndrej Mosnacek 		.suite = {
3021a0d608eeSEric Biggers 			.aead = __VECS(aegis128l_tv_template)
3022b87dc203SOndrej Mosnacek 		}
3023b87dc203SOndrej Mosnacek 	}, {
3024b87dc203SOndrej Mosnacek 		.alg = "aegis256",
3025b87dc203SOndrej Mosnacek 		.test = alg_test_aead,
3026b87dc203SOndrej Mosnacek 		.suite = {
3027a0d608eeSEric Biggers 			.aead = __VECS(aegis256_tv_template)
3028b87dc203SOndrej Mosnacek 		}
3029b87dc203SOndrej Mosnacek 	}, {
3030e08ca2daSJarod Wilson 		.alg = "ansi_cprng",
3031e08ca2daSJarod Wilson 		.test = alg_test_cprng,
3032e08ca2daSJarod Wilson 		.suite = {
303321c8e720SArd Biesheuvel 			.cprng = __VECS(ansi_cprng_aes_tv_template)
3034e08ca2daSJarod Wilson 		}
3035e08ca2daSJarod Wilson 	}, {
3036bca4feb0SHoria Geanta 		.alg = "authenc(hmac(md5),ecb(cipher_null))",
3037bca4feb0SHoria Geanta 		.test = alg_test_aead,
3038bca4feb0SHoria Geanta 		.suite = {
3039a0d608eeSEric Biggers 			.aead = __VECS(hmac_md5_ecb_cipher_null_tv_template)
3040bca4feb0SHoria Geanta 		}
3041bca4feb0SHoria Geanta 	}, {
3042a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha1),cbc(aes))",
3043e46e9a46SHoria Geanta 		.test = alg_test_aead,
3044bcf741cbSHerbert Xu 		.fips_allowed = 1,
3045e46e9a46SHoria Geanta 		.suite = {
3046a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_aes_cbc_tv_temp)
30475208ed2cSNitesh Lal 		}
30485208ed2cSNitesh Lal 	}, {
3049a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha1),cbc(des))",
30505208ed2cSNitesh Lal 		.test = alg_test_aead,
30515208ed2cSNitesh Lal 		.suite = {
3052a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_des_cbc_tv_temp)
30535208ed2cSNitesh Lal 		}
30545208ed2cSNitesh Lal 	}, {
3055a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha1),cbc(des3_ede))",
30565208ed2cSNitesh Lal 		.test = alg_test_aead,
3057ed1afac9SMarcus Meissner 		.fips_allowed = 1,
30585208ed2cSNitesh Lal 		.suite = {
3059a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_des3_ede_cbc_tv_temp)
3060e46e9a46SHoria Geanta 		}
3061e46e9a46SHoria Geanta 	}, {
3062fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha1),ctr(aes))",
3063fb16abc2SMarcus Meissner 		.test = alg_test_null,
3064fb16abc2SMarcus Meissner 		.fips_allowed = 1,
3065fb16abc2SMarcus Meissner 	}, {
3066bca4feb0SHoria Geanta 		.alg = "authenc(hmac(sha1),ecb(cipher_null))",
3067bca4feb0SHoria Geanta 		.test = alg_test_aead,
3068bca4feb0SHoria Geanta 		.suite = {
3069a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_ecb_cipher_null_tv_temp)
30705208ed2cSNitesh Lal 		}
30715208ed2cSNitesh Lal 	}, {
30728888690eSMarcus Meissner 		.alg = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
30738888690eSMarcus Meissner 		.test = alg_test_null,
30748888690eSMarcus Meissner 		.fips_allowed = 1,
30758888690eSMarcus Meissner 	}, {
3076a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha224),cbc(des))",
30775208ed2cSNitesh Lal 		.test = alg_test_aead,
30785208ed2cSNitesh Lal 		.suite = {
3079a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha224_des_cbc_tv_temp)
30805208ed2cSNitesh Lal 		}
30815208ed2cSNitesh Lal 	}, {
3082a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha224),cbc(des3_ede))",
30835208ed2cSNitesh Lal 		.test = alg_test_aead,
3084ed1afac9SMarcus Meissner 		.fips_allowed = 1,
30855208ed2cSNitesh Lal 		.suite = {
3086a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha224_des3_ede_cbc_tv_temp)
3087bca4feb0SHoria Geanta 		}
3088bca4feb0SHoria Geanta 	}, {
3089a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha256),cbc(aes))",
3090e46e9a46SHoria Geanta 		.test = alg_test_aead,
3091ed1afac9SMarcus Meissner 		.fips_allowed = 1,
3092e46e9a46SHoria Geanta 		.suite = {
3093a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha256_aes_cbc_tv_temp)
30945208ed2cSNitesh Lal 		}
30955208ed2cSNitesh Lal 	}, {
3096a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha256),cbc(des))",
30975208ed2cSNitesh Lal 		.test = alg_test_aead,
30985208ed2cSNitesh Lal 		.suite = {
3099a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha256_des_cbc_tv_temp)
31005208ed2cSNitesh Lal 		}
31015208ed2cSNitesh Lal 	}, {
3102a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha256),cbc(des3_ede))",
31035208ed2cSNitesh Lal 		.test = alg_test_aead,
3104ed1afac9SMarcus Meissner 		.fips_allowed = 1,
31055208ed2cSNitesh Lal 		.suite = {
3106a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha256_des3_ede_cbc_tv_temp)
31075208ed2cSNitesh Lal 		}
31085208ed2cSNitesh Lal 	}, {
3109fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha256),ctr(aes))",
3110fb16abc2SMarcus Meissner 		.test = alg_test_null,
3111fb16abc2SMarcus Meissner 		.fips_allowed = 1,
3112fb16abc2SMarcus Meissner 	}, {
31138888690eSMarcus Meissner 		.alg = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
31148888690eSMarcus Meissner 		.test = alg_test_null,
31158888690eSMarcus Meissner 		.fips_allowed = 1,
31168888690eSMarcus Meissner 	}, {
3117a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha384),cbc(des))",
31185208ed2cSNitesh Lal 		.test = alg_test_aead,
31195208ed2cSNitesh Lal 		.suite = {
3120a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha384_des_cbc_tv_temp)
31215208ed2cSNitesh Lal 		}
31225208ed2cSNitesh Lal 	}, {
3123a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha384),cbc(des3_ede))",
31245208ed2cSNitesh Lal 		.test = alg_test_aead,
3125ed1afac9SMarcus Meissner 		.fips_allowed = 1,
31265208ed2cSNitesh Lal 		.suite = {
3127a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha384_des3_ede_cbc_tv_temp)
3128e46e9a46SHoria Geanta 		}
3129e46e9a46SHoria Geanta 	}, {
3130fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha384),ctr(aes))",
3131fb16abc2SMarcus Meissner 		.test = alg_test_null,
3132fb16abc2SMarcus Meissner 		.fips_allowed = 1,
3133fb16abc2SMarcus Meissner 	}, {
31348888690eSMarcus Meissner 		.alg = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
31358888690eSMarcus Meissner 		.test = alg_test_null,
31368888690eSMarcus Meissner 		.fips_allowed = 1,
31378888690eSMarcus Meissner 	}, {
3138a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha512),cbc(aes))",
3139ed1afac9SMarcus Meissner 		.fips_allowed = 1,
3140e46e9a46SHoria Geanta 		.test = alg_test_aead,
3141e46e9a46SHoria Geanta 		.suite = {
3142a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha512_aes_cbc_tv_temp)
31435208ed2cSNitesh Lal 		}
31445208ed2cSNitesh Lal 	}, {
3145a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha512),cbc(des))",
31465208ed2cSNitesh Lal 		.test = alg_test_aead,
31475208ed2cSNitesh Lal 		.suite = {
3148a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha512_des_cbc_tv_temp)
31495208ed2cSNitesh Lal 		}
31505208ed2cSNitesh Lal 	}, {
3151a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha512),cbc(des3_ede))",
31525208ed2cSNitesh Lal 		.test = alg_test_aead,
3153ed1afac9SMarcus Meissner 		.fips_allowed = 1,
31545208ed2cSNitesh Lal 		.suite = {
3155a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha512_des3_ede_cbc_tv_temp)
3156e46e9a46SHoria Geanta 		}
3157e46e9a46SHoria Geanta 	}, {
3158fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha512),ctr(aes))",
3159fb16abc2SMarcus Meissner 		.test = alg_test_null,
3160fb16abc2SMarcus Meissner 		.fips_allowed = 1,
3161fb16abc2SMarcus Meissner 	}, {
31628888690eSMarcus Meissner 		.alg = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
31638888690eSMarcus Meissner 		.test = alg_test_null,
31648888690eSMarcus Meissner 		.fips_allowed = 1,
31658888690eSMarcus Meissner 	}, {
3166da7f033dSHerbert Xu 		.alg = "cbc(aes)",
31671aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3168a1915d51SJarod Wilson 		.fips_allowed = 1,
3169da7f033dSHerbert Xu 		.suite = {
317092a4c9feSEric Biggers 			.cipher = __VECS(aes_cbc_tv_template)
317192a4c9feSEric Biggers 		},
3172da7f033dSHerbert Xu 	}, {
3173da7f033dSHerbert Xu 		.alg = "cbc(anubis)",
31741aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3175da7f033dSHerbert Xu 		.suite = {
317692a4c9feSEric Biggers 			.cipher = __VECS(anubis_cbc_tv_template)
317792a4c9feSEric Biggers 		},
3178da7f033dSHerbert Xu 	}, {
3179da7f033dSHerbert Xu 		.alg = "cbc(blowfish)",
31801aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3181da7f033dSHerbert Xu 		.suite = {
318292a4c9feSEric Biggers 			.cipher = __VECS(bf_cbc_tv_template)
318392a4c9feSEric Biggers 		},
3184da7f033dSHerbert Xu 	}, {
3185da7f033dSHerbert Xu 		.alg = "cbc(camellia)",
31861aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3187da7f033dSHerbert Xu 		.suite = {
318892a4c9feSEric Biggers 			.cipher = __VECS(camellia_cbc_tv_template)
318992a4c9feSEric Biggers 		},
3190da7f033dSHerbert Xu 	}, {
3191a2c58260SJohannes Goetzfried 		.alg = "cbc(cast5)",
3192a2c58260SJohannes Goetzfried 		.test = alg_test_skcipher,
3193a2c58260SJohannes Goetzfried 		.suite = {
319492a4c9feSEric Biggers 			.cipher = __VECS(cast5_cbc_tv_template)
319592a4c9feSEric Biggers 		},
3196a2c58260SJohannes Goetzfried 	}, {
31979b8b0405SJohannes Goetzfried 		.alg = "cbc(cast6)",
31989b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
31999b8b0405SJohannes Goetzfried 		.suite = {
320092a4c9feSEric Biggers 			.cipher = __VECS(cast6_cbc_tv_template)
320192a4c9feSEric Biggers 		},
32029b8b0405SJohannes Goetzfried 	}, {
3203da7f033dSHerbert Xu 		.alg = "cbc(des)",
32041aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3205da7f033dSHerbert Xu 		.suite = {
320692a4c9feSEric Biggers 			.cipher = __VECS(des_cbc_tv_template)
320792a4c9feSEric Biggers 		},
3208da7f033dSHerbert Xu 	}, {
3209da7f033dSHerbert Xu 		.alg = "cbc(des3_ede)",
32101aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3211a1915d51SJarod Wilson 		.fips_allowed = 1,
3212da7f033dSHerbert Xu 		.suite = {
321392a4c9feSEric Biggers 			.cipher = __VECS(des3_ede_cbc_tv_template)
321492a4c9feSEric Biggers 		},
3215da7f033dSHerbert Xu 	}, {
3216a794d8d8SGilad Ben-Yossef 		/* Same as cbc(aes) except the key is stored in
3217a794d8d8SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
3218a794d8d8SGilad Ben-Yossef 		 */
3219a794d8d8SGilad Ben-Yossef 		.alg = "cbc(paes)",
3220a794d8d8SGilad Ben-Yossef 		.test = alg_test_null,
3221a794d8d8SGilad Ben-Yossef 		.fips_allowed = 1,
3222a794d8d8SGilad Ben-Yossef 	}, {
32239d25917dSJussi Kivilinna 		.alg = "cbc(serpent)",
32249d25917dSJussi Kivilinna 		.test = alg_test_skcipher,
32259d25917dSJussi Kivilinna 		.suite = {
322692a4c9feSEric Biggers 			.cipher = __VECS(serpent_cbc_tv_template)
322792a4c9feSEric Biggers 		},
32289d25917dSJussi Kivilinna 	}, {
322995ba5973SGilad Ben-Yossef 		.alg = "cbc(sm4)",
323095ba5973SGilad Ben-Yossef 		.test = alg_test_skcipher,
323195ba5973SGilad Ben-Yossef 		.suite = {
323295ba5973SGilad Ben-Yossef 			.cipher = __VECS(sm4_cbc_tv_template)
323395ba5973SGilad Ben-Yossef 		}
323495ba5973SGilad Ben-Yossef 	}, {
3235da7f033dSHerbert Xu 		.alg = "cbc(twofish)",
32361aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3237da7f033dSHerbert Xu 		.suite = {
323892a4c9feSEric Biggers 			.cipher = __VECS(tf_cbc_tv_template)
323992a4c9feSEric Biggers 		},
3240da7f033dSHerbert Xu 	}, {
3241092acf06SArd Biesheuvel 		.alg = "cbcmac(aes)",
3242092acf06SArd Biesheuvel 		.fips_allowed = 1,
3243092acf06SArd Biesheuvel 		.test = alg_test_hash,
3244092acf06SArd Biesheuvel 		.suite = {
3245092acf06SArd Biesheuvel 			.hash = __VECS(aes_cbcmac_tv_template)
3246092acf06SArd Biesheuvel 		}
3247092acf06SArd Biesheuvel 	}, {
3248da7f033dSHerbert Xu 		.alg = "ccm(aes)",
3249da7f033dSHerbert Xu 		.test = alg_test_aead,
3250a1915d51SJarod Wilson 		.fips_allowed = 1,
3251da7f033dSHerbert Xu 		.suite = {
3252a0d608eeSEric Biggers 			.aead = __VECS(aes_ccm_tv_template)
3253da7f033dSHerbert Xu 		}
3254da7f033dSHerbert Xu 	}, {
32557da66670SDmitry Eremin-Solenikov 		.alg = "cfb(aes)",
32567da66670SDmitry Eremin-Solenikov 		.test = alg_test_skcipher,
32577da66670SDmitry Eremin-Solenikov 		.fips_allowed = 1,
32587da66670SDmitry Eremin-Solenikov 		.suite = {
32597da66670SDmitry Eremin-Solenikov 			.cipher = __VECS(aes_cfb_tv_template)
32607da66670SDmitry Eremin-Solenikov 		},
32617da66670SDmitry Eremin-Solenikov 	}, {
32623590ebf2SMartin Willi 		.alg = "chacha20",
32633590ebf2SMartin Willi 		.test = alg_test_skcipher,
32643590ebf2SMartin Willi 		.suite = {
326592a4c9feSEric Biggers 			.cipher = __VECS(chacha20_tv_template)
326692a4c9feSEric Biggers 		},
32673590ebf2SMartin Willi 	}, {
326893b5e86aSJussi Kivilinna 		.alg = "cmac(aes)",
32698f183751SStephan Mueller 		.fips_allowed = 1,
327093b5e86aSJussi Kivilinna 		.test = alg_test_hash,
327193b5e86aSJussi Kivilinna 		.suite = {
327221c8e720SArd Biesheuvel 			.hash = __VECS(aes_cmac128_tv_template)
327393b5e86aSJussi Kivilinna 		}
327493b5e86aSJussi Kivilinna 	}, {
327593b5e86aSJussi Kivilinna 		.alg = "cmac(des3_ede)",
32768f183751SStephan Mueller 		.fips_allowed = 1,
327793b5e86aSJussi Kivilinna 		.test = alg_test_hash,
327893b5e86aSJussi Kivilinna 		.suite = {
327921c8e720SArd Biesheuvel 			.hash = __VECS(des3_ede_cmac64_tv_template)
328093b5e86aSJussi Kivilinna 		}
328193b5e86aSJussi Kivilinna 	}, {
3282e448370dSJussi Kivilinna 		.alg = "compress_null",
3283e448370dSJussi Kivilinna 		.test = alg_test_null,
3284e448370dSJussi Kivilinna 	}, {
3285ebb3472fSArd Biesheuvel 		.alg = "crc32",
3286ebb3472fSArd Biesheuvel 		.test = alg_test_hash,
3287a8a34416SMilan Broz 		.fips_allowed = 1,
3288ebb3472fSArd Biesheuvel 		.suite = {
328921c8e720SArd Biesheuvel 			.hash = __VECS(crc32_tv_template)
3290ebb3472fSArd Biesheuvel 		}
3291ebb3472fSArd Biesheuvel 	}, {
3292da7f033dSHerbert Xu 		.alg = "crc32c",
32938e3ee85eSHerbert Xu 		.test = alg_test_crc32c,
3294a1915d51SJarod Wilson 		.fips_allowed = 1,
3295da7f033dSHerbert Xu 		.suite = {
329621c8e720SArd Biesheuvel 			.hash = __VECS(crc32c_tv_template)
3297da7f033dSHerbert Xu 		}
3298da7f033dSHerbert Xu 	}, {
329968411521SHerbert Xu 		.alg = "crct10dif",
330068411521SHerbert Xu 		.test = alg_test_hash,
330168411521SHerbert Xu 		.fips_allowed = 1,
330268411521SHerbert Xu 		.suite = {
330321c8e720SArd Biesheuvel 			.hash = __VECS(crct10dif_tv_template)
330468411521SHerbert Xu 		}
330568411521SHerbert Xu 	}, {
3306f7cb80f2SJarod Wilson 		.alg = "ctr(aes)",
3307f7cb80f2SJarod Wilson 		.test = alg_test_skcipher,
3308a1915d51SJarod Wilson 		.fips_allowed = 1,
3309f7cb80f2SJarod Wilson 		.suite = {
331092a4c9feSEric Biggers 			.cipher = __VECS(aes_ctr_tv_template)
3311f7cb80f2SJarod Wilson 		}
3312f7cb80f2SJarod Wilson 	}, {
331385b63e34SJussi Kivilinna 		.alg = "ctr(blowfish)",
331485b63e34SJussi Kivilinna 		.test = alg_test_skcipher,
331585b63e34SJussi Kivilinna 		.suite = {
331692a4c9feSEric Biggers 			.cipher = __VECS(bf_ctr_tv_template)
331785b63e34SJussi Kivilinna 		}
331885b63e34SJussi Kivilinna 	}, {
33190840605eSJussi Kivilinna 		.alg = "ctr(camellia)",
33200840605eSJussi Kivilinna 		.test = alg_test_skcipher,
33210840605eSJussi Kivilinna 		.suite = {
332292a4c9feSEric Biggers 			.cipher = __VECS(camellia_ctr_tv_template)
33230840605eSJussi Kivilinna 		}
33240840605eSJussi Kivilinna 	}, {
3325a2c58260SJohannes Goetzfried 		.alg = "ctr(cast5)",
3326a2c58260SJohannes Goetzfried 		.test = alg_test_skcipher,
3327a2c58260SJohannes Goetzfried 		.suite = {
332892a4c9feSEric Biggers 			.cipher = __VECS(cast5_ctr_tv_template)
3329a2c58260SJohannes Goetzfried 		}
3330a2c58260SJohannes Goetzfried 	}, {
33319b8b0405SJohannes Goetzfried 		.alg = "ctr(cast6)",
33329b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
33339b8b0405SJohannes Goetzfried 		.suite = {
333492a4c9feSEric Biggers 			.cipher = __VECS(cast6_ctr_tv_template)
33359b8b0405SJohannes Goetzfried 		}
33369b8b0405SJohannes Goetzfried 	}, {
33378163fc30SJussi Kivilinna 		.alg = "ctr(des)",
33388163fc30SJussi Kivilinna 		.test = alg_test_skcipher,
33398163fc30SJussi Kivilinna 		.suite = {
334092a4c9feSEric Biggers 			.cipher = __VECS(des_ctr_tv_template)
33418163fc30SJussi Kivilinna 		}
33428163fc30SJussi Kivilinna 	}, {
3343e080b17aSJussi Kivilinna 		.alg = "ctr(des3_ede)",
3344e080b17aSJussi Kivilinna 		.test = alg_test_skcipher,
33450d8da104SMarcelo Cerri 		.fips_allowed = 1,
3346e080b17aSJussi Kivilinna 		.suite = {
334792a4c9feSEric Biggers 			.cipher = __VECS(des3_ede_ctr_tv_template)
3348e080b17aSJussi Kivilinna 		}
3349e080b17aSJussi Kivilinna 	}, {
3350a794d8d8SGilad Ben-Yossef 		/* Same as ctr(aes) except the key is stored in
3351a794d8d8SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
3352a794d8d8SGilad Ben-Yossef 		 */
3353a794d8d8SGilad Ben-Yossef 		.alg = "ctr(paes)",
3354a794d8d8SGilad Ben-Yossef 		.test = alg_test_null,
3355a794d8d8SGilad Ben-Yossef 		.fips_allowed = 1,
3356a794d8d8SGilad Ben-Yossef 	}, {
33579d25917dSJussi Kivilinna 		.alg = "ctr(serpent)",
33589d25917dSJussi Kivilinna 		.test = alg_test_skcipher,
33599d25917dSJussi Kivilinna 		.suite = {
336092a4c9feSEric Biggers 			.cipher = __VECS(serpent_ctr_tv_template)
33619d25917dSJussi Kivilinna 		}
33629d25917dSJussi Kivilinna 	}, {
336395ba5973SGilad Ben-Yossef 		.alg = "ctr(sm4)",
336495ba5973SGilad Ben-Yossef 		.test = alg_test_skcipher,
336595ba5973SGilad Ben-Yossef 		.suite = {
336695ba5973SGilad Ben-Yossef 			.cipher = __VECS(sm4_ctr_tv_template)
336795ba5973SGilad Ben-Yossef 		}
336895ba5973SGilad Ben-Yossef 	}, {
3369573da620SJussi Kivilinna 		.alg = "ctr(twofish)",
3370573da620SJussi Kivilinna 		.test = alg_test_skcipher,
3371573da620SJussi Kivilinna 		.suite = {
337292a4c9feSEric Biggers 			.cipher = __VECS(tf_ctr_tv_template)
3373573da620SJussi Kivilinna 		}
3374573da620SJussi Kivilinna 	}, {
3375da7f033dSHerbert Xu 		.alg = "cts(cbc(aes))",
33761aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3377196ad604SGilad Ben-Yossef 		.fips_allowed = 1,
3378da7f033dSHerbert Xu 		.suite = {
337992a4c9feSEric Biggers 			.cipher = __VECS(cts_mode_tv_template)
3380da7f033dSHerbert Xu 		}
3381da7f033dSHerbert Xu 	}, {
3382da7f033dSHerbert Xu 		.alg = "deflate",
3383da7f033dSHerbert Xu 		.test = alg_test_comp,
33840818904dSMilan Broz 		.fips_allowed = 1,
3385da7f033dSHerbert Xu 		.suite = {
3386da7f033dSHerbert Xu 			.comp = {
338721c8e720SArd Biesheuvel 				.comp = __VECS(deflate_comp_tv_template),
338821c8e720SArd Biesheuvel 				.decomp = __VECS(deflate_decomp_tv_template)
3389da7f033dSHerbert Xu 			}
3390da7f033dSHerbert Xu 		}
3391da7f033dSHerbert Xu 	}, {
3392802c7f1cSSalvatore Benedetto 		.alg = "dh",
3393802c7f1cSSalvatore Benedetto 		.test = alg_test_kpp,
3394802c7f1cSSalvatore Benedetto 		.fips_allowed = 1,
3395802c7f1cSSalvatore Benedetto 		.suite = {
339621c8e720SArd Biesheuvel 			.kpp = __VECS(dh_tv_template)
3397802c7f1cSSalvatore Benedetto 		}
3398802c7f1cSSalvatore Benedetto 	}, {
3399e448370dSJussi Kivilinna 		.alg = "digest_null",
3400e448370dSJussi Kivilinna 		.test = alg_test_null,
3401e448370dSJussi Kivilinna 	}, {
340264d1cdfbSStephan Mueller 		.alg = "drbg_nopr_ctr_aes128",
340364d1cdfbSStephan Mueller 		.test = alg_test_drbg,
340464d1cdfbSStephan Mueller 		.fips_allowed = 1,
340564d1cdfbSStephan Mueller 		.suite = {
340621c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_ctr_aes128_tv_template)
340764d1cdfbSStephan Mueller 		}
340864d1cdfbSStephan Mueller 	}, {
340964d1cdfbSStephan Mueller 		.alg = "drbg_nopr_ctr_aes192",
341064d1cdfbSStephan Mueller 		.test = alg_test_drbg,
341164d1cdfbSStephan Mueller 		.fips_allowed = 1,
341264d1cdfbSStephan Mueller 		.suite = {
341321c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_ctr_aes192_tv_template)
341464d1cdfbSStephan Mueller 		}
341564d1cdfbSStephan Mueller 	}, {
341664d1cdfbSStephan Mueller 		.alg = "drbg_nopr_ctr_aes256",
341764d1cdfbSStephan Mueller 		.test = alg_test_drbg,
341864d1cdfbSStephan Mueller 		.fips_allowed = 1,
341964d1cdfbSStephan Mueller 		.suite = {
342021c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_ctr_aes256_tv_template)
342164d1cdfbSStephan Mueller 		}
342264d1cdfbSStephan Mueller 	}, {
342364d1cdfbSStephan Mueller 		/*
342464d1cdfbSStephan Mueller 		 * There is no need to specifically test the DRBG with every
342564d1cdfbSStephan Mueller 		 * backend cipher -- covered by drbg_nopr_hmac_sha256 test
342664d1cdfbSStephan Mueller 		 */
342764d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha1",
342864d1cdfbSStephan Mueller 		.fips_allowed = 1,
342964d1cdfbSStephan Mueller 		.test = alg_test_null,
343064d1cdfbSStephan Mueller 	}, {
343164d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha256",
343264d1cdfbSStephan Mueller 		.test = alg_test_drbg,
343364d1cdfbSStephan Mueller 		.fips_allowed = 1,
343464d1cdfbSStephan Mueller 		.suite = {
343521c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_hmac_sha256_tv_template)
343664d1cdfbSStephan Mueller 		}
343764d1cdfbSStephan Mueller 	}, {
343864d1cdfbSStephan Mueller 		/* covered by drbg_nopr_hmac_sha256 test */
343964d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha384",
344064d1cdfbSStephan Mueller 		.fips_allowed = 1,
344164d1cdfbSStephan Mueller 		.test = alg_test_null,
344264d1cdfbSStephan Mueller 	}, {
344364d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha512",
344464d1cdfbSStephan Mueller 		.test = alg_test_null,
344564d1cdfbSStephan Mueller 		.fips_allowed = 1,
344664d1cdfbSStephan Mueller 	}, {
344764d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha1",
344864d1cdfbSStephan Mueller 		.fips_allowed = 1,
344964d1cdfbSStephan Mueller 		.test = alg_test_null,
345064d1cdfbSStephan Mueller 	}, {
345164d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha256",
345264d1cdfbSStephan Mueller 		.test = alg_test_drbg,
345364d1cdfbSStephan Mueller 		.fips_allowed = 1,
345464d1cdfbSStephan Mueller 		.suite = {
345521c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_sha256_tv_template)
345664d1cdfbSStephan Mueller 		}
345764d1cdfbSStephan Mueller 	}, {
345864d1cdfbSStephan Mueller 		/* covered by drbg_nopr_sha256 test */
345964d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha384",
346064d1cdfbSStephan Mueller 		.fips_allowed = 1,
346164d1cdfbSStephan Mueller 		.test = alg_test_null,
346264d1cdfbSStephan Mueller 	}, {
346364d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha512",
346464d1cdfbSStephan Mueller 		.fips_allowed = 1,
346564d1cdfbSStephan Mueller 		.test = alg_test_null,
346664d1cdfbSStephan Mueller 	}, {
346764d1cdfbSStephan Mueller 		.alg = "drbg_pr_ctr_aes128",
346864d1cdfbSStephan Mueller 		.test = alg_test_drbg,
346964d1cdfbSStephan Mueller 		.fips_allowed = 1,
347064d1cdfbSStephan Mueller 		.suite = {
347121c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_pr_ctr_aes128_tv_template)
347264d1cdfbSStephan Mueller 		}
347364d1cdfbSStephan Mueller 	}, {
347464d1cdfbSStephan Mueller 		/* covered by drbg_pr_ctr_aes128 test */
347564d1cdfbSStephan Mueller 		.alg = "drbg_pr_ctr_aes192",
347664d1cdfbSStephan Mueller 		.fips_allowed = 1,
347764d1cdfbSStephan Mueller 		.test = alg_test_null,
347864d1cdfbSStephan Mueller 	}, {
347964d1cdfbSStephan Mueller 		.alg = "drbg_pr_ctr_aes256",
348064d1cdfbSStephan Mueller 		.fips_allowed = 1,
348164d1cdfbSStephan Mueller 		.test = alg_test_null,
348264d1cdfbSStephan Mueller 	}, {
348364d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha1",
348464d1cdfbSStephan Mueller 		.fips_allowed = 1,
348564d1cdfbSStephan Mueller 		.test = alg_test_null,
348664d1cdfbSStephan Mueller 	}, {
348764d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha256",
348864d1cdfbSStephan Mueller 		.test = alg_test_drbg,
348964d1cdfbSStephan Mueller 		.fips_allowed = 1,
349064d1cdfbSStephan Mueller 		.suite = {
349121c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_pr_hmac_sha256_tv_template)
349264d1cdfbSStephan Mueller 		}
349364d1cdfbSStephan Mueller 	}, {
349464d1cdfbSStephan Mueller 		/* covered by drbg_pr_hmac_sha256 test */
349564d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha384",
349664d1cdfbSStephan Mueller 		.fips_allowed = 1,
349764d1cdfbSStephan Mueller 		.test = alg_test_null,
349864d1cdfbSStephan Mueller 	}, {
349964d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha512",
350064d1cdfbSStephan Mueller 		.test = alg_test_null,
350164d1cdfbSStephan Mueller 		.fips_allowed = 1,
350264d1cdfbSStephan Mueller 	}, {
350364d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha1",
350464d1cdfbSStephan Mueller 		.fips_allowed = 1,
350564d1cdfbSStephan Mueller 		.test = alg_test_null,
350664d1cdfbSStephan Mueller 	}, {
350764d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha256",
350864d1cdfbSStephan Mueller 		.test = alg_test_drbg,
350964d1cdfbSStephan Mueller 		.fips_allowed = 1,
351064d1cdfbSStephan Mueller 		.suite = {
351121c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_pr_sha256_tv_template)
351264d1cdfbSStephan Mueller 		}
351364d1cdfbSStephan Mueller 	}, {
351464d1cdfbSStephan Mueller 		/* covered by drbg_pr_sha256 test */
351564d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha384",
351664d1cdfbSStephan Mueller 		.fips_allowed = 1,
351764d1cdfbSStephan Mueller 		.test = alg_test_null,
351864d1cdfbSStephan Mueller 	}, {
351964d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha512",
352064d1cdfbSStephan Mueller 		.fips_allowed = 1,
352164d1cdfbSStephan Mueller 		.test = alg_test_null,
352264d1cdfbSStephan Mueller 	}, {
3523da7f033dSHerbert Xu 		.alg = "ecb(aes)",
35241aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3525a1915d51SJarod Wilson 		.fips_allowed = 1,
3526da7f033dSHerbert Xu 		.suite = {
352792a4c9feSEric Biggers 			.cipher = __VECS(aes_tv_template)
3528da7f033dSHerbert Xu 		}
3529da7f033dSHerbert Xu 	}, {
3530da7f033dSHerbert Xu 		.alg = "ecb(anubis)",
35311aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3532da7f033dSHerbert Xu 		.suite = {
353392a4c9feSEric Biggers 			.cipher = __VECS(anubis_tv_template)
3534da7f033dSHerbert Xu 		}
3535da7f033dSHerbert Xu 	}, {
3536da7f033dSHerbert Xu 		.alg = "ecb(arc4)",
35371aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3538da7f033dSHerbert Xu 		.suite = {
353992a4c9feSEric Biggers 			.cipher = __VECS(arc4_tv_template)
3540da7f033dSHerbert Xu 		}
3541da7f033dSHerbert Xu 	}, {
3542da7f033dSHerbert Xu 		.alg = "ecb(blowfish)",
35431aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3544da7f033dSHerbert Xu 		.suite = {
354592a4c9feSEric Biggers 			.cipher = __VECS(bf_tv_template)
3546da7f033dSHerbert Xu 		}
3547da7f033dSHerbert Xu 	}, {
3548da7f033dSHerbert Xu 		.alg = "ecb(camellia)",
35491aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3550da7f033dSHerbert Xu 		.suite = {
355192a4c9feSEric Biggers 			.cipher = __VECS(camellia_tv_template)
3552da7f033dSHerbert Xu 		}
3553da7f033dSHerbert Xu 	}, {
3554da7f033dSHerbert Xu 		.alg = "ecb(cast5)",
35551aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3556da7f033dSHerbert Xu 		.suite = {
355792a4c9feSEric Biggers 			.cipher = __VECS(cast5_tv_template)
3558da7f033dSHerbert Xu 		}
3559da7f033dSHerbert Xu 	}, {
3560da7f033dSHerbert Xu 		.alg = "ecb(cast6)",
35611aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3562da7f033dSHerbert Xu 		.suite = {
356392a4c9feSEric Biggers 			.cipher = __VECS(cast6_tv_template)
3564da7f033dSHerbert Xu 		}
3565da7f033dSHerbert Xu 	}, {
3566e448370dSJussi Kivilinna 		.alg = "ecb(cipher_null)",
3567e448370dSJussi Kivilinna 		.test = alg_test_null,
35686175ca2bSMilan Broz 		.fips_allowed = 1,
3569e448370dSJussi Kivilinna 	}, {
3570da7f033dSHerbert Xu 		.alg = "ecb(des)",
35711aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3572da7f033dSHerbert Xu 		.suite = {
357392a4c9feSEric Biggers 			.cipher = __VECS(des_tv_template)
3574da7f033dSHerbert Xu 		}
3575da7f033dSHerbert Xu 	}, {
3576da7f033dSHerbert Xu 		.alg = "ecb(des3_ede)",
35771aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3578a1915d51SJarod Wilson 		.fips_allowed = 1,
3579da7f033dSHerbert Xu 		.suite = {
358092a4c9feSEric Biggers 			.cipher = __VECS(des3_ede_tv_template)
3581da7f033dSHerbert Xu 		}
3582da7f033dSHerbert Xu 	}, {
358366e5bd00SJussi Kivilinna 		.alg = "ecb(fcrypt)",
358466e5bd00SJussi Kivilinna 		.test = alg_test_skcipher,
358566e5bd00SJussi Kivilinna 		.suite = {
358666e5bd00SJussi Kivilinna 			.cipher = {
358792a4c9feSEric Biggers 				.vecs = fcrypt_pcbc_tv_template,
358866e5bd00SJussi Kivilinna 				.count = 1
358966e5bd00SJussi Kivilinna 			}
359066e5bd00SJussi Kivilinna 		}
359166e5bd00SJussi Kivilinna 	}, {
3592da7f033dSHerbert Xu 		.alg = "ecb(khazad)",
35931aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3594da7f033dSHerbert Xu 		.suite = {
359592a4c9feSEric Biggers 			.cipher = __VECS(khazad_tv_template)
3596da7f033dSHerbert Xu 		}
3597da7f033dSHerbert Xu 	}, {
359815f47ce5SGilad Ben-Yossef 		/* Same as ecb(aes) except the key is stored in
359915f47ce5SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
360015f47ce5SGilad Ben-Yossef 		 */
360115f47ce5SGilad Ben-Yossef 		.alg = "ecb(paes)",
360215f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
360315f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
360415f47ce5SGilad Ben-Yossef 	}, {
3605da7f033dSHerbert Xu 		.alg = "ecb(seed)",
36061aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3607da7f033dSHerbert Xu 		.suite = {
360892a4c9feSEric Biggers 			.cipher = __VECS(seed_tv_template)
3609da7f033dSHerbert Xu 		}
3610da7f033dSHerbert Xu 	}, {
3611da7f033dSHerbert Xu 		.alg = "ecb(serpent)",
36121aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3613da7f033dSHerbert Xu 		.suite = {
361492a4c9feSEric Biggers 			.cipher = __VECS(serpent_tv_template)
3615da7f033dSHerbert Xu 		}
3616da7f033dSHerbert Xu 	}, {
3617cd83a8a7SGilad Ben-Yossef 		.alg = "ecb(sm4)",
3618cd83a8a7SGilad Ben-Yossef 		.test = alg_test_skcipher,
3619cd83a8a7SGilad Ben-Yossef 		.suite = {
362092a4c9feSEric Biggers 			.cipher = __VECS(sm4_tv_template)
3621cd83a8a7SGilad Ben-Yossef 		}
3622cd83a8a7SGilad Ben-Yossef 	}, {
3623da7f033dSHerbert Xu 		.alg = "ecb(tea)",
36241aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3625da7f033dSHerbert Xu 		.suite = {
362692a4c9feSEric Biggers 			.cipher = __VECS(tea_tv_template)
3627da7f033dSHerbert Xu 		}
3628da7f033dSHerbert Xu 	}, {
3629da7f033dSHerbert Xu 		.alg = "ecb(tnepres)",
36301aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3631da7f033dSHerbert Xu 		.suite = {
363292a4c9feSEric Biggers 			.cipher = __VECS(tnepres_tv_template)
3633da7f033dSHerbert Xu 		}
3634da7f033dSHerbert Xu 	}, {
3635da7f033dSHerbert Xu 		.alg = "ecb(twofish)",
36361aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3637da7f033dSHerbert Xu 		.suite = {
363892a4c9feSEric Biggers 			.cipher = __VECS(tf_tv_template)
3639da7f033dSHerbert Xu 		}
3640da7f033dSHerbert Xu 	}, {
3641da7f033dSHerbert Xu 		.alg = "ecb(xeta)",
36421aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3643da7f033dSHerbert Xu 		.suite = {
364492a4c9feSEric Biggers 			.cipher = __VECS(xeta_tv_template)
3645da7f033dSHerbert Xu 		}
3646da7f033dSHerbert Xu 	}, {
3647da7f033dSHerbert Xu 		.alg = "ecb(xtea)",
36481aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3649da7f033dSHerbert Xu 		.suite = {
365092a4c9feSEric Biggers 			.cipher = __VECS(xtea_tv_template)
3651da7f033dSHerbert Xu 		}
3652da7f033dSHerbert Xu 	}, {
36533c4b2390SSalvatore Benedetto 		.alg = "ecdh",
36543c4b2390SSalvatore Benedetto 		.test = alg_test_kpp,
36553c4b2390SSalvatore Benedetto 		.fips_allowed = 1,
36563c4b2390SSalvatore Benedetto 		.suite = {
365721c8e720SArd Biesheuvel 			.kpp = __VECS(ecdh_tv_template)
36583c4b2390SSalvatore Benedetto 		}
36593c4b2390SSalvatore Benedetto 	}, {
3660da7f033dSHerbert Xu 		.alg = "gcm(aes)",
3661da7f033dSHerbert Xu 		.test = alg_test_aead,
3662a1915d51SJarod Wilson 		.fips_allowed = 1,
3663da7f033dSHerbert Xu 		.suite = {
3664a0d608eeSEric Biggers 			.aead = __VECS(aes_gcm_tv_template)
3665da7f033dSHerbert Xu 		}
3666da7f033dSHerbert Xu 	}, {
3667507069c9SYouquan, Song 		.alg = "ghash",
3668507069c9SYouquan, Song 		.test = alg_test_hash,
366918c0ebd2SJarod Wilson 		.fips_allowed = 1,
3670507069c9SYouquan, Song 		.suite = {
367121c8e720SArd Biesheuvel 			.hash = __VECS(ghash_tv_template)
3672507069c9SYouquan, Song 		}
3673507069c9SYouquan, Song 	}, {
3674da7f033dSHerbert Xu 		.alg = "hmac(md5)",
3675da7f033dSHerbert Xu 		.test = alg_test_hash,
3676da7f033dSHerbert Xu 		.suite = {
367721c8e720SArd Biesheuvel 			.hash = __VECS(hmac_md5_tv_template)
3678da7f033dSHerbert Xu 		}
3679da7f033dSHerbert Xu 	}, {
3680da7f033dSHerbert Xu 		.alg = "hmac(rmd128)",
3681da7f033dSHerbert Xu 		.test = alg_test_hash,
3682da7f033dSHerbert Xu 		.suite = {
368321c8e720SArd Biesheuvel 			.hash = __VECS(hmac_rmd128_tv_template)
3684da7f033dSHerbert Xu 		}
3685da7f033dSHerbert Xu 	}, {
3686da7f033dSHerbert Xu 		.alg = "hmac(rmd160)",
3687da7f033dSHerbert Xu 		.test = alg_test_hash,
3688da7f033dSHerbert Xu 		.suite = {
368921c8e720SArd Biesheuvel 			.hash = __VECS(hmac_rmd160_tv_template)
3690da7f033dSHerbert Xu 		}
3691da7f033dSHerbert Xu 	}, {
3692da7f033dSHerbert Xu 		.alg = "hmac(sha1)",
3693da7f033dSHerbert Xu 		.test = alg_test_hash,
3694a1915d51SJarod Wilson 		.fips_allowed = 1,
3695da7f033dSHerbert Xu 		.suite = {
369621c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha1_tv_template)
3697da7f033dSHerbert Xu 		}
3698da7f033dSHerbert Xu 	}, {
3699da7f033dSHerbert Xu 		.alg = "hmac(sha224)",
3700da7f033dSHerbert Xu 		.test = alg_test_hash,
3701a1915d51SJarod Wilson 		.fips_allowed = 1,
3702da7f033dSHerbert Xu 		.suite = {
370321c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha224_tv_template)
3704da7f033dSHerbert Xu 		}
3705da7f033dSHerbert Xu 	}, {
3706da7f033dSHerbert Xu 		.alg = "hmac(sha256)",
3707da7f033dSHerbert Xu 		.test = alg_test_hash,
3708a1915d51SJarod Wilson 		.fips_allowed = 1,
3709da7f033dSHerbert Xu 		.suite = {
371021c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha256_tv_template)
3711da7f033dSHerbert Xu 		}
3712da7f033dSHerbert Xu 	}, {
371398eca72fSraveendra padasalagi 		.alg = "hmac(sha3-224)",
371498eca72fSraveendra padasalagi 		.test = alg_test_hash,
371598eca72fSraveendra padasalagi 		.fips_allowed = 1,
371698eca72fSraveendra padasalagi 		.suite = {
371721c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_224_tv_template)
371898eca72fSraveendra padasalagi 		}
371998eca72fSraveendra padasalagi 	}, {
372098eca72fSraveendra padasalagi 		.alg = "hmac(sha3-256)",
372198eca72fSraveendra padasalagi 		.test = alg_test_hash,
372298eca72fSraveendra padasalagi 		.fips_allowed = 1,
372398eca72fSraveendra padasalagi 		.suite = {
372421c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_256_tv_template)
372598eca72fSraveendra padasalagi 		}
372698eca72fSraveendra padasalagi 	}, {
372798eca72fSraveendra padasalagi 		.alg = "hmac(sha3-384)",
372898eca72fSraveendra padasalagi 		.test = alg_test_hash,
372998eca72fSraveendra padasalagi 		.fips_allowed = 1,
373098eca72fSraveendra padasalagi 		.suite = {
373121c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_384_tv_template)
373298eca72fSraveendra padasalagi 		}
373398eca72fSraveendra padasalagi 	}, {
373498eca72fSraveendra padasalagi 		.alg = "hmac(sha3-512)",
373598eca72fSraveendra padasalagi 		.test = alg_test_hash,
373698eca72fSraveendra padasalagi 		.fips_allowed = 1,
373798eca72fSraveendra padasalagi 		.suite = {
373821c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_512_tv_template)
373998eca72fSraveendra padasalagi 		}
374098eca72fSraveendra padasalagi 	}, {
3741da7f033dSHerbert Xu 		.alg = "hmac(sha384)",
3742da7f033dSHerbert Xu 		.test = alg_test_hash,
3743a1915d51SJarod Wilson 		.fips_allowed = 1,
3744da7f033dSHerbert Xu 		.suite = {
374521c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha384_tv_template)
3746da7f033dSHerbert Xu 		}
3747da7f033dSHerbert Xu 	}, {
3748da7f033dSHerbert Xu 		.alg = "hmac(sha512)",
3749da7f033dSHerbert Xu 		.test = alg_test_hash,
3750a1915d51SJarod Wilson 		.fips_allowed = 1,
3751da7f033dSHerbert Xu 		.suite = {
375221c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha512_tv_template)
3753da7f033dSHerbert Xu 		}
3754da7f033dSHerbert Xu 	}, {
375525a0b9d4SVitaly Chikunov 		.alg = "hmac(streebog256)",
375625a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
375725a0b9d4SVitaly Chikunov 		.suite = {
375825a0b9d4SVitaly Chikunov 			.hash = __VECS(hmac_streebog256_tv_template)
375925a0b9d4SVitaly Chikunov 		}
376025a0b9d4SVitaly Chikunov 	}, {
376125a0b9d4SVitaly Chikunov 		.alg = "hmac(streebog512)",
376225a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
376325a0b9d4SVitaly Chikunov 		.suite = {
376425a0b9d4SVitaly Chikunov 			.hash = __VECS(hmac_streebog512_tv_template)
376525a0b9d4SVitaly Chikunov 		}
376625a0b9d4SVitaly Chikunov 	}, {
3767bb5530e4SStephan Mueller 		.alg = "jitterentropy_rng",
3768bb5530e4SStephan Mueller 		.fips_allowed = 1,
3769bb5530e4SStephan Mueller 		.test = alg_test_null,
3770bb5530e4SStephan Mueller 	}, {
377135351988SStephan Mueller 		.alg = "kw(aes)",
377235351988SStephan Mueller 		.test = alg_test_skcipher,
377335351988SStephan Mueller 		.fips_allowed = 1,
377435351988SStephan Mueller 		.suite = {
377592a4c9feSEric Biggers 			.cipher = __VECS(aes_kw_tv_template)
377635351988SStephan Mueller 		}
377735351988SStephan Mueller 	}, {
3778da7f033dSHerbert Xu 		.alg = "lrw(aes)",
37791aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3780da7f033dSHerbert Xu 		.suite = {
378192a4c9feSEric Biggers 			.cipher = __VECS(aes_lrw_tv_template)
3782da7f033dSHerbert Xu 		}
3783da7f033dSHerbert Xu 	}, {
37840840605eSJussi Kivilinna 		.alg = "lrw(camellia)",
37850840605eSJussi Kivilinna 		.test = alg_test_skcipher,
37860840605eSJussi Kivilinna 		.suite = {
378792a4c9feSEric Biggers 			.cipher = __VECS(camellia_lrw_tv_template)
37880840605eSJussi Kivilinna 		}
37890840605eSJussi Kivilinna 	}, {
37909b8b0405SJohannes Goetzfried 		.alg = "lrw(cast6)",
37919b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
37929b8b0405SJohannes Goetzfried 		.suite = {
379392a4c9feSEric Biggers 			.cipher = __VECS(cast6_lrw_tv_template)
37949b8b0405SJohannes Goetzfried 		}
37959b8b0405SJohannes Goetzfried 	}, {
3796d7bfc0faSJussi Kivilinna 		.alg = "lrw(serpent)",
3797d7bfc0faSJussi Kivilinna 		.test = alg_test_skcipher,
3798d7bfc0faSJussi Kivilinna 		.suite = {
379992a4c9feSEric Biggers 			.cipher = __VECS(serpent_lrw_tv_template)
3800d7bfc0faSJussi Kivilinna 		}
3801d7bfc0faSJussi Kivilinna 	}, {
38020b2a1551SJussi Kivilinna 		.alg = "lrw(twofish)",
38030b2a1551SJussi Kivilinna 		.test = alg_test_skcipher,
38040b2a1551SJussi Kivilinna 		.suite = {
380592a4c9feSEric Biggers 			.cipher = __VECS(tf_lrw_tv_template)
38060b2a1551SJussi Kivilinna 		}
38070b2a1551SJussi Kivilinna 	}, {
38081443cc9bSKOVACS Krisztian 		.alg = "lz4",
38091443cc9bSKOVACS Krisztian 		.test = alg_test_comp,
38101443cc9bSKOVACS Krisztian 		.fips_allowed = 1,
38111443cc9bSKOVACS Krisztian 		.suite = {
38121443cc9bSKOVACS Krisztian 			.comp = {
381321c8e720SArd Biesheuvel 				.comp = __VECS(lz4_comp_tv_template),
381421c8e720SArd Biesheuvel 				.decomp = __VECS(lz4_decomp_tv_template)
38151443cc9bSKOVACS Krisztian 			}
38161443cc9bSKOVACS Krisztian 		}
38171443cc9bSKOVACS Krisztian 	}, {
38181443cc9bSKOVACS Krisztian 		.alg = "lz4hc",
38191443cc9bSKOVACS Krisztian 		.test = alg_test_comp,
38201443cc9bSKOVACS Krisztian 		.fips_allowed = 1,
38211443cc9bSKOVACS Krisztian 		.suite = {
38221443cc9bSKOVACS Krisztian 			.comp = {
382321c8e720SArd Biesheuvel 				.comp = __VECS(lz4hc_comp_tv_template),
382421c8e720SArd Biesheuvel 				.decomp = __VECS(lz4hc_decomp_tv_template)
38251443cc9bSKOVACS Krisztian 			}
38261443cc9bSKOVACS Krisztian 		}
38271443cc9bSKOVACS Krisztian 	}, {
3828da7f033dSHerbert Xu 		.alg = "lzo",
3829da7f033dSHerbert Xu 		.test = alg_test_comp,
38300818904dSMilan Broz 		.fips_allowed = 1,
3831da7f033dSHerbert Xu 		.suite = {
3832da7f033dSHerbert Xu 			.comp = {
383321c8e720SArd Biesheuvel 				.comp = __VECS(lzo_comp_tv_template),
383421c8e720SArd Biesheuvel 				.decomp = __VECS(lzo_decomp_tv_template)
3835da7f033dSHerbert Xu 			}
3836da7f033dSHerbert Xu 		}
3837da7f033dSHerbert Xu 	}, {
3838da7f033dSHerbert Xu 		.alg = "md4",
3839da7f033dSHerbert Xu 		.test = alg_test_hash,
3840da7f033dSHerbert Xu 		.suite = {
384121c8e720SArd Biesheuvel 			.hash = __VECS(md4_tv_template)
3842da7f033dSHerbert Xu 		}
3843da7f033dSHerbert Xu 	}, {
3844da7f033dSHerbert Xu 		.alg = "md5",
3845da7f033dSHerbert Xu 		.test = alg_test_hash,
3846da7f033dSHerbert Xu 		.suite = {
384721c8e720SArd Biesheuvel 			.hash = __VECS(md5_tv_template)
3848da7f033dSHerbert Xu 		}
3849da7f033dSHerbert Xu 	}, {
3850da7f033dSHerbert Xu 		.alg = "michael_mic",
3851da7f033dSHerbert Xu 		.test = alg_test_hash,
3852da7f033dSHerbert Xu 		.suite = {
385321c8e720SArd Biesheuvel 			.hash = __VECS(michael_mic_tv_template)
3854da7f033dSHerbert Xu 		}
3855da7f033dSHerbert Xu 	}, {
38564feb4c59SOndrej Mosnacek 		.alg = "morus1280",
38574feb4c59SOndrej Mosnacek 		.test = alg_test_aead,
38584feb4c59SOndrej Mosnacek 		.suite = {
3859a0d608eeSEric Biggers 			.aead = __VECS(morus1280_tv_template)
38604feb4c59SOndrej Mosnacek 		}
38614feb4c59SOndrej Mosnacek 	}, {
38624feb4c59SOndrej Mosnacek 		.alg = "morus640",
38634feb4c59SOndrej Mosnacek 		.test = alg_test_aead,
38644feb4c59SOndrej Mosnacek 		.suite = {
3865a0d608eeSEric Biggers 			.aead = __VECS(morus640_tv_template)
38664feb4c59SOndrej Mosnacek 		}
38674feb4c59SOndrej Mosnacek 	}, {
386826609a21SEric Biggers 		.alg = "nhpoly1305",
386926609a21SEric Biggers 		.test = alg_test_hash,
387026609a21SEric Biggers 		.suite = {
387126609a21SEric Biggers 			.hash = __VECS(nhpoly1305_tv_template)
387226609a21SEric Biggers 		}
387326609a21SEric Biggers 	}, {
3874ba0e14acSPuneet Saxena 		.alg = "ofb(aes)",
3875ba0e14acSPuneet Saxena 		.test = alg_test_skcipher,
3876ba0e14acSPuneet Saxena 		.fips_allowed = 1,
3877ba0e14acSPuneet Saxena 		.suite = {
387892a4c9feSEric Biggers 			.cipher = __VECS(aes_ofb_tv_template)
3879ba0e14acSPuneet Saxena 		}
3880ba0e14acSPuneet Saxena 	}, {
3881a794d8d8SGilad Ben-Yossef 		/* Same as ofb(aes) except the key is stored in
3882a794d8d8SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
3883a794d8d8SGilad Ben-Yossef 		 */
3884a794d8d8SGilad Ben-Yossef 		.alg = "ofb(paes)",
3885a794d8d8SGilad Ben-Yossef 		.test = alg_test_null,
3886a794d8d8SGilad Ben-Yossef 		.fips_allowed = 1,
3887a794d8d8SGilad Ben-Yossef 	}, {
3888da7f033dSHerbert Xu 		.alg = "pcbc(fcrypt)",
38891aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3890da7f033dSHerbert Xu 		.suite = {
389192a4c9feSEric Biggers 			.cipher = __VECS(fcrypt_pcbc_tv_template)
3892da7f033dSHerbert Xu 		}
3893da7f033dSHerbert Xu 	}, {
38941207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha224)",
38951207107cSStephan Mueller 		.test = alg_test_null,
38961207107cSStephan Mueller 		.fips_allowed = 1,
38971207107cSStephan Mueller 	}, {
38981207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha256)",
38991207107cSStephan Mueller 		.test = alg_test_akcipher,
39001207107cSStephan Mueller 		.fips_allowed = 1,
39011207107cSStephan Mueller 		.suite = {
39021207107cSStephan Mueller 			.akcipher = __VECS(pkcs1pad_rsa_tv_template)
39031207107cSStephan Mueller 		}
39041207107cSStephan Mueller 	}, {
39051207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha384)",
39061207107cSStephan Mueller 		.test = alg_test_null,
39071207107cSStephan Mueller 		.fips_allowed = 1,
39081207107cSStephan Mueller 	}, {
39091207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha512)",
39101207107cSStephan Mueller 		.test = alg_test_null,
39111207107cSStephan Mueller 		.fips_allowed = 1,
39121207107cSStephan Mueller 	}, {
3913eee9dc61SMartin Willi 		.alg = "poly1305",
3914eee9dc61SMartin Willi 		.test = alg_test_hash,
3915eee9dc61SMartin Willi 		.suite = {
391621c8e720SArd Biesheuvel 			.hash = __VECS(poly1305_tv_template)
3917eee9dc61SMartin Willi 		}
3918eee9dc61SMartin Willi 	}, {
3919da7f033dSHerbert Xu 		.alg = "rfc3686(ctr(aes))",
39201aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3921a1915d51SJarod Wilson 		.fips_allowed = 1,
3922da7f033dSHerbert Xu 		.suite = {
392392a4c9feSEric Biggers 			.cipher = __VECS(aes_ctr_rfc3686_tv_template)
3924da7f033dSHerbert Xu 		}
3925da7f033dSHerbert Xu 	}, {
39263f31a740SHerbert Xu 		.alg = "rfc4106(gcm(aes))",
392769435b94SAdrian Hoban 		.test = alg_test_aead,
3928db71f29aSJarod Wilson 		.fips_allowed = 1,
392969435b94SAdrian Hoban 		.suite = {
3930a0d608eeSEric Biggers 			.aead = __VECS(aes_gcm_rfc4106_tv_template)
393169435b94SAdrian Hoban 		}
393269435b94SAdrian Hoban 	}, {
3933544c436aSHerbert Xu 		.alg = "rfc4309(ccm(aes))",
39345d667322SJarod Wilson 		.test = alg_test_aead,
3935a1915d51SJarod Wilson 		.fips_allowed = 1,
39365d667322SJarod Wilson 		.suite = {
3937a0d608eeSEric Biggers 			.aead = __VECS(aes_ccm_rfc4309_tv_template)
39385d667322SJarod Wilson 		}
39395d667322SJarod Wilson 	}, {
3940bb68745eSHerbert Xu 		.alg = "rfc4543(gcm(aes))",
3941e9b7441aSJussi Kivilinna 		.test = alg_test_aead,
3942e9b7441aSJussi Kivilinna 		.suite = {
3943a0d608eeSEric Biggers 			.aead = __VECS(aes_gcm_rfc4543_tv_template)
3944e9b7441aSJussi Kivilinna 		}
3945e9b7441aSJussi Kivilinna 	}, {
3946af2b76b5SMartin Willi 		.alg = "rfc7539(chacha20,poly1305)",
3947af2b76b5SMartin Willi 		.test = alg_test_aead,
3948af2b76b5SMartin Willi 		.suite = {
3949a0d608eeSEric Biggers 			.aead = __VECS(rfc7539_tv_template)
3950af2b76b5SMartin Willi 		}
3951af2b76b5SMartin Willi 	}, {
39525900758dSMartin Willi 		.alg = "rfc7539esp(chacha20,poly1305)",
39535900758dSMartin Willi 		.test = alg_test_aead,
39545900758dSMartin Willi 		.suite = {
3955a0d608eeSEric Biggers 			.aead = __VECS(rfc7539esp_tv_template)
39565900758dSMartin Willi 		}
39575900758dSMartin Willi 	}, {
3958da7f033dSHerbert Xu 		.alg = "rmd128",
3959da7f033dSHerbert Xu 		.test = alg_test_hash,
3960da7f033dSHerbert Xu 		.suite = {
396121c8e720SArd Biesheuvel 			.hash = __VECS(rmd128_tv_template)
3962da7f033dSHerbert Xu 		}
3963da7f033dSHerbert Xu 	}, {
3964da7f033dSHerbert Xu 		.alg = "rmd160",
3965da7f033dSHerbert Xu 		.test = alg_test_hash,
3966da7f033dSHerbert Xu 		.suite = {
396721c8e720SArd Biesheuvel 			.hash = __VECS(rmd160_tv_template)
3968da7f033dSHerbert Xu 		}
3969da7f033dSHerbert Xu 	}, {
3970da7f033dSHerbert Xu 		.alg = "rmd256",
3971da7f033dSHerbert Xu 		.test = alg_test_hash,
3972da7f033dSHerbert Xu 		.suite = {
397321c8e720SArd Biesheuvel 			.hash = __VECS(rmd256_tv_template)
3974da7f033dSHerbert Xu 		}
3975da7f033dSHerbert Xu 	}, {
3976da7f033dSHerbert Xu 		.alg = "rmd320",
3977da7f033dSHerbert Xu 		.test = alg_test_hash,
3978da7f033dSHerbert Xu 		.suite = {
397921c8e720SArd Biesheuvel 			.hash = __VECS(rmd320_tv_template)
3980da7f033dSHerbert Xu 		}
3981da7f033dSHerbert Xu 	}, {
3982946cc463STadeusz Struk 		.alg = "rsa",
3983946cc463STadeusz Struk 		.test = alg_test_akcipher,
3984946cc463STadeusz Struk 		.fips_allowed = 1,
3985946cc463STadeusz Struk 		.suite = {
398621c8e720SArd Biesheuvel 			.akcipher = __VECS(rsa_tv_template)
3987946cc463STadeusz Struk 		}
3988946cc463STadeusz Struk 	}, {
3989da7f033dSHerbert Xu 		.alg = "salsa20",
39901aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3991da7f033dSHerbert Xu 		.suite = {
399292a4c9feSEric Biggers 			.cipher = __VECS(salsa20_stream_tv_template)
3993da7f033dSHerbert Xu 		}
3994da7f033dSHerbert Xu 	}, {
3995da7f033dSHerbert Xu 		.alg = "sha1",
3996da7f033dSHerbert Xu 		.test = alg_test_hash,
3997a1915d51SJarod Wilson 		.fips_allowed = 1,
3998da7f033dSHerbert Xu 		.suite = {
399921c8e720SArd Biesheuvel 			.hash = __VECS(sha1_tv_template)
4000da7f033dSHerbert Xu 		}
4001da7f033dSHerbert Xu 	}, {
4002da7f033dSHerbert Xu 		.alg = "sha224",
4003da7f033dSHerbert Xu 		.test = alg_test_hash,
4004a1915d51SJarod Wilson 		.fips_allowed = 1,
4005da7f033dSHerbert Xu 		.suite = {
400621c8e720SArd Biesheuvel 			.hash = __VECS(sha224_tv_template)
4007da7f033dSHerbert Xu 		}
4008da7f033dSHerbert Xu 	}, {
4009da7f033dSHerbert Xu 		.alg = "sha256",
4010da7f033dSHerbert Xu 		.test = alg_test_hash,
4011a1915d51SJarod Wilson 		.fips_allowed = 1,
4012da7f033dSHerbert Xu 		.suite = {
401321c8e720SArd Biesheuvel 			.hash = __VECS(sha256_tv_template)
4014da7f033dSHerbert Xu 		}
4015da7f033dSHerbert Xu 	}, {
401679cc6ab8Sraveendra padasalagi 		.alg = "sha3-224",
401779cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
401879cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
401979cc6ab8Sraveendra padasalagi 		.suite = {
402021c8e720SArd Biesheuvel 			.hash = __VECS(sha3_224_tv_template)
402179cc6ab8Sraveendra padasalagi 		}
402279cc6ab8Sraveendra padasalagi 	}, {
402379cc6ab8Sraveendra padasalagi 		.alg = "sha3-256",
402479cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
402579cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
402679cc6ab8Sraveendra padasalagi 		.suite = {
402721c8e720SArd Biesheuvel 			.hash = __VECS(sha3_256_tv_template)
402879cc6ab8Sraveendra padasalagi 		}
402979cc6ab8Sraveendra padasalagi 	}, {
403079cc6ab8Sraveendra padasalagi 		.alg = "sha3-384",
403179cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
403279cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
403379cc6ab8Sraveendra padasalagi 		.suite = {
403421c8e720SArd Biesheuvel 			.hash = __VECS(sha3_384_tv_template)
403579cc6ab8Sraveendra padasalagi 		}
403679cc6ab8Sraveendra padasalagi 	}, {
403779cc6ab8Sraveendra padasalagi 		.alg = "sha3-512",
403879cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
403979cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
404079cc6ab8Sraveendra padasalagi 		.suite = {
404121c8e720SArd Biesheuvel 			.hash = __VECS(sha3_512_tv_template)
404279cc6ab8Sraveendra padasalagi 		}
404379cc6ab8Sraveendra padasalagi 	}, {
4044da7f033dSHerbert Xu 		.alg = "sha384",
4045da7f033dSHerbert Xu 		.test = alg_test_hash,
4046a1915d51SJarod Wilson 		.fips_allowed = 1,
4047da7f033dSHerbert Xu 		.suite = {
404821c8e720SArd Biesheuvel 			.hash = __VECS(sha384_tv_template)
4049da7f033dSHerbert Xu 		}
4050da7f033dSHerbert Xu 	}, {
4051da7f033dSHerbert Xu 		.alg = "sha512",
4052da7f033dSHerbert Xu 		.test = alg_test_hash,
4053a1915d51SJarod Wilson 		.fips_allowed = 1,
4054da7f033dSHerbert Xu 		.suite = {
405521c8e720SArd Biesheuvel 			.hash = __VECS(sha512_tv_template)
4056da7f033dSHerbert Xu 		}
4057da7f033dSHerbert Xu 	}, {
4058b7e27530SGilad Ben-Yossef 		.alg = "sm3",
4059b7e27530SGilad Ben-Yossef 		.test = alg_test_hash,
4060b7e27530SGilad Ben-Yossef 		.suite = {
4061b7e27530SGilad Ben-Yossef 			.hash = __VECS(sm3_tv_template)
4062b7e27530SGilad Ben-Yossef 		}
4063b7e27530SGilad Ben-Yossef 	}, {
406425a0b9d4SVitaly Chikunov 		.alg = "streebog256",
406525a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
406625a0b9d4SVitaly Chikunov 		.suite = {
406725a0b9d4SVitaly Chikunov 			.hash = __VECS(streebog256_tv_template)
406825a0b9d4SVitaly Chikunov 		}
406925a0b9d4SVitaly Chikunov 	}, {
407025a0b9d4SVitaly Chikunov 		.alg = "streebog512",
407125a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
407225a0b9d4SVitaly Chikunov 		.suite = {
407325a0b9d4SVitaly Chikunov 			.hash = __VECS(streebog512_tv_template)
407425a0b9d4SVitaly Chikunov 		}
407525a0b9d4SVitaly Chikunov 	}, {
4076da7f033dSHerbert Xu 		.alg = "tgr128",
4077da7f033dSHerbert Xu 		.test = alg_test_hash,
4078da7f033dSHerbert Xu 		.suite = {
407921c8e720SArd Biesheuvel 			.hash = __VECS(tgr128_tv_template)
4080da7f033dSHerbert Xu 		}
4081da7f033dSHerbert Xu 	}, {
4082da7f033dSHerbert Xu 		.alg = "tgr160",
4083da7f033dSHerbert Xu 		.test = alg_test_hash,
4084da7f033dSHerbert Xu 		.suite = {
408521c8e720SArd Biesheuvel 			.hash = __VECS(tgr160_tv_template)
4086da7f033dSHerbert Xu 		}
4087da7f033dSHerbert Xu 	}, {
4088da7f033dSHerbert Xu 		.alg = "tgr192",
4089da7f033dSHerbert Xu 		.test = alg_test_hash,
4090da7f033dSHerbert Xu 		.suite = {
409121c8e720SArd Biesheuvel 			.hash = __VECS(tgr192_tv_template)
4092da7f033dSHerbert Xu 		}
4093da7f033dSHerbert Xu 	}, {
4094ed331adaSEric Biggers 		.alg = "vmac64(aes)",
4095ed331adaSEric Biggers 		.test = alg_test_hash,
4096ed331adaSEric Biggers 		.suite = {
4097ed331adaSEric Biggers 			.hash = __VECS(vmac64_aes_tv_template)
4098ed331adaSEric Biggers 		}
4099ed331adaSEric Biggers 	}, {
4100da7f033dSHerbert Xu 		.alg = "wp256",
4101da7f033dSHerbert Xu 		.test = alg_test_hash,
4102da7f033dSHerbert Xu 		.suite = {
410321c8e720SArd Biesheuvel 			.hash = __VECS(wp256_tv_template)
4104da7f033dSHerbert Xu 		}
4105da7f033dSHerbert Xu 	}, {
4106da7f033dSHerbert Xu 		.alg = "wp384",
4107da7f033dSHerbert Xu 		.test = alg_test_hash,
4108da7f033dSHerbert Xu 		.suite = {
410921c8e720SArd Biesheuvel 			.hash = __VECS(wp384_tv_template)
4110da7f033dSHerbert Xu 		}
4111da7f033dSHerbert Xu 	}, {
4112da7f033dSHerbert Xu 		.alg = "wp512",
4113da7f033dSHerbert Xu 		.test = alg_test_hash,
4114da7f033dSHerbert Xu 		.suite = {
411521c8e720SArd Biesheuvel 			.hash = __VECS(wp512_tv_template)
4116da7f033dSHerbert Xu 		}
4117da7f033dSHerbert Xu 	}, {
4118da7f033dSHerbert Xu 		.alg = "xcbc(aes)",
4119da7f033dSHerbert Xu 		.test = alg_test_hash,
4120da7f033dSHerbert Xu 		.suite = {
412121c8e720SArd Biesheuvel 			.hash = __VECS(aes_xcbc128_tv_template)
4122da7f033dSHerbert Xu 		}
4123da7f033dSHerbert Xu 	}, {
4124aa762409SEric Biggers 		.alg = "xchacha12",
4125aa762409SEric Biggers 		.test = alg_test_skcipher,
4126aa762409SEric Biggers 		.suite = {
4127aa762409SEric Biggers 			.cipher = __VECS(xchacha12_tv_template)
4128aa762409SEric Biggers 		},
4129aa762409SEric Biggers 	}, {
4130de61d7aeSEric Biggers 		.alg = "xchacha20",
4131de61d7aeSEric Biggers 		.test = alg_test_skcipher,
4132de61d7aeSEric Biggers 		.suite = {
4133de61d7aeSEric Biggers 			.cipher = __VECS(xchacha20_tv_template)
4134de61d7aeSEric Biggers 		},
4135de61d7aeSEric Biggers 	}, {
4136da7f033dSHerbert Xu 		.alg = "xts(aes)",
41371aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
41382918aa8dSJarod Wilson 		.fips_allowed = 1,
4139da7f033dSHerbert Xu 		.suite = {
414092a4c9feSEric Biggers 			.cipher = __VECS(aes_xts_tv_template)
4141da7f033dSHerbert Xu 		}
41420c01aed5SGeert Uytterhoeven 	}, {
41430840605eSJussi Kivilinna 		.alg = "xts(camellia)",
41440840605eSJussi Kivilinna 		.test = alg_test_skcipher,
41450840605eSJussi Kivilinna 		.suite = {
414692a4c9feSEric Biggers 			.cipher = __VECS(camellia_xts_tv_template)
41470840605eSJussi Kivilinna 		}
41480840605eSJussi Kivilinna 	}, {
41499b8b0405SJohannes Goetzfried 		.alg = "xts(cast6)",
41509b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
41519b8b0405SJohannes Goetzfried 		.suite = {
415292a4c9feSEric Biggers 			.cipher = __VECS(cast6_xts_tv_template)
41539b8b0405SJohannes Goetzfried 		}
41549b8b0405SJohannes Goetzfried 	}, {
415515f47ce5SGilad Ben-Yossef 		/* Same as xts(aes) except the key is stored in
415615f47ce5SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
415715f47ce5SGilad Ben-Yossef 		 */
415815f47ce5SGilad Ben-Yossef 		.alg = "xts(paes)",
415915f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
416015f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
416115f47ce5SGilad Ben-Yossef 	}, {
416218be20b9SJussi Kivilinna 		.alg = "xts(serpent)",
416318be20b9SJussi Kivilinna 		.test = alg_test_skcipher,
416418be20b9SJussi Kivilinna 		.suite = {
416592a4c9feSEric Biggers 			.cipher = __VECS(serpent_xts_tv_template)
416618be20b9SJussi Kivilinna 		}
416718be20b9SJussi Kivilinna 	}, {
4168aed265b9SJussi Kivilinna 		.alg = "xts(twofish)",
4169aed265b9SJussi Kivilinna 		.test = alg_test_skcipher,
4170aed265b9SJussi Kivilinna 		.suite = {
417192a4c9feSEric Biggers 			.cipher = __VECS(tf_xts_tv_template)
4172aed265b9SJussi Kivilinna 		}
4173a368f43dSGiovanni Cabiddu 	}, {
417415f47ce5SGilad Ben-Yossef 		.alg = "xts4096(paes)",
417515f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
417615f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
417715f47ce5SGilad Ben-Yossef 	}, {
417815f47ce5SGilad Ben-Yossef 		.alg = "xts512(paes)",
417915f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
418015f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
418115f47ce5SGilad Ben-Yossef 	}, {
4182a368f43dSGiovanni Cabiddu 		.alg = "zlib-deflate",
4183a368f43dSGiovanni Cabiddu 		.test = alg_test_comp,
4184a368f43dSGiovanni Cabiddu 		.fips_allowed = 1,
4185a368f43dSGiovanni Cabiddu 		.suite = {
4186a368f43dSGiovanni Cabiddu 			.comp = {
4187a368f43dSGiovanni Cabiddu 				.comp = __VECS(zlib_deflate_comp_tv_template),
4188a368f43dSGiovanni Cabiddu 				.decomp = __VECS(zlib_deflate_decomp_tv_template)
4189a368f43dSGiovanni Cabiddu 			}
4190a368f43dSGiovanni Cabiddu 		}
4191d28fc3dbSNick Terrell 	}, {
4192d28fc3dbSNick Terrell 		.alg = "zstd",
4193d28fc3dbSNick Terrell 		.test = alg_test_comp,
4194d28fc3dbSNick Terrell 		.fips_allowed = 1,
4195d28fc3dbSNick Terrell 		.suite = {
4196d28fc3dbSNick Terrell 			.comp = {
4197d28fc3dbSNick Terrell 				.comp = __VECS(zstd_comp_tv_template),
4198d28fc3dbSNick Terrell 				.decomp = __VECS(zstd_decomp_tv_template)
4199d28fc3dbSNick Terrell 			}
4200d28fc3dbSNick Terrell 		}
4201da7f033dSHerbert Xu 	}
4202da7f033dSHerbert Xu };
4203da7f033dSHerbert Xu 
42043f47a03dSEric Biggers static void alg_check_test_descs_order(void)
42055714758bSJussi Kivilinna {
42065714758bSJussi Kivilinna 	int i;
42075714758bSJussi Kivilinna 
42085714758bSJussi Kivilinna 	for (i = 1; i < ARRAY_SIZE(alg_test_descs); i++) {
42095714758bSJussi Kivilinna 		int diff = strcmp(alg_test_descs[i - 1].alg,
42105714758bSJussi Kivilinna 				  alg_test_descs[i].alg);
42115714758bSJussi Kivilinna 
42125714758bSJussi Kivilinna 		if (WARN_ON(diff > 0)) {
42135714758bSJussi Kivilinna 			pr_warn("testmgr: alg_test_descs entries in wrong order: '%s' before '%s'\n",
42145714758bSJussi Kivilinna 				alg_test_descs[i - 1].alg,
42155714758bSJussi Kivilinna 				alg_test_descs[i].alg);
42165714758bSJussi Kivilinna 		}
42175714758bSJussi Kivilinna 
42185714758bSJussi Kivilinna 		if (WARN_ON(diff == 0)) {
42195714758bSJussi Kivilinna 			pr_warn("testmgr: duplicate alg_test_descs entry: '%s'\n",
42205714758bSJussi Kivilinna 				alg_test_descs[i].alg);
42215714758bSJussi Kivilinna 		}
42225714758bSJussi Kivilinna 	}
42235714758bSJussi Kivilinna }
42245714758bSJussi Kivilinna 
42253f47a03dSEric Biggers static void alg_check_testvec_configs(void)
42263f47a03dSEric Biggers {
42273f47a03dSEric Biggers }
42283f47a03dSEric Biggers 
42293f47a03dSEric Biggers static void testmgr_onetime_init(void)
42303f47a03dSEric Biggers {
42313f47a03dSEric Biggers 	alg_check_test_descs_order();
42323f47a03dSEric Biggers 	alg_check_testvec_configs();
42335b2706a4SEric Biggers 
42345b2706a4SEric Biggers #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
42355b2706a4SEric Biggers 	pr_warn("alg: extra crypto tests enabled.  This is intended for developer use only.\n");
42365b2706a4SEric Biggers #endif
42373f47a03dSEric Biggers }
42383f47a03dSEric Biggers 
42391aa4ecd9SHerbert Xu static int alg_find_test(const char *alg)
4240da7f033dSHerbert Xu {
4241da7f033dSHerbert Xu 	int start = 0;
4242da7f033dSHerbert Xu 	int end = ARRAY_SIZE(alg_test_descs);
4243da7f033dSHerbert Xu 
4244da7f033dSHerbert Xu 	while (start < end) {
4245da7f033dSHerbert Xu 		int i = (start + end) / 2;
4246da7f033dSHerbert Xu 		int diff = strcmp(alg_test_descs[i].alg, alg);
4247da7f033dSHerbert Xu 
4248da7f033dSHerbert Xu 		if (diff > 0) {
4249da7f033dSHerbert Xu 			end = i;
4250da7f033dSHerbert Xu 			continue;
4251da7f033dSHerbert Xu 		}
4252da7f033dSHerbert Xu 
4253da7f033dSHerbert Xu 		if (diff < 0) {
4254da7f033dSHerbert Xu 			start = i + 1;
4255da7f033dSHerbert Xu 			continue;
4256da7f033dSHerbert Xu 		}
4257da7f033dSHerbert Xu 
42581aa4ecd9SHerbert Xu 		return i;
4259da7f033dSHerbert Xu 	}
4260da7f033dSHerbert Xu 
42611aa4ecd9SHerbert Xu 	return -1;
42621aa4ecd9SHerbert Xu }
42631aa4ecd9SHerbert Xu 
42641aa4ecd9SHerbert Xu int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
42651aa4ecd9SHerbert Xu {
42661aa4ecd9SHerbert Xu 	int i;
4267a68f6610SHerbert Xu 	int j;
4268d12d6b6dSNeil Horman 	int rc;
42691aa4ecd9SHerbert Xu 
42709e5c9fe4SRichard W.M. Jones 	if (!fips_enabled && notests) {
42719e5c9fe4SRichard W.M. Jones 		printk_once(KERN_INFO "alg: self-tests disabled\n");
42729e5c9fe4SRichard W.M. Jones 		return 0;
42739e5c9fe4SRichard W.M. Jones 	}
42749e5c9fe4SRichard W.M. Jones 
42753f47a03dSEric Biggers 	DO_ONCE(testmgr_onetime_init);
42765714758bSJussi Kivilinna 
42771aa4ecd9SHerbert Xu 	if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) {
42781aa4ecd9SHerbert Xu 		char nalg[CRYPTO_MAX_ALG_NAME];
42791aa4ecd9SHerbert Xu 
42801aa4ecd9SHerbert Xu 		if (snprintf(nalg, sizeof(nalg), "ecb(%s)", alg) >=
42811aa4ecd9SHerbert Xu 		    sizeof(nalg))
42821aa4ecd9SHerbert Xu 			return -ENAMETOOLONG;
42831aa4ecd9SHerbert Xu 
42841aa4ecd9SHerbert Xu 		i = alg_find_test(nalg);
42851aa4ecd9SHerbert Xu 		if (i < 0)
42861aa4ecd9SHerbert Xu 			goto notest;
42871aa4ecd9SHerbert Xu 
4288a3bef3a3SJarod Wilson 		if (fips_enabled && !alg_test_descs[i].fips_allowed)
4289a3bef3a3SJarod Wilson 			goto non_fips_alg;
4290a3bef3a3SJarod Wilson 
4291941fb328SJarod Wilson 		rc = alg_test_cipher(alg_test_descs + i, driver, type, mask);
4292941fb328SJarod Wilson 		goto test_done;
42931aa4ecd9SHerbert Xu 	}
42941aa4ecd9SHerbert Xu 
42951aa4ecd9SHerbert Xu 	i = alg_find_test(alg);
4296a68f6610SHerbert Xu 	j = alg_find_test(driver);
4297a68f6610SHerbert Xu 	if (i < 0 && j < 0)
42981aa4ecd9SHerbert Xu 		goto notest;
42991aa4ecd9SHerbert Xu 
4300a68f6610SHerbert Xu 	if (fips_enabled && ((i >= 0 && !alg_test_descs[i].fips_allowed) ||
4301a68f6610SHerbert Xu 			     (j >= 0 && !alg_test_descs[j].fips_allowed)))
4302a3bef3a3SJarod Wilson 		goto non_fips_alg;
4303a3bef3a3SJarod Wilson 
4304a68f6610SHerbert Xu 	rc = 0;
4305a68f6610SHerbert Xu 	if (i >= 0)
4306a68f6610SHerbert Xu 		rc |= alg_test_descs[i].test(alg_test_descs + i, driver,
43071aa4ecd9SHerbert Xu 					     type, mask);
4308032c8cacSCristian Stoica 	if (j >= 0 && j != i)
4309a68f6610SHerbert Xu 		rc |= alg_test_descs[j].test(alg_test_descs + j, driver,
4310a68f6610SHerbert Xu 					     type, mask);
4311a68f6610SHerbert Xu 
4312941fb328SJarod Wilson test_done:
4313d12d6b6dSNeil Horman 	if (fips_enabled && rc)
4314d12d6b6dSNeil Horman 		panic("%s: %s alg self test failed in fips mode!\n", driver, alg);
4315d12d6b6dSNeil Horman 
431629ecd4abSJarod Wilson 	if (fips_enabled && !rc)
43173e8cffd4SMasanari Iida 		pr_info("alg: self-tests for %s (%s) passed\n", driver, alg);
431829ecd4abSJarod Wilson 
4319d12d6b6dSNeil Horman 	return rc;
43201aa4ecd9SHerbert Xu 
43211aa4ecd9SHerbert Xu notest:
4322da7f033dSHerbert Xu 	printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);
4323da7f033dSHerbert Xu 	return 0;
4324a3bef3a3SJarod Wilson non_fips_alg:
4325a3bef3a3SJarod Wilson 	return -EINVAL;
4326da7f033dSHerbert Xu }
43270b767f96SAlexander Shishkin 
4328326a6346SHerbert Xu #endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */
43290b767f96SAlexander Shishkin 
4330da7f033dSHerbert Xu EXPORT_SYMBOL_GPL(alg_test);
4331