xref: /openbmc/linux/crypto/testmgr.c (revision 3f47a03d)
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>
31da7f033dSHerbert Xu #include <linux/scatterlist.h>
32da7f033dSHerbert Xu #include <linux/slab.h>
33da7f033dSHerbert Xu #include <linux/string.h>
347647d6ceSJarod Wilson #include <crypto/rng.h>
3564d1cdfbSStephan Mueller #include <crypto/drbg.h>
36946cc463STadeusz Struk #include <crypto/akcipher.h>
37802c7f1cSSalvatore Benedetto #include <crypto/kpp.h>
38d7db7a88SGiovanni Cabiddu #include <crypto/acompress.h>
39da7f033dSHerbert Xu 
40da7f033dSHerbert Xu #include "internal.h"
410b767f96SAlexander Shishkin 
429e5c9fe4SRichard W.M. Jones static bool notests;
439e5c9fe4SRichard W.M. Jones module_param(notests, bool, 0644);
449e5c9fe4SRichard W.M. Jones MODULE_PARM_DESC(notests, "disable crypto self-tests");
459e5c9fe4SRichard W.M. Jones 
46326a6346SHerbert Xu #ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
470b767f96SAlexander Shishkin 
480b767f96SAlexander Shishkin /* a perfect nop */
490b767f96SAlexander Shishkin int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
500b767f96SAlexander Shishkin {
510b767f96SAlexander Shishkin 	return 0;
520b767f96SAlexander Shishkin }
530b767f96SAlexander Shishkin 
540b767f96SAlexander Shishkin #else
550b767f96SAlexander Shishkin 
56da7f033dSHerbert Xu #include "testmgr.h"
57da7f033dSHerbert Xu 
58da7f033dSHerbert Xu /*
59da7f033dSHerbert Xu  * Need slab memory for testing (size in number of pages).
60da7f033dSHerbert Xu  */
61da7f033dSHerbert Xu #define XBUFSIZE	8
62da7f033dSHerbert Xu 
63da7f033dSHerbert Xu /*
64da7f033dSHerbert Xu  * Indexes into the xbuf to simulate cross-page access.
65da7f033dSHerbert Xu  */
66da7f033dSHerbert Xu #define IDX1		32
67da7f033dSHerbert Xu #define IDX2		32400
6804b46fbdSArd Biesheuvel #define IDX3		1511
69da7f033dSHerbert Xu #define IDX4		8193
70da7f033dSHerbert Xu #define IDX5		22222
71da7f033dSHerbert Xu #define IDX6		17101
72da7f033dSHerbert Xu #define IDX7		27333
73da7f033dSHerbert Xu #define IDX8		3000
74da7f033dSHerbert Xu 
75da7f033dSHerbert Xu /*
76da7f033dSHerbert Xu * Used by test_cipher()
77da7f033dSHerbert Xu */
78da7f033dSHerbert Xu #define ENCRYPT 1
79da7f033dSHerbert Xu #define DECRYPT 0
80da7f033dSHerbert Xu 
81da7f033dSHerbert Xu struct aead_test_suite {
82b13b1e0cSEric Biggers 	const struct aead_testvec *vecs;
83da7f033dSHerbert Xu 	unsigned int count;
84da7f033dSHerbert Xu };
85da7f033dSHerbert Xu 
86da7f033dSHerbert Xu struct cipher_test_suite {
87b13b1e0cSEric Biggers 	const struct cipher_testvec *vecs;
88da7f033dSHerbert Xu 	unsigned int count;
89da7f033dSHerbert Xu };
90da7f033dSHerbert Xu 
91da7f033dSHerbert Xu struct comp_test_suite {
92da7f033dSHerbert Xu 	struct {
93b13b1e0cSEric Biggers 		const struct comp_testvec *vecs;
94da7f033dSHerbert Xu 		unsigned int count;
95da7f033dSHerbert Xu 	} comp, decomp;
96da7f033dSHerbert Xu };
97da7f033dSHerbert Xu 
98da7f033dSHerbert Xu struct hash_test_suite {
99b13b1e0cSEric Biggers 	const struct hash_testvec *vecs;
100da7f033dSHerbert Xu 	unsigned int count;
101da7f033dSHerbert Xu };
102da7f033dSHerbert Xu 
1037647d6ceSJarod Wilson struct cprng_test_suite {
104b13b1e0cSEric Biggers 	const struct cprng_testvec *vecs;
1057647d6ceSJarod Wilson 	unsigned int count;
1067647d6ceSJarod Wilson };
1077647d6ceSJarod Wilson 
10864d1cdfbSStephan Mueller struct drbg_test_suite {
109b13b1e0cSEric Biggers 	const struct drbg_testvec *vecs;
11064d1cdfbSStephan Mueller 	unsigned int count;
11164d1cdfbSStephan Mueller };
11264d1cdfbSStephan Mueller 
113946cc463STadeusz Struk struct akcipher_test_suite {
114b13b1e0cSEric Biggers 	const struct akcipher_testvec *vecs;
115946cc463STadeusz Struk 	unsigned int count;
116946cc463STadeusz Struk };
117946cc463STadeusz Struk 
118802c7f1cSSalvatore Benedetto struct kpp_test_suite {
119b13b1e0cSEric Biggers 	const struct kpp_testvec *vecs;
120802c7f1cSSalvatore Benedetto 	unsigned int count;
121802c7f1cSSalvatore Benedetto };
122802c7f1cSSalvatore Benedetto 
123da7f033dSHerbert Xu struct alg_test_desc {
124da7f033dSHerbert Xu 	const char *alg;
125da7f033dSHerbert Xu 	int (*test)(const struct alg_test_desc *desc, const char *driver,
126da7f033dSHerbert Xu 		    u32 type, u32 mask);
127a1915d51SJarod Wilson 	int fips_allowed;	/* set if alg is allowed in fips mode */
128da7f033dSHerbert Xu 
129da7f033dSHerbert Xu 	union {
130da7f033dSHerbert Xu 		struct aead_test_suite aead;
131da7f033dSHerbert Xu 		struct cipher_test_suite cipher;
132da7f033dSHerbert Xu 		struct comp_test_suite comp;
133da7f033dSHerbert Xu 		struct hash_test_suite hash;
1347647d6ceSJarod Wilson 		struct cprng_test_suite cprng;
13564d1cdfbSStephan Mueller 		struct drbg_test_suite drbg;
136946cc463STadeusz Struk 		struct akcipher_test_suite akcipher;
137802c7f1cSSalvatore Benedetto 		struct kpp_test_suite kpp;
138da7f033dSHerbert Xu 	} suite;
139da7f033dSHerbert Xu };
140da7f033dSHerbert Xu 
141b13b1e0cSEric Biggers static const unsigned int IDX[8] = {
142b13b1e0cSEric Biggers 	IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
143da7f033dSHerbert Xu 
144da7f033dSHerbert Xu static void hexdump(unsigned char *buf, unsigned int len)
145da7f033dSHerbert Xu {
146da7f033dSHerbert Xu 	print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
147da7f033dSHerbert Xu 			16, 1,
148da7f033dSHerbert Xu 			buf, len, false);
149da7f033dSHerbert Xu }
150da7f033dSHerbert Xu 
1513f47a03dSEric Biggers static int __testmgr_alloc_buf(char *buf[XBUFSIZE], int order)
152f8b0d4d0SHerbert Xu {
153f8b0d4d0SHerbert Xu 	int i;
154f8b0d4d0SHerbert Xu 
155f8b0d4d0SHerbert Xu 	for (i = 0; i < XBUFSIZE; i++) {
1563f47a03dSEric Biggers 		buf[i] = (char *)__get_free_pages(GFP_KERNEL, order);
157f8b0d4d0SHerbert Xu 		if (!buf[i])
158f8b0d4d0SHerbert Xu 			goto err_free_buf;
159f8b0d4d0SHerbert Xu 	}
160f8b0d4d0SHerbert Xu 
161f8b0d4d0SHerbert Xu 	return 0;
162f8b0d4d0SHerbert Xu 
163f8b0d4d0SHerbert Xu err_free_buf:
164f8b0d4d0SHerbert Xu 	while (i-- > 0)
1653f47a03dSEric Biggers 		free_pages((unsigned long)buf[i], order);
166f8b0d4d0SHerbert Xu 
167f8b0d4d0SHerbert Xu 	return -ENOMEM;
168f8b0d4d0SHerbert Xu }
169f8b0d4d0SHerbert Xu 
1703f47a03dSEric Biggers static int testmgr_alloc_buf(char *buf[XBUFSIZE])
1713f47a03dSEric Biggers {
1723f47a03dSEric Biggers 	return __testmgr_alloc_buf(buf, 0);
1733f47a03dSEric Biggers }
1743f47a03dSEric Biggers 
1753f47a03dSEric Biggers static void __testmgr_free_buf(char *buf[XBUFSIZE], int order)
176f8b0d4d0SHerbert Xu {
177f8b0d4d0SHerbert Xu 	int i;
178f8b0d4d0SHerbert Xu 
179f8b0d4d0SHerbert Xu 	for (i = 0; i < XBUFSIZE; i++)
1803f47a03dSEric Biggers 		free_pages((unsigned long)buf[i], order);
1813f47a03dSEric Biggers }
1823f47a03dSEric Biggers 
1833f47a03dSEric Biggers static void testmgr_free_buf(char *buf[XBUFSIZE])
1843f47a03dSEric Biggers {
1853f47a03dSEric Biggers 	__testmgr_free_buf(buf, 0);
1863f47a03dSEric Biggers }
1873f47a03dSEric Biggers 
1883f47a03dSEric Biggers #define TESTMGR_POISON_BYTE	0xfe
1893f47a03dSEric Biggers #define TESTMGR_POISON_LEN	16
1903f47a03dSEric Biggers 
1913f47a03dSEric Biggers static inline void testmgr_poison(void *addr, size_t len)
1923f47a03dSEric Biggers {
1933f47a03dSEric Biggers 	memset(addr, TESTMGR_POISON_BYTE, len);
1943f47a03dSEric Biggers }
1953f47a03dSEric Biggers 
1963f47a03dSEric Biggers /* Is the memory region still fully poisoned? */
1973f47a03dSEric Biggers static inline bool testmgr_is_poison(const void *addr, size_t len)
1983f47a03dSEric Biggers {
1993f47a03dSEric Biggers 	return memchr_inv(addr, TESTMGR_POISON_BYTE, len) == NULL;
2003f47a03dSEric Biggers }
2013f47a03dSEric Biggers 
2023f47a03dSEric Biggers /* flush type for hash algorithms */
2033f47a03dSEric Biggers enum flush_type {
2043f47a03dSEric Biggers 	/* merge with update of previous buffer(s) */
2053f47a03dSEric Biggers 	FLUSH_TYPE_NONE = 0,
2063f47a03dSEric Biggers 
2073f47a03dSEric Biggers 	/* update with previous buffer(s) before doing this one */
2083f47a03dSEric Biggers 	FLUSH_TYPE_FLUSH,
2093f47a03dSEric Biggers 
2103f47a03dSEric Biggers 	/* likewise, but also export and re-import the intermediate state */
2113f47a03dSEric Biggers 	FLUSH_TYPE_REIMPORT,
2123f47a03dSEric Biggers };
2133f47a03dSEric Biggers 
2143f47a03dSEric Biggers /* finalization function for hash algorithms */
2153f47a03dSEric Biggers enum finalization_type {
2163f47a03dSEric Biggers 	FINALIZATION_TYPE_FINAL,	/* use final() */
2173f47a03dSEric Biggers 	FINALIZATION_TYPE_FINUP,	/* use finup() */
2183f47a03dSEric Biggers 	FINALIZATION_TYPE_DIGEST,	/* use digest() */
2193f47a03dSEric Biggers };
2203f47a03dSEric Biggers 
2213f47a03dSEric Biggers #define TEST_SG_TOTAL	10000
2223f47a03dSEric Biggers 
2233f47a03dSEric Biggers /**
2243f47a03dSEric Biggers  * struct test_sg_division - description of a scatterlist entry
2253f47a03dSEric Biggers  *
2263f47a03dSEric Biggers  * This struct describes one entry of a scatterlist being constructed to check a
2273f47a03dSEric Biggers  * crypto test vector.
2283f47a03dSEric Biggers  *
2293f47a03dSEric Biggers  * @proportion_of_total: length of this chunk relative to the total length,
2303f47a03dSEric Biggers  *			 given as a proportion out of TEST_SG_TOTAL so that it
2313f47a03dSEric Biggers  *			 scales to fit any test vector
2323f47a03dSEric Biggers  * @offset: byte offset into a 2-page buffer at which this chunk will start
2333f47a03dSEric Biggers  * @offset_relative_to_alignmask: if true, add the algorithm's alignmask to the
2343f47a03dSEric Biggers  *				  @offset
2353f47a03dSEric Biggers  * @flush_type: for hashes, whether an update() should be done now vs.
2363f47a03dSEric Biggers  *		continuing to accumulate data
2373f47a03dSEric Biggers  */
2383f47a03dSEric Biggers struct test_sg_division {
2393f47a03dSEric Biggers 	unsigned int proportion_of_total;
2403f47a03dSEric Biggers 	unsigned int offset;
2413f47a03dSEric Biggers 	bool offset_relative_to_alignmask;
2423f47a03dSEric Biggers 	enum flush_type flush_type;
2433f47a03dSEric Biggers };
2443f47a03dSEric Biggers 
2453f47a03dSEric Biggers /**
2463f47a03dSEric Biggers  * struct testvec_config - configuration for testing a crypto test vector
2473f47a03dSEric Biggers  *
2483f47a03dSEric Biggers  * This struct describes the data layout and other parameters with which each
2493f47a03dSEric Biggers  * crypto test vector can be tested.
2503f47a03dSEric Biggers  *
2513f47a03dSEric Biggers  * @name: name of this config, logged for debugging purposes if a test fails
2523f47a03dSEric Biggers  * @inplace: operate on the data in-place, if applicable for the algorithm type?
2533f47a03dSEric Biggers  * @req_flags: extra request_flags, e.g. CRYPTO_TFM_REQ_MAY_SLEEP
2543f47a03dSEric Biggers  * @src_divs: description of how to arrange the source scatterlist
2553f47a03dSEric Biggers  * @dst_divs: description of how to arrange the dst scatterlist, if applicable
2563f47a03dSEric Biggers  *	      for the algorithm type.  Defaults to @src_divs if unset.
2573f47a03dSEric Biggers  * @iv_offset: misalignment of the IV in the range [0..MAX_ALGAPI_ALIGNMASK+1],
2583f47a03dSEric Biggers  *	       where 0 is aligned to a 2*(MAX_ALGAPI_ALIGNMASK+1) byte boundary
2593f47a03dSEric Biggers  * @iv_offset_relative_to_alignmask: if true, add the algorithm's alignmask to
2603f47a03dSEric Biggers  *				     the @iv_offset
2613f47a03dSEric Biggers  * @finalization_type: what finalization function to use for hashes
2623f47a03dSEric Biggers  */
2633f47a03dSEric Biggers struct testvec_config {
2643f47a03dSEric Biggers 	const char *name;
2653f47a03dSEric Biggers 	bool inplace;
2663f47a03dSEric Biggers 	u32 req_flags;
2673f47a03dSEric Biggers 	struct test_sg_division src_divs[XBUFSIZE];
2683f47a03dSEric Biggers 	struct test_sg_division dst_divs[XBUFSIZE];
2693f47a03dSEric Biggers 	unsigned int iv_offset;
2703f47a03dSEric Biggers 	bool iv_offset_relative_to_alignmask;
2713f47a03dSEric Biggers 	enum finalization_type finalization_type;
2723f47a03dSEric Biggers };
2733f47a03dSEric Biggers 
2743f47a03dSEric Biggers #define TESTVEC_CONFIG_NAMELEN	192
2753f47a03dSEric Biggers 
2763f47a03dSEric Biggers static unsigned int count_test_sg_divisions(const struct test_sg_division *divs)
2773f47a03dSEric Biggers {
2783f47a03dSEric Biggers 	unsigned int remaining = TEST_SG_TOTAL;
2793f47a03dSEric Biggers 	unsigned int ndivs = 0;
2803f47a03dSEric Biggers 
2813f47a03dSEric Biggers 	do {
2823f47a03dSEric Biggers 		remaining -= divs[ndivs++].proportion_of_total;
2833f47a03dSEric Biggers 	} while (remaining);
2843f47a03dSEric Biggers 
2853f47a03dSEric Biggers 	return ndivs;
2863f47a03dSEric Biggers }
2873f47a03dSEric Biggers 
2883f47a03dSEric Biggers static bool valid_sg_divisions(const struct test_sg_division *divs,
2893f47a03dSEric Biggers 			       unsigned int count, bool *any_flushes_ret)
2903f47a03dSEric Biggers {
2913f47a03dSEric Biggers 	unsigned int total = 0;
2923f47a03dSEric Biggers 	unsigned int i;
2933f47a03dSEric Biggers 
2943f47a03dSEric Biggers 	for (i = 0; i < count && total != TEST_SG_TOTAL; i++) {
2953f47a03dSEric Biggers 		if (divs[i].proportion_of_total <= 0 ||
2963f47a03dSEric Biggers 		    divs[i].proportion_of_total > TEST_SG_TOTAL - total)
2973f47a03dSEric Biggers 			return false;
2983f47a03dSEric Biggers 		total += divs[i].proportion_of_total;
2993f47a03dSEric Biggers 		if (divs[i].flush_type != FLUSH_TYPE_NONE)
3003f47a03dSEric Biggers 			*any_flushes_ret = true;
3013f47a03dSEric Biggers 	}
3023f47a03dSEric Biggers 	return total == TEST_SG_TOTAL &&
3033f47a03dSEric Biggers 		memchr_inv(&divs[i], 0, (count - i) * sizeof(divs[0])) == NULL;
3043f47a03dSEric Biggers }
3053f47a03dSEric Biggers 
3063f47a03dSEric Biggers /*
3073f47a03dSEric Biggers  * Check whether the given testvec_config is valid.  This isn't strictly needed
3083f47a03dSEric Biggers  * since every testvec_config should be valid, but check anyway so that people
3093f47a03dSEric Biggers  * don't unknowingly add broken configs that don't do what they wanted.
3103f47a03dSEric Biggers  */
3113f47a03dSEric Biggers static bool valid_testvec_config(const struct testvec_config *cfg)
3123f47a03dSEric Biggers {
3133f47a03dSEric Biggers 	bool any_flushes = false;
3143f47a03dSEric Biggers 
3153f47a03dSEric Biggers 	if (cfg->name == NULL)
3163f47a03dSEric Biggers 		return false;
3173f47a03dSEric Biggers 
3183f47a03dSEric Biggers 	if (!valid_sg_divisions(cfg->src_divs, ARRAY_SIZE(cfg->src_divs),
3193f47a03dSEric Biggers 				&any_flushes))
3203f47a03dSEric Biggers 		return false;
3213f47a03dSEric Biggers 
3223f47a03dSEric Biggers 	if (cfg->dst_divs[0].proportion_of_total) {
3233f47a03dSEric Biggers 		if (!valid_sg_divisions(cfg->dst_divs,
3243f47a03dSEric Biggers 					ARRAY_SIZE(cfg->dst_divs),
3253f47a03dSEric Biggers 					&any_flushes))
3263f47a03dSEric Biggers 			return false;
3273f47a03dSEric Biggers 	} else {
3283f47a03dSEric Biggers 		if (memchr_inv(cfg->dst_divs, 0, sizeof(cfg->dst_divs)))
3293f47a03dSEric Biggers 			return false;
3303f47a03dSEric Biggers 		/* defaults to dst_divs=src_divs */
3313f47a03dSEric Biggers 	}
3323f47a03dSEric Biggers 
3333f47a03dSEric Biggers 	if (cfg->iv_offset +
3343f47a03dSEric Biggers 	    (cfg->iv_offset_relative_to_alignmask ? MAX_ALGAPI_ALIGNMASK : 0) >
3353f47a03dSEric Biggers 	    MAX_ALGAPI_ALIGNMASK + 1)
3363f47a03dSEric Biggers 		return false;
3373f47a03dSEric Biggers 
3383f47a03dSEric Biggers 	if (any_flushes && cfg->finalization_type == FINALIZATION_TYPE_DIGEST)
3393f47a03dSEric Biggers 		return false;
3403f47a03dSEric Biggers 
3413f47a03dSEric Biggers 	return true;
3423f47a03dSEric Biggers }
3433f47a03dSEric Biggers 
3443f47a03dSEric Biggers struct test_sglist {
3453f47a03dSEric Biggers 	char *bufs[XBUFSIZE];
3463f47a03dSEric Biggers 	struct scatterlist sgl[XBUFSIZE];
3473f47a03dSEric Biggers 	struct scatterlist sgl_saved[XBUFSIZE];
3483f47a03dSEric Biggers 	struct scatterlist *sgl_ptr;
3493f47a03dSEric Biggers 	unsigned int nents;
3503f47a03dSEric Biggers };
3513f47a03dSEric Biggers 
3523f47a03dSEric Biggers static int init_test_sglist(struct test_sglist *tsgl)
3533f47a03dSEric Biggers {
3543f47a03dSEric Biggers 	return __testmgr_alloc_buf(tsgl->bufs, 1 /* two pages per buffer */);
3553f47a03dSEric Biggers }
3563f47a03dSEric Biggers 
3573f47a03dSEric Biggers static void destroy_test_sglist(struct test_sglist *tsgl)
3583f47a03dSEric Biggers {
3593f47a03dSEric Biggers 	return __testmgr_free_buf(tsgl->bufs, 1 /* two pages per buffer */);
3603f47a03dSEric Biggers }
3613f47a03dSEric Biggers 
3623f47a03dSEric Biggers /**
3633f47a03dSEric Biggers  * build_test_sglist() - build a scatterlist for a crypto test
3643f47a03dSEric Biggers  *
3653f47a03dSEric Biggers  * @tsgl: the scatterlist to build.  @tsgl->bufs[] contains an array of 2-page
3663f47a03dSEric Biggers  *	  buffers which the scatterlist @tsgl->sgl[] will be made to point into.
3673f47a03dSEric Biggers  * @divs: the layout specification on which the scatterlist will be based
3683f47a03dSEric Biggers  * @alignmask: the algorithm's alignmask
3693f47a03dSEric Biggers  * @total_len: the total length of the scatterlist to build in bytes
3703f47a03dSEric Biggers  * @data: if non-NULL, the buffers will be filled with this data until it ends.
3713f47a03dSEric Biggers  *	  Otherwise the buffers will be poisoned.  In both cases, some bytes
3723f47a03dSEric Biggers  *	  past the end of each buffer will be poisoned to help detect overruns.
3733f47a03dSEric Biggers  * @out_divs: if non-NULL, the test_sg_division to which each scatterlist entry
3743f47a03dSEric Biggers  *	      corresponds will be returned here.  This will match @divs except
3753f47a03dSEric Biggers  *	      that divisions resolving to a length of 0 are omitted as they are
3763f47a03dSEric Biggers  *	      not included in the scatterlist.
3773f47a03dSEric Biggers  *
3783f47a03dSEric Biggers  * Return: 0 or a -errno value
3793f47a03dSEric Biggers  */
3803f47a03dSEric Biggers static int build_test_sglist(struct test_sglist *tsgl,
3813f47a03dSEric Biggers 			     const struct test_sg_division *divs,
3823f47a03dSEric Biggers 			     const unsigned int alignmask,
3833f47a03dSEric Biggers 			     const unsigned int total_len,
3843f47a03dSEric Biggers 			     struct iov_iter *data,
3853f47a03dSEric Biggers 			     const struct test_sg_division *out_divs[XBUFSIZE])
3863f47a03dSEric Biggers {
3873f47a03dSEric Biggers 	struct {
3883f47a03dSEric Biggers 		const struct test_sg_division *div;
3893f47a03dSEric Biggers 		size_t length;
3903f47a03dSEric Biggers 	} partitions[XBUFSIZE];
3913f47a03dSEric Biggers 	const unsigned int ndivs = count_test_sg_divisions(divs);
3923f47a03dSEric Biggers 	unsigned int len_remaining = total_len;
3933f47a03dSEric Biggers 	unsigned int i;
3943f47a03dSEric Biggers 
3953f47a03dSEric Biggers 	BUILD_BUG_ON(ARRAY_SIZE(partitions) != ARRAY_SIZE(tsgl->sgl));
3963f47a03dSEric Biggers 	if (WARN_ON(ndivs > ARRAY_SIZE(partitions)))
3973f47a03dSEric Biggers 		return -EINVAL;
3983f47a03dSEric Biggers 
3993f47a03dSEric Biggers 	/* Calculate the (div, length) pairs */
4003f47a03dSEric Biggers 	tsgl->nents = 0;
4013f47a03dSEric Biggers 	for (i = 0; i < ndivs; i++) {
4023f47a03dSEric Biggers 		unsigned int len_this_sg =
4033f47a03dSEric Biggers 			min(len_remaining,
4043f47a03dSEric Biggers 			    (total_len * divs[i].proportion_of_total +
4053f47a03dSEric Biggers 			     TEST_SG_TOTAL / 2) / TEST_SG_TOTAL);
4063f47a03dSEric Biggers 
4073f47a03dSEric Biggers 		if (len_this_sg != 0) {
4083f47a03dSEric Biggers 			partitions[tsgl->nents].div = &divs[i];
4093f47a03dSEric Biggers 			partitions[tsgl->nents].length = len_this_sg;
4103f47a03dSEric Biggers 			tsgl->nents++;
4113f47a03dSEric Biggers 			len_remaining -= len_this_sg;
4123f47a03dSEric Biggers 		}
4133f47a03dSEric Biggers 	}
4143f47a03dSEric Biggers 	if (tsgl->nents == 0) {
4153f47a03dSEric Biggers 		partitions[tsgl->nents].div = &divs[0];
4163f47a03dSEric Biggers 		partitions[tsgl->nents].length = 0;
4173f47a03dSEric Biggers 		tsgl->nents++;
4183f47a03dSEric Biggers 	}
4193f47a03dSEric Biggers 	partitions[tsgl->nents - 1].length += len_remaining;
4203f47a03dSEric Biggers 
4213f47a03dSEric Biggers 	/* Set up the sgl entries and fill the data or poison */
4223f47a03dSEric Biggers 	sg_init_table(tsgl->sgl, tsgl->nents);
4233f47a03dSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
4243f47a03dSEric Biggers 		unsigned int offset = partitions[i].div->offset;
4253f47a03dSEric Biggers 		void *addr;
4263f47a03dSEric Biggers 
4273f47a03dSEric Biggers 		if (partitions[i].div->offset_relative_to_alignmask)
4283f47a03dSEric Biggers 			offset += alignmask;
4293f47a03dSEric Biggers 
4303f47a03dSEric Biggers 		while (offset + partitions[i].length + TESTMGR_POISON_LEN >
4313f47a03dSEric Biggers 		       2 * PAGE_SIZE) {
4323f47a03dSEric Biggers 			if (WARN_ON(offset <= 0))
4333f47a03dSEric Biggers 				return -EINVAL;
4343f47a03dSEric Biggers 			offset /= 2;
4353f47a03dSEric Biggers 		}
4363f47a03dSEric Biggers 
4373f47a03dSEric Biggers 		addr = &tsgl->bufs[i][offset];
4383f47a03dSEric Biggers 		sg_set_buf(&tsgl->sgl[i], addr, partitions[i].length);
4393f47a03dSEric Biggers 
4403f47a03dSEric Biggers 		if (out_divs)
4413f47a03dSEric Biggers 			out_divs[i] = partitions[i].div;
4423f47a03dSEric Biggers 
4433f47a03dSEric Biggers 		if (data) {
4443f47a03dSEric Biggers 			size_t copy_len, copied;
4453f47a03dSEric Biggers 
4463f47a03dSEric Biggers 			copy_len = min(partitions[i].length, data->count);
4473f47a03dSEric Biggers 			copied = copy_from_iter(addr, copy_len, data);
4483f47a03dSEric Biggers 			if (WARN_ON(copied != copy_len))
4493f47a03dSEric Biggers 				return -EINVAL;
4503f47a03dSEric Biggers 			testmgr_poison(addr + copy_len, partitions[i].length +
4513f47a03dSEric Biggers 				       TESTMGR_POISON_LEN - copy_len);
4523f47a03dSEric Biggers 		} else {
4533f47a03dSEric Biggers 			testmgr_poison(addr, partitions[i].length +
4543f47a03dSEric Biggers 				       TESTMGR_POISON_LEN);
4553f47a03dSEric Biggers 		}
4563f47a03dSEric Biggers 	}
4573f47a03dSEric Biggers 
4583f47a03dSEric Biggers 	sg_mark_end(&tsgl->sgl[tsgl->nents - 1]);
4593f47a03dSEric Biggers 	tsgl->sgl_ptr = tsgl->sgl;
4603f47a03dSEric Biggers 	memcpy(tsgl->sgl_saved, tsgl->sgl, tsgl->nents * sizeof(tsgl->sgl[0]));
4613f47a03dSEric Biggers 	return 0;
4623f47a03dSEric Biggers }
4633f47a03dSEric Biggers 
4643f47a03dSEric Biggers /*
4653f47a03dSEric Biggers  * Verify that a scatterlist crypto operation produced the correct output.
4663f47a03dSEric Biggers  *
4673f47a03dSEric Biggers  * @tsgl: scatterlist containing the actual output
4683f47a03dSEric Biggers  * @expected_output: buffer containing the expected output
4693f47a03dSEric Biggers  * @len_to_check: length of @expected_output in bytes
4703f47a03dSEric Biggers  * @unchecked_prefix_len: number of ignored bytes in @tsgl prior to real result
4713f47a03dSEric Biggers  * @check_poison: verify that the poison bytes after each chunk are intact?
4723f47a03dSEric Biggers  *
4733f47a03dSEric Biggers  * Return: 0 if correct, -EINVAL if incorrect, -EOVERFLOW if buffer overrun.
4743f47a03dSEric Biggers  */
4753f47a03dSEric Biggers static int verify_correct_output(const struct test_sglist *tsgl,
4763f47a03dSEric Biggers 				 const char *expected_output,
4773f47a03dSEric Biggers 				 unsigned int len_to_check,
4783f47a03dSEric Biggers 				 unsigned int unchecked_prefix_len,
4793f47a03dSEric Biggers 				 bool check_poison)
4803f47a03dSEric Biggers {
4813f47a03dSEric Biggers 	unsigned int i;
4823f47a03dSEric Biggers 
4833f47a03dSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
4843f47a03dSEric Biggers 		struct scatterlist *sg = &tsgl->sgl_ptr[i];
4853f47a03dSEric Biggers 		unsigned int len = sg->length;
4863f47a03dSEric Biggers 		unsigned int offset = sg->offset;
4873f47a03dSEric Biggers 		const char *actual_output;
4883f47a03dSEric Biggers 
4893f47a03dSEric Biggers 		if (unchecked_prefix_len) {
4903f47a03dSEric Biggers 			if (unchecked_prefix_len >= len) {
4913f47a03dSEric Biggers 				unchecked_prefix_len -= len;
4923f47a03dSEric Biggers 				continue;
4933f47a03dSEric Biggers 			}
4943f47a03dSEric Biggers 			offset += unchecked_prefix_len;
4953f47a03dSEric Biggers 			len -= unchecked_prefix_len;
4963f47a03dSEric Biggers 			unchecked_prefix_len = 0;
4973f47a03dSEric Biggers 		}
4983f47a03dSEric Biggers 		len = min(len, len_to_check);
4993f47a03dSEric Biggers 		actual_output = page_address(sg_page(sg)) + offset;
5003f47a03dSEric Biggers 		if (memcmp(expected_output, actual_output, len) != 0)
5013f47a03dSEric Biggers 			return -EINVAL;
5023f47a03dSEric Biggers 		if (check_poison &&
5033f47a03dSEric Biggers 		    !testmgr_is_poison(actual_output + len, TESTMGR_POISON_LEN))
5043f47a03dSEric Biggers 			return -EOVERFLOW;
5053f47a03dSEric Biggers 		len_to_check -= len;
5063f47a03dSEric Biggers 		expected_output += len;
5073f47a03dSEric Biggers 	}
5083f47a03dSEric Biggers 	if (WARN_ON(len_to_check != 0))
5093f47a03dSEric Biggers 		return -EINVAL;
5103f47a03dSEric Biggers 	return 0;
5113f47a03dSEric Biggers }
5123f47a03dSEric Biggers 
5133f47a03dSEric Biggers static bool is_test_sglist_corrupted(const struct test_sglist *tsgl)
5143f47a03dSEric Biggers {
5153f47a03dSEric Biggers 	unsigned int i;
5163f47a03dSEric Biggers 
5173f47a03dSEric Biggers 	for (i = 0; i < tsgl->nents; i++) {
5183f47a03dSEric Biggers 		if (tsgl->sgl[i].page_link != tsgl->sgl_saved[i].page_link)
5193f47a03dSEric Biggers 			return true;
5203f47a03dSEric Biggers 		if (tsgl->sgl[i].offset != tsgl->sgl_saved[i].offset)
5213f47a03dSEric Biggers 			return true;
5223f47a03dSEric Biggers 		if (tsgl->sgl[i].length != tsgl->sgl_saved[i].length)
5233f47a03dSEric Biggers 			return true;
5243f47a03dSEric Biggers 	}
5253f47a03dSEric Biggers 	return false;
5263f47a03dSEric Biggers }
5273f47a03dSEric Biggers 
5283f47a03dSEric Biggers struct cipher_test_sglists {
5293f47a03dSEric Biggers 	struct test_sglist src;
5303f47a03dSEric Biggers 	struct test_sglist dst;
5313f47a03dSEric Biggers };
5323f47a03dSEric Biggers 
5333f47a03dSEric Biggers static struct cipher_test_sglists *alloc_cipher_test_sglists(void)
5343f47a03dSEric Biggers {
5353f47a03dSEric Biggers 	struct cipher_test_sglists *tsgls;
5363f47a03dSEric Biggers 
5373f47a03dSEric Biggers 	tsgls = kmalloc(sizeof(*tsgls), GFP_KERNEL);
5383f47a03dSEric Biggers 	if (!tsgls)
5393f47a03dSEric Biggers 		return NULL;
5403f47a03dSEric Biggers 
5413f47a03dSEric Biggers 	if (init_test_sglist(&tsgls->src) != 0)
5423f47a03dSEric Biggers 		goto fail_kfree;
5433f47a03dSEric Biggers 	if (init_test_sglist(&tsgls->dst) != 0)
5443f47a03dSEric Biggers 		goto fail_destroy_src;
5453f47a03dSEric Biggers 
5463f47a03dSEric Biggers 	return tsgls;
5473f47a03dSEric Biggers 
5483f47a03dSEric Biggers fail_destroy_src:
5493f47a03dSEric Biggers 	destroy_test_sglist(&tsgls->src);
5503f47a03dSEric Biggers fail_kfree:
5513f47a03dSEric Biggers 	kfree(tsgls);
5523f47a03dSEric Biggers 	return NULL;
5533f47a03dSEric Biggers }
5543f47a03dSEric Biggers 
5553f47a03dSEric Biggers static void free_cipher_test_sglists(struct cipher_test_sglists *tsgls)
5563f47a03dSEric Biggers {
5573f47a03dSEric Biggers 	if (tsgls) {
5583f47a03dSEric Biggers 		destroy_test_sglist(&tsgls->src);
5593f47a03dSEric Biggers 		destroy_test_sglist(&tsgls->dst);
5603f47a03dSEric Biggers 		kfree(tsgls);
5613f47a03dSEric Biggers 	}
5623f47a03dSEric Biggers }
5633f47a03dSEric Biggers 
5643f47a03dSEric Biggers /* Build the src and dst scatterlists for an skcipher or AEAD test */
5653f47a03dSEric Biggers static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls,
5663f47a03dSEric Biggers 				     const struct testvec_config *cfg,
5673f47a03dSEric Biggers 				     unsigned int alignmask,
5683f47a03dSEric Biggers 				     unsigned int src_total_len,
5693f47a03dSEric Biggers 				     unsigned int dst_total_len,
5703f47a03dSEric Biggers 				     const struct kvec *inputs,
5713f47a03dSEric Biggers 				     unsigned int nr_inputs)
5723f47a03dSEric Biggers {
5733f47a03dSEric Biggers 	struct iov_iter input;
5743f47a03dSEric Biggers 	int err;
5753f47a03dSEric Biggers 
5763f47a03dSEric Biggers 	iov_iter_kvec(&input, WRITE, inputs, nr_inputs, src_total_len);
5773f47a03dSEric Biggers 	err = build_test_sglist(&tsgls->src, cfg->src_divs, alignmask,
5783f47a03dSEric Biggers 				cfg->inplace ?
5793f47a03dSEric Biggers 					max(dst_total_len, src_total_len) :
5803f47a03dSEric Biggers 					src_total_len,
5813f47a03dSEric Biggers 				&input, NULL);
5823f47a03dSEric Biggers 	if (err)
5833f47a03dSEric Biggers 		return err;
5843f47a03dSEric Biggers 
5853f47a03dSEric Biggers 	if (cfg->inplace) {
5863f47a03dSEric Biggers 		tsgls->dst.sgl_ptr = tsgls->src.sgl;
5873f47a03dSEric Biggers 		tsgls->dst.nents = tsgls->src.nents;
5883f47a03dSEric Biggers 		return 0;
5893f47a03dSEric Biggers 	}
5903f47a03dSEric Biggers 	return build_test_sglist(&tsgls->dst,
5913f47a03dSEric Biggers 				 cfg->dst_divs[0].proportion_of_total ?
5923f47a03dSEric Biggers 					cfg->dst_divs : cfg->src_divs,
5933f47a03dSEric Biggers 				 alignmask, dst_total_len, NULL, NULL);
594f8b0d4d0SHerbert Xu }
595f8b0d4d0SHerbert Xu 
596466d7b9fSKamil Konieczny static int ahash_guard_result(char *result, char c, int size)
597466d7b9fSKamil Konieczny {
598466d7b9fSKamil Konieczny 	int i;
599466d7b9fSKamil Konieczny 
600466d7b9fSKamil Konieczny 	for (i = 0; i < size; i++) {
601466d7b9fSKamil Konieczny 		if (result[i] != c)
602466d7b9fSKamil Konieczny 			return -EINVAL;
603466d7b9fSKamil Konieczny 	}
604466d7b9fSKamil Konieczny 
605466d7b9fSKamil Konieczny 	return 0;
606466d7b9fSKamil Konieczny }
607466d7b9fSKamil Konieczny 
608018ba95cSWang, Rui Y static int ahash_partial_update(struct ahash_request **preq,
609b13b1e0cSEric Biggers 	struct crypto_ahash *tfm, const struct hash_testvec *template,
610018ba95cSWang, Rui Y 	void *hash_buff, int k, int temp, struct scatterlist *sg,
6117f397136SGilad Ben-Yossef 	const char *algo, char *result, struct crypto_wait *wait)
612018ba95cSWang, Rui Y {
613018ba95cSWang, Rui Y 	char *state;
614018ba95cSWang, Rui Y 	struct ahash_request *req;
615018ba95cSWang, Rui Y 	int statesize, ret = -EINVAL;
616da1729ceSJoey Pabalinas 	static const unsigned char guard[] = { 0x00, 0xba, 0xad, 0x00 };
617466d7b9fSKamil Konieczny 	int digestsize = crypto_ahash_digestsize(tfm);
618018ba95cSWang, Rui Y 
619018ba95cSWang, Rui Y 	req = *preq;
620018ba95cSWang, Rui Y 	statesize = crypto_ahash_statesize(
621018ba95cSWang, Rui Y 			crypto_ahash_reqtfm(req));
6227bcb87bcSJan Stancek 	state = kmalloc(statesize + sizeof(guard), GFP_KERNEL);
623018ba95cSWang, Rui Y 	if (!state) {
624cf3f9609SGilad Ben-Yossef 		pr_err("alg: hash: Failed to alloc state for %s\n", algo);
625018ba95cSWang, Rui Y 		goto out_nostate;
626018ba95cSWang, Rui Y 	}
6277bcb87bcSJan Stancek 	memcpy(state + statesize, guard, sizeof(guard));
628466d7b9fSKamil Konieczny 	memset(result, 1, digestsize);
629018ba95cSWang, Rui Y 	ret = crypto_ahash_export(req, state);
6307bcb87bcSJan Stancek 	WARN_ON(memcmp(state + statesize, guard, sizeof(guard)));
631018ba95cSWang, Rui Y 	if (ret) {
632cf3f9609SGilad Ben-Yossef 		pr_err("alg: hash: Failed to export() for %s\n", algo);
633018ba95cSWang, Rui Y 		goto out;
634018ba95cSWang, Rui Y 	}
635466d7b9fSKamil Konieczny 	ret = ahash_guard_result(result, 1, digestsize);
636466d7b9fSKamil Konieczny 	if (ret) {
637466d7b9fSKamil Konieczny 		pr_err("alg: hash: Failed, export used req->result for %s\n",
638466d7b9fSKamil Konieczny 		       algo);
639466d7b9fSKamil Konieczny 		goto out;
640466d7b9fSKamil Konieczny 	}
641018ba95cSWang, Rui Y 	ahash_request_free(req);
642018ba95cSWang, Rui Y 	req = ahash_request_alloc(tfm, GFP_KERNEL);
643018ba95cSWang, Rui Y 	if (!req) {
644018ba95cSWang, Rui Y 		pr_err("alg: hash: Failed to alloc request for %s\n", algo);
645018ba95cSWang, Rui Y 		goto out_noreq;
646018ba95cSWang, Rui Y 	}
647018ba95cSWang, Rui Y 	ahash_request_set_callback(req,
648018ba95cSWang, Rui Y 		CRYPTO_TFM_REQ_MAY_BACKLOG,
6497f397136SGilad Ben-Yossef 		crypto_req_done, wait);
650018ba95cSWang, Rui Y 
651018ba95cSWang, Rui Y 	memcpy(hash_buff, template->plaintext + temp,
652018ba95cSWang, Rui Y 		template->tap[k]);
653018ba95cSWang, Rui Y 	sg_init_one(&sg[0], hash_buff, template->tap[k]);
654018ba95cSWang, Rui Y 	ahash_request_set_crypt(req, sg, result, template->tap[k]);
655018ba95cSWang, Rui Y 	ret = crypto_ahash_import(req, state);
656018ba95cSWang, Rui Y 	if (ret) {
657018ba95cSWang, Rui Y 		pr_err("alg: hash: Failed to import() for %s\n", algo);
658018ba95cSWang, Rui Y 		goto out;
659018ba95cSWang, Rui Y 	}
660466d7b9fSKamil Konieczny 	ret = ahash_guard_result(result, 1, digestsize);
661466d7b9fSKamil Konieczny 	if (ret) {
662466d7b9fSKamil Konieczny 		pr_err("alg: hash: Failed, import used req->result for %s\n",
663466d7b9fSKamil Konieczny 		       algo);
664466d7b9fSKamil Konieczny 		goto out;
665466d7b9fSKamil Konieczny 	}
6667f397136SGilad Ben-Yossef 	ret = crypto_wait_req(crypto_ahash_update(req), wait);
667018ba95cSWang, Rui Y 	if (ret)
668018ba95cSWang, Rui Y 		goto out;
669018ba95cSWang, Rui Y 	*preq = req;
670018ba95cSWang, Rui Y 	ret = 0;
671018ba95cSWang, Rui Y 	goto out_noreq;
672018ba95cSWang, Rui Y out:
673018ba95cSWang, Rui Y 	ahash_request_free(req);
674018ba95cSWang, Rui Y out_noreq:
675018ba95cSWang, Rui Y 	kfree(state);
676018ba95cSWang, Rui Y out_nostate:
677018ba95cSWang, Rui Y 	return ret;
678018ba95cSWang, Rui Y }
679018ba95cSWang, Rui Y 
68076715095SGilad Ben-Yossef enum hash_test {
68176715095SGilad Ben-Yossef 	HASH_TEST_DIGEST,
68276715095SGilad Ben-Yossef 	HASH_TEST_FINAL,
68376715095SGilad Ben-Yossef 	HASH_TEST_FINUP
68476715095SGilad Ben-Yossef };
68576715095SGilad Ben-Yossef 
686b13b1e0cSEric Biggers static int __test_hash(struct crypto_ahash *tfm,
687b13b1e0cSEric Biggers 		       const struct hash_testvec *template, unsigned int tcount,
68876715095SGilad Ben-Yossef 		       enum hash_test test_type, const int align_offset)
689da7f033dSHerbert Xu {
690da7f033dSHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm));
691e93acd6fSAndrew Lutomirski 	size_t digest_size = crypto_ahash_digestsize(tfm);
692da7f033dSHerbert Xu 	unsigned int i, j, k, temp;
693da7f033dSHerbert Xu 	struct scatterlist sg[8];
69429b77e5dSHoria Geanta 	char *result;
69529b77e5dSHoria Geanta 	char *key;
696da7f033dSHerbert Xu 	struct ahash_request *req;
6977f397136SGilad Ben-Yossef 	struct crypto_wait wait;
698da7f033dSHerbert Xu 	void *hash_buff;
699f8b0d4d0SHerbert Xu 	char *xbuf[XBUFSIZE];
700f8b0d4d0SHerbert Xu 	int ret = -ENOMEM;
701f8b0d4d0SHerbert Xu 
702e93acd6fSAndrew Lutomirski 	result = kmalloc(digest_size, GFP_KERNEL);
70329b77e5dSHoria Geanta 	if (!result)
70429b77e5dSHoria Geanta 		return ret;
70529b77e5dSHoria Geanta 	key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
70629b77e5dSHoria Geanta 	if (!key)
70729b77e5dSHoria Geanta 		goto out_nobuf;
708f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(xbuf))
709f8b0d4d0SHerbert Xu 		goto out_nobuf;
710da7f033dSHerbert Xu 
7117f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
712da7f033dSHerbert Xu 
713da7f033dSHerbert Xu 	req = ahash_request_alloc(tfm, GFP_KERNEL);
714da7f033dSHerbert Xu 	if (!req) {
715da7f033dSHerbert Xu 		printk(KERN_ERR "alg: hash: Failed to allocate request for "
716da7f033dSHerbert Xu 		       "%s\n", algo);
717da7f033dSHerbert Xu 		goto out_noreq;
718da7f033dSHerbert Xu 	}
719da7f033dSHerbert Xu 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
7207f397136SGilad Ben-Yossef 				   crypto_req_done, &wait);
721da7f033dSHerbert Xu 
722a0cfae59SHerbert Xu 	j = 0;
723da7f033dSHerbert Xu 	for (i = 0; i < tcount; i++) {
724a0cfae59SHerbert Xu 		if (template[i].np)
725a0cfae59SHerbert Xu 			continue;
726a0cfae59SHerbert Xu 
727da5ffe11SJussi Kivilinna 		ret = -EINVAL;
728da5ffe11SJussi Kivilinna 		if (WARN_ON(align_offset + template[i].psize > PAGE_SIZE))
729da5ffe11SJussi Kivilinna 			goto out;
730da5ffe11SJussi Kivilinna 
731a0cfae59SHerbert Xu 		j++;
732e93acd6fSAndrew Lutomirski 		memset(result, 0, digest_size);
733da7f033dSHerbert Xu 
734da7f033dSHerbert Xu 		hash_buff = xbuf[0];
735da5ffe11SJussi Kivilinna 		hash_buff += align_offset;
736da7f033dSHerbert Xu 
737da7f033dSHerbert Xu 		memcpy(hash_buff, template[i].plaintext, template[i].psize);
738da7f033dSHerbert Xu 		sg_init_one(&sg[0], hash_buff, template[i].psize);
739da7f033dSHerbert Xu 
740da7f033dSHerbert Xu 		if (template[i].ksize) {
741da7f033dSHerbert Xu 			crypto_ahash_clear_flags(tfm, ~0);
74229b77e5dSHoria Geanta 			if (template[i].ksize > MAX_KEYLEN) {
74329b77e5dSHoria Geanta 				pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
74429b77e5dSHoria Geanta 				       j, algo, template[i].ksize, MAX_KEYLEN);
74529b77e5dSHoria Geanta 				ret = -EINVAL;
74629b77e5dSHoria Geanta 				goto out;
74729b77e5dSHoria Geanta 			}
74829b77e5dSHoria Geanta 			memcpy(key, template[i].key, template[i].ksize);
74929b77e5dSHoria Geanta 			ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
750da7f033dSHerbert Xu 			if (ret) {
751da7f033dSHerbert Xu 				printk(KERN_ERR "alg: hash: setkey failed on "
752a0cfae59SHerbert Xu 				       "test %d for %s: ret=%d\n", j, algo,
753da7f033dSHerbert Xu 				       -ret);
754da7f033dSHerbert Xu 				goto out;
755da7f033dSHerbert Xu 			}
756da7f033dSHerbert Xu 		}
757da7f033dSHerbert Xu 
758da7f033dSHerbert Xu 		ahash_request_set_crypt(req, sg, result, template[i].psize);
75976715095SGilad Ben-Yossef 		switch (test_type) {
76076715095SGilad Ben-Yossef 		case HASH_TEST_DIGEST:
7617f397136SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
762a8f1a052SDavid S. Miller 			if (ret) {
763a8f1a052SDavid S. Miller 				pr_err("alg: hash: digest failed on test %d "
764a0cfae59SHerbert Xu 				       "for %s: ret=%d\n", j, algo, -ret);
765da7f033dSHerbert Xu 				goto out;
766da7f033dSHerbert Xu 			}
76776715095SGilad Ben-Yossef 			break;
76876715095SGilad Ben-Yossef 
76976715095SGilad Ben-Yossef 		case HASH_TEST_FINAL:
770466d7b9fSKamil Konieczny 			memset(result, 1, digest_size);
7717f397136SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_init(req), &wait);
772a8f1a052SDavid S. Miller 			if (ret) {
773cf3f9609SGilad Ben-Yossef 				pr_err("alg: hash: init failed on test %d "
774a8f1a052SDavid S. Miller 				       "for %s: ret=%d\n", j, algo, -ret);
775a8f1a052SDavid S. Miller 				goto out;
776a8f1a052SDavid S. Miller 			}
777466d7b9fSKamil Konieczny 			ret = ahash_guard_result(result, 1, digest_size);
778466d7b9fSKamil Konieczny 			if (ret) {
779466d7b9fSKamil Konieczny 				pr_err("alg: hash: init failed on test %d "
780466d7b9fSKamil Konieczny 				       "for %s: used req->result\n", j, algo);
781466d7b9fSKamil Konieczny 				goto out;
782466d7b9fSKamil Konieczny 			}
7837f397136SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_update(req), &wait);
784a8f1a052SDavid S. Miller 			if (ret) {
785cf3f9609SGilad Ben-Yossef 				pr_err("alg: hash: update failed on test %d "
786a8f1a052SDavid S. Miller 				       "for %s: ret=%d\n", j, algo, -ret);
787a8f1a052SDavid S. Miller 				goto out;
788a8f1a052SDavid S. Miller 			}
789466d7b9fSKamil Konieczny 			ret = ahash_guard_result(result, 1, digest_size);
790466d7b9fSKamil Konieczny 			if (ret) {
791466d7b9fSKamil Konieczny 				pr_err("alg: hash: update failed on test %d "
792466d7b9fSKamil Konieczny 				       "for %s: used req->result\n", j, algo);
793466d7b9fSKamil Konieczny 				goto out;
794466d7b9fSKamil Konieczny 			}
7957f397136SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_final(req), &wait);
796a8f1a052SDavid S. Miller 			if (ret) {
797cf3f9609SGilad Ben-Yossef 				pr_err("alg: hash: final failed on test %d "
798a8f1a052SDavid S. Miller 				       "for %s: ret=%d\n", j, algo, -ret);
799a8f1a052SDavid S. Miller 				goto out;
800a8f1a052SDavid S. Miller 			}
80176715095SGilad Ben-Yossef 			break;
80276715095SGilad Ben-Yossef 
80376715095SGilad Ben-Yossef 		case HASH_TEST_FINUP:
80476715095SGilad Ben-Yossef 			memset(result, 1, digest_size);
80576715095SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_init(req), &wait);
80676715095SGilad Ben-Yossef 			if (ret) {
80776715095SGilad Ben-Yossef 				pr_err("alg: hash: init failed on test %d "
80876715095SGilad Ben-Yossef 				       "for %s: ret=%d\n", j, algo, -ret);
80976715095SGilad Ben-Yossef 				goto out;
81076715095SGilad Ben-Yossef 			}
81176715095SGilad Ben-Yossef 			ret = ahash_guard_result(result, 1, digest_size);
81276715095SGilad Ben-Yossef 			if (ret) {
81376715095SGilad Ben-Yossef 				pr_err("alg: hash: init failed on test %d "
81476715095SGilad Ben-Yossef 				       "for %s: used req->result\n", j, algo);
81576715095SGilad Ben-Yossef 				goto out;
81676715095SGilad Ben-Yossef 			}
81776715095SGilad Ben-Yossef 			ret = crypto_wait_req(crypto_ahash_finup(req), &wait);
81876715095SGilad Ben-Yossef 			if (ret) {
81976715095SGilad Ben-Yossef 				pr_err("alg: hash: final failed on test %d "
82076715095SGilad Ben-Yossef 				       "for %s: ret=%d\n", j, algo, -ret);
82176715095SGilad Ben-Yossef 				goto out;
82276715095SGilad Ben-Yossef 			}
82376715095SGilad Ben-Yossef 			break;
824a8f1a052SDavid S. Miller 		}
825da7f033dSHerbert Xu 
826da7f033dSHerbert Xu 		if (memcmp(result, template[i].digest,
827da7f033dSHerbert Xu 			   crypto_ahash_digestsize(tfm))) {
828da7f033dSHerbert Xu 			printk(KERN_ERR "alg: hash: Test %d failed for %s\n",
829a0cfae59SHerbert Xu 			       j, algo);
830da7f033dSHerbert Xu 			hexdump(result, crypto_ahash_digestsize(tfm));
831da7f033dSHerbert Xu 			ret = -EINVAL;
832da7f033dSHerbert Xu 			goto out;
833da7f033dSHerbert Xu 		}
834da7f033dSHerbert Xu 	}
835da7f033dSHerbert Xu 
83676715095SGilad Ben-Yossef 	if (test_type)
83776715095SGilad Ben-Yossef 		goto out;
83876715095SGilad Ben-Yossef 
839da7f033dSHerbert Xu 	j = 0;
840da7f033dSHerbert Xu 	for (i = 0; i < tcount; i++) {
841da5ffe11SJussi Kivilinna 		/* alignment tests are only done with continuous buffers */
842da5ffe11SJussi Kivilinna 		if (align_offset != 0)
843da5ffe11SJussi Kivilinna 			break;
844da5ffe11SJussi Kivilinna 
8455f2b424eSCristian Stoica 		if (!template[i].np)
8465f2b424eSCristian Stoica 			continue;
8475f2b424eSCristian Stoica 
848da7f033dSHerbert Xu 		j++;
849e93acd6fSAndrew Lutomirski 		memset(result, 0, digest_size);
850da7f033dSHerbert Xu 
851da7f033dSHerbert Xu 		temp = 0;
852da7f033dSHerbert Xu 		sg_init_table(sg, template[i].np);
853fd57f22aSHerbert Xu 		ret = -EINVAL;
854da7f033dSHerbert Xu 		for (k = 0; k < template[i].np; k++) {
855fd57f22aSHerbert Xu 			if (WARN_ON(offset_in_page(IDX[k]) +
856fd57f22aSHerbert Xu 				    template[i].tap[k] > PAGE_SIZE))
857fd57f22aSHerbert Xu 				goto out;
858da7f033dSHerbert Xu 			sg_set_buf(&sg[k],
859da7f033dSHerbert Xu 				   memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
860da7f033dSHerbert Xu 					  offset_in_page(IDX[k]),
861da7f033dSHerbert Xu 					  template[i].plaintext + temp,
862da7f033dSHerbert Xu 					  template[i].tap[k]),
863da7f033dSHerbert Xu 				   template[i].tap[k]);
864da7f033dSHerbert Xu 			temp += template[i].tap[k];
865da7f033dSHerbert Xu 		}
866da7f033dSHerbert Xu 
867da7f033dSHerbert Xu 		if (template[i].ksize) {
86829b77e5dSHoria Geanta 			if (template[i].ksize > MAX_KEYLEN) {
86929b77e5dSHoria Geanta 				pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
8705f2b424eSCristian Stoica 				       j, algo, template[i].ksize, MAX_KEYLEN);
87129b77e5dSHoria Geanta 				ret = -EINVAL;
87229b77e5dSHoria Geanta 				goto out;
87329b77e5dSHoria Geanta 			}
874da7f033dSHerbert Xu 			crypto_ahash_clear_flags(tfm, ~0);
87529b77e5dSHoria Geanta 			memcpy(key, template[i].key, template[i].ksize);
8765f2b424eSCristian Stoica 			ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
877da7f033dSHerbert Xu 
878da7f033dSHerbert Xu 			if (ret) {
879da7f033dSHerbert Xu 				printk(KERN_ERR "alg: hash: setkey "
880da7f033dSHerbert Xu 				       "failed on chunking test %d "
8815f2b424eSCristian Stoica 				       "for %s: ret=%d\n", j, algo, -ret);
882da7f033dSHerbert Xu 				goto out;
883da7f033dSHerbert Xu 			}
884da7f033dSHerbert Xu 		}
885da7f033dSHerbert Xu 
8865f2b424eSCristian Stoica 		ahash_request_set_crypt(req, sg, result, template[i].psize);
8877f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
8887f397136SGilad Ben-Yossef 		if (ret) {
8897f397136SGilad Ben-Yossef 			pr_err("alg: hash: digest failed on chunking test %d for %s: ret=%d\n",
8907f397136SGilad Ben-Yossef 			       j, algo, -ret);
891da7f033dSHerbert Xu 			goto out;
892da7f033dSHerbert Xu 		}
893da7f033dSHerbert Xu 
894da7f033dSHerbert Xu 		if (memcmp(result, template[i].digest,
895da7f033dSHerbert Xu 			   crypto_ahash_digestsize(tfm))) {
896da7f033dSHerbert Xu 			printk(KERN_ERR "alg: hash: Chunking test %d "
897da7f033dSHerbert Xu 			       "failed for %s\n", j, algo);
898da7f033dSHerbert Xu 			hexdump(result, crypto_ahash_digestsize(tfm));
899da7f033dSHerbert Xu 			ret = -EINVAL;
900da7f033dSHerbert Xu 			goto out;
901da7f033dSHerbert Xu 		}
902da7f033dSHerbert Xu 	}
903da7f033dSHerbert Xu 
904018ba95cSWang, Rui Y 	/* partial update exercise */
905018ba95cSWang, Rui Y 	j = 0;
906018ba95cSWang, Rui Y 	for (i = 0; i < tcount; i++) {
907018ba95cSWang, Rui Y 		/* alignment tests are only done with continuous buffers */
908018ba95cSWang, Rui Y 		if (align_offset != 0)
909018ba95cSWang, Rui Y 			break;
910018ba95cSWang, Rui Y 
911018ba95cSWang, Rui Y 		if (template[i].np < 2)
912018ba95cSWang, Rui Y 			continue;
913018ba95cSWang, Rui Y 
914018ba95cSWang, Rui Y 		j++;
915e93acd6fSAndrew Lutomirski 		memset(result, 0, digest_size);
916018ba95cSWang, Rui Y 
917018ba95cSWang, Rui Y 		ret = -EINVAL;
918018ba95cSWang, Rui Y 		hash_buff = xbuf[0];
919018ba95cSWang, Rui Y 		memcpy(hash_buff, template[i].plaintext,
920018ba95cSWang, Rui Y 			template[i].tap[0]);
921018ba95cSWang, Rui Y 		sg_init_one(&sg[0], hash_buff, template[i].tap[0]);
922018ba95cSWang, Rui Y 
923018ba95cSWang, Rui Y 		if (template[i].ksize) {
924018ba95cSWang, Rui Y 			crypto_ahash_clear_flags(tfm, ~0);
925018ba95cSWang, Rui Y 			if (template[i].ksize > MAX_KEYLEN) {
926018ba95cSWang, Rui Y 				pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
927018ba95cSWang, Rui Y 					j, algo, template[i].ksize, MAX_KEYLEN);
928018ba95cSWang, Rui Y 				ret = -EINVAL;
929018ba95cSWang, Rui Y 				goto out;
930018ba95cSWang, Rui Y 			}
931018ba95cSWang, Rui Y 			memcpy(key, template[i].key, template[i].ksize);
932018ba95cSWang, Rui Y 			ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
933018ba95cSWang, Rui Y 			if (ret) {
934018ba95cSWang, Rui Y 				pr_err("alg: hash: setkey failed on test %d for %s: ret=%d\n",
935018ba95cSWang, Rui Y 					j, algo, -ret);
936018ba95cSWang, Rui Y 				goto out;
937018ba95cSWang, Rui Y 			}
938018ba95cSWang, Rui Y 		}
939018ba95cSWang, Rui Y 
940018ba95cSWang, Rui Y 		ahash_request_set_crypt(req, sg, result, template[i].tap[0]);
9417f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_ahash_init(req), &wait);
942018ba95cSWang, Rui Y 		if (ret) {
943cf3f9609SGilad Ben-Yossef 			pr_err("alg: hash: init failed on test %d for %s: ret=%d\n",
944018ba95cSWang, Rui Y 				j, algo, -ret);
945018ba95cSWang, Rui Y 			goto out;
946018ba95cSWang, Rui Y 		}
9477f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_ahash_update(req), &wait);
948018ba95cSWang, Rui Y 		if (ret) {
949cf3f9609SGilad Ben-Yossef 			pr_err("alg: hash: update failed on test %d for %s: ret=%d\n",
950018ba95cSWang, Rui Y 				j, algo, -ret);
951018ba95cSWang, Rui Y 			goto out;
952018ba95cSWang, Rui Y 		}
953018ba95cSWang, Rui Y 
954018ba95cSWang, Rui Y 		temp = template[i].tap[0];
955018ba95cSWang, Rui Y 		for (k = 1; k < template[i].np; k++) {
956018ba95cSWang, Rui Y 			ret = ahash_partial_update(&req, tfm, &template[i],
957018ba95cSWang, Rui Y 				hash_buff, k, temp, &sg[0], algo, result,
9587f397136SGilad Ben-Yossef 				&wait);
959018ba95cSWang, Rui Y 			if (ret) {
960cf3f9609SGilad Ben-Yossef 				pr_err("alg: hash: partial update failed on test %d for %s: ret=%d\n",
961018ba95cSWang, Rui Y 					j, algo, -ret);
962018ba95cSWang, Rui Y 				goto out_noreq;
963018ba95cSWang, Rui Y 			}
964018ba95cSWang, Rui Y 			temp += template[i].tap[k];
965018ba95cSWang, Rui Y 		}
9667f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_ahash_final(req), &wait);
967018ba95cSWang, Rui Y 		if (ret) {
968cf3f9609SGilad Ben-Yossef 			pr_err("alg: hash: final failed on test %d for %s: ret=%d\n",
969018ba95cSWang, Rui Y 				j, algo, -ret);
970018ba95cSWang, Rui Y 			goto out;
971018ba95cSWang, Rui Y 		}
972018ba95cSWang, Rui Y 		if (memcmp(result, template[i].digest,
973018ba95cSWang, Rui Y 			   crypto_ahash_digestsize(tfm))) {
974018ba95cSWang, Rui Y 			pr_err("alg: hash: Partial Test %d failed for %s\n",
975018ba95cSWang, Rui Y 			       j, algo);
976018ba95cSWang, Rui Y 			hexdump(result, crypto_ahash_digestsize(tfm));
977018ba95cSWang, Rui Y 			ret = -EINVAL;
978018ba95cSWang, Rui Y 			goto out;
979018ba95cSWang, Rui Y 		}
980018ba95cSWang, Rui Y 	}
981018ba95cSWang, Rui Y 
982da7f033dSHerbert Xu 	ret = 0;
983da7f033dSHerbert Xu 
984da7f033dSHerbert Xu out:
985da7f033dSHerbert Xu 	ahash_request_free(req);
986da7f033dSHerbert Xu out_noreq:
987f8b0d4d0SHerbert Xu 	testmgr_free_buf(xbuf);
988f8b0d4d0SHerbert Xu out_nobuf:
98929b77e5dSHoria Geanta 	kfree(key);
99029b77e5dSHoria Geanta 	kfree(result);
991da7f033dSHerbert Xu 	return ret;
992da7f033dSHerbert Xu }
993da7f033dSHerbert Xu 
994b13b1e0cSEric Biggers static int test_hash(struct crypto_ahash *tfm,
995b13b1e0cSEric Biggers 		     const struct hash_testvec *template,
99676715095SGilad Ben-Yossef 		     unsigned int tcount, enum hash_test test_type)
997da5ffe11SJussi Kivilinna {
998da5ffe11SJussi Kivilinna 	unsigned int alignmask;
999da5ffe11SJussi Kivilinna 	int ret;
1000da5ffe11SJussi Kivilinna 
100176715095SGilad Ben-Yossef 	ret = __test_hash(tfm, template, tcount, test_type, 0);
1002da5ffe11SJussi Kivilinna 	if (ret)
1003da5ffe11SJussi Kivilinna 		return ret;
1004da5ffe11SJussi Kivilinna 
1005da5ffe11SJussi Kivilinna 	/* test unaligned buffers, check with one byte offset */
100676715095SGilad Ben-Yossef 	ret = __test_hash(tfm, template, tcount, test_type, 1);
1007da5ffe11SJussi Kivilinna 	if (ret)
1008da5ffe11SJussi Kivilinna 		return ret;
1009da5ffe11SJussi Kivilinna 
1010da5ffe11SJussi Kivilinna 	alignmask = crypto_tfm_alg_alignmask(&tfm->base);
1011da5ffe11SJussi Kivilinna 	if (alignmask) {
1012da5ffe11SJussi Kivilinna 		/* Check if alignment mask for tfm is correctly set. */
101376715095SGilad Ben-Yossef 		ret = __test_hash(tfm, template, tcount, test_type,
1014da5ffe11SJussi Kivilinna 				  alignmask + 1);
1015da5ffe11SJussi Kivilinna 		if (ret)
1016da5ffe11SJussi Kivilinna 			return ret;
1017da5ffe11SJussi Kivilinna 	}
1018da5ffe11SJussi Kivilinna 
1019da5ffe11SJussi Kivilinna 	return 0;
1020da5ffe11SJussi Kivilinna }
1021da5ffe11SJussi Kivilinna 
1022d8a32ac2SJussi Kivilinna static int __test_aead(struct crypto_aead *tfm, int enc,
1023b13b1e0cSEric Biggers 		       const struct aead_testvec *template, unsigned int tcount,
102458dcf548SJussi Kivilinna 		       const bool diff_dst, const int align_offset)
1025da7f033dSHerbert Xu {
1026da7f033dSHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm));
1027da7f033dSHerbert Xu 	unsigned int i, j, k, n, temp;
1028f8b0d4d0SHerbert Xu 	int ret = -ENOMEM;
1029da7f033dSHerbert Xu 	char *q;
1030da7f033dSHerbert Xu 	char *key;
1031da7f033dSHerbert Xu 	struct aead_request *req;
1032d8a32ac2SJussi Kivilinna 	struct scatterlist *sg;
1033d8a32ac2SJussi Kivilinna 	struct scatterlist *sgout;
1034d8a32ac2SJussi Kivilinna 	const char *e, *d;
10357f397136SGilad Ben-Yossef 	struct crypto_wait wait;
1036424a5da6SCristian Stoica 	unsigned int authsize, iv_len;
10379bac019dSTadeusz Struk 	char *iv;
1038f8b0d4d0SHerbert Xu 	char *xbuf[XBUFSIZE];
1039d8a32ac2SJussi Kivilinna 	char *xoutbuf[XBUFSIZE];
1040f8b0d4d0SHerbert Xu 	char *axbuf[XBUFSIZE];
1041f8b0d4d0SHerbert Xu 
10429bac019dSTadeusz Struk 	iv = kzalloc(MAX_IVLEN, GFP_KERNEL);
10439bac019dSTadeusz Struk 	if (!iv)
10449bac019dSTadeusz Struk 		return ret;
104529b77e5dSHoria Geanta 	key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
104629b77e5dSHoria Geanta 	if (!key)
104729b77e5dSHoria Geanta 		goto out_noxbuf;
1048f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(xbuf))
1049f8b0d4d0SHerbert Xu 		goto out_noxbuf;
1050f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(axbuf))
1051f8b0d4d0SHerbert Xu 		goto out_noaxbuf;
1052d8a32ac2SJussi Kivilinna 	if (diff_dst && testmgr_alloc_buf(xoutbuf))
1053d8a32ac2SJussi Kivilinna 		goto out_nooutbuf;
1054d8a32ac2SJussi Kivilinna 
1055d8a32ac2SJussi Kivilinna 	/* avoid "the frame size is larger than 1024 bytes" compiler warning */
10566da2ec56SKees Cook 	sg = kmalloc(array3_size(sizeof(*sg), 8, (diff_dst ? 4 : 2)),
10576da2ec56SKees Cook 		     GFP_KERNEL);
1058d8a32ac2SJussi Kivilinna 	if (!sg)
1059d8a32ac2SJussi Kivilinna 		goto out_nosg;
10608a525fcdSHerbert Xu 	sgout = &sg[16];
1061d8a32ac2SJussi Kivilinna 
1062d8a32ac2SJussi Kivilinna 	if (diff_dst)
1063d8a32ac2SJussi Kivilinna 		d = "-ddst";
1064d8a32ac2SJussi Kivilinna 	else
1065d8a32ac2SJussi Kivilinna 		d = "";
1066d8a32ac2SJussi Kivilinna 
1067da7f033dSHerbert Xu 	if (enc == ENCRYPT)
1068da7f033dSHerbert Xu 		e = "encryption";
1069da7f033dSHerbert Xu 	else
1070da7f033dSHerbert Xu 		e = "decryption";
1071da7f033dSHerbert Xu 
10727f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
1073da7f033dSHerbert Xu 
1074da7f033dSHerbert Xu 	req = aead_request_alloc(tfm, GFP_KERNEL);
1075da7f033dSHerbert Xu 	if (!req) {
1076d8a32ac2SJussi Kivilinna 		pr_err("alg: aead%s: Failed to allocate request for %s\n",
1077d8a32ac2SJussi Kivilinna 		       d, algo);
1078da7f033dSHerbert Xu 		goto out;
1079da7f033dSHerbert Xu 	}
1080da7f033dSHerbert Xu 
1081da7f033dSHerbert Xu 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
10827f397136SGilad Ben-Yossef 				  crypto_req_done, &wait);
1083da7f033dSHerbert Xu 
1084abfa7f43SJerome Marchand 	iv_len = crypto_aead_ivsize(tfm);
1085abfa7f43SJerome Marchand 
1086da7f033dSHerbert Xu 	for (i = 0, j = 0; i < tcount; i++) {
1087a0d608eeSEric Biggers 		const char *input, *expected_output;
1088a0d608eeSEric Biggers 		unsigned int inlen, outlen;
1089a0d608eeSEric Biggers 		char *inbuf, *outbuf, *assocbuf;
1090a0d608eeSEric Biggers 
109105b1d338SCristian Stoica 		if (template[i].np)
109205b1d338SCristian Stoica 			continue;
1093a0d608eeSEric Biggers 		if (enc) {
1094a0d608eeSEric Biggers 			if (template[i].novrfy)
10955bc3de58SEric Biggers 				continue;
1096a0d608eeSEric Biggers 			input = template[i].ptext;
1097a0d608eeSEric Biggers 			inlen = template[i].plen;
1098a0d608eeSEric Biggers 			expected_output = template[i].ctext;
1099a0d608eeSEric Biggers 			outlen = template[i].clen;
1100a0d608eeSEric Biggers 		} else {
1101a0d608eeSEric Biggers 			input = template[i].ctext;
1102a0d608eeSEric Biggers 			inlen = template[i].clen;
1103a0d608eeSEric Biggers 			expected_output = template[i].ptext;
1104a0d608eeSEric Biggers 			outlen = template[i].plen;
1105a0d608eeSEric Biggers 		}
110605b1d338SCristian Stoica 
1107da7f033dSHerbert Xu 		j++;
1108da7f033dSHerbert Xu 
110958dcf548SJussi Kivilinna 		/* some templates have no input data but they will
1110da7f033dSHerbert Xu 		 * touch input
1111da7f033dSHerbert Xu 		 */
1112a0d608eeSEric Biggers 		inbuf = xbuf[0] + align_offset;
1113a0d608eeSEric Biggers 		assocbuf = axbuf[0];
1114da7f033dSHerbert Xu 
1115fd57f22aSHerbert Xu 		ret = -EINVAL;
1116a0d608eeSEric Biggers 		if (WARN_ON(align_offset + template[i].clen > PAGE_SIZE ||
1117a0d608eeSEric Biggers 			    template[i].alen > PAGE_SIZE))
1118fd57f22aSHerbert Xu 			goto out;
1119fd57f22aSHerbert Xu 
1120a0d608eeSEric Biggers 		memcpy(inbuf, input, inlen);
1121a0d608eeSEric Biggers 		memcpy(assocbuf, template[i].assoc, template[i].alen);
1122da7f033dSHerbert Xu 		if (template[i].iv)
1123424a5da6SCristian Stoica 			memcpy(iv, template[i].iv, iv_len);
1124da7f033dSHerbert Xu 		else
1125424a5da6SCristian Stoica 			memset(iv, 0, iv_len);
1126da7f033dSHerbert Xu 
1127da7f033dSHerbert Xu 		crypto_aead_clear_flags(tfm, ~0);
1128da7f033dSHerbert Xu 		if (template[i].wk)
1129231baecdSEric Biggers 			crypto_aead_set_flags(tfm,
1130231baecdSEric Biggers 					      CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
1131da7f033dSHerbert Xu 
113229b77e5dSHoria Geanta 		if (template[i].klen > MAX_KEYLEN) {
113329b77e5dSHoria Geanta 			pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
113429b77e5dSHoria Geanta 			       d, j, algo, template[i].klen,
113529b77e5dSHoria Geanta 			       MAX_KEYLEN);
113629b77e5dSHoria Geanta 			ret = -EINVAL;
113729b77e5dSHoria Geanta 			goto out;
113829b77e5dSHoria Geanta 		}
113929b77e5dSHoria Geanta 		memcpy(key, template[i].key, template[i].klen);
1140da7f033dSHerbert Xu 
114105b1d338SCristian Stoica 		ret = crypto_aead_setkey(tfm, key, template[i].klen);
11420fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
1143d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: setkey failed on test %d for %s: flags=%x\n",
1144d8a32ac2SJussi Kivilinna 			       d, j, algo, crypto_aead_get_flags(tfm));
1145da7f033dSHerbert Xu 			goto out;
1146da7f033dSHerbert Xu 		} else if (ret)
1147da7f033dSHerbert Xu 			continue;
1148da7f033dSHerbert Xu 
1149a0d608eeSEric Biggers 		authsize = template[i].clen - template[i].plen;
1150da7f033dSHerbert Xu 		ret = crypto_aead_setauthsize(tfm, authsize);
1151da7f033dSHerbert Xu 		if (ret) {
1152d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: Failed to set authsize to %u on test %d for %s\n",
1153d8a32ac2SJussi Kivilinna 			       d, authsize, j, algo);
1154da7f033dSHerbert Xu 			goto out;
1155da7f033dSHerbert Xu 		}
1156da7f033dSHerbert Xu 
11578a525fcdSHerbert Xu 		k = !!template[i].alen;
11588a525fcdSHerbert Xu 		sg_init_table(sg, k + 1);
1159a0d608eeSEric Biggers 		sg_set_buf(&sg[0], assocbuf, template[i].alen);
1160a0d608eeSEric Biggers 		sg_set_buf(&sg[k], inbuf, template[i].clen);
1161a0d608eeSEric Biggers 		outbuf = inbuf;
1162d8a32ac2SJussi Kivilinna 
11638a525fcdSHerbert Xu 		if (diff_dst) {
11648a525fcdSHerbert Xu 			sg_init_table(sgout, k + 1);
1165a0d608eeSEric Biggers 			sg_set_buf(&sgout[0], assocbuf, template[i].alen);
11668a525fcdSHerbert Xu 
1167a0d608eeSEric Biggers 			outbuf = xoutbuf[0] + align_offset;
1168a0d608eeSEric Biggers 			sg_set_buf(&sgout[k], outbuf, template[i].clen);
11698a525fcdSHerbert Xu 		}
1170da7f033dSHerbert Xu 
1171a0d608eeSEric Biggers 		aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg, inlen,
1172a0d608eeSEric Biggers 				       iv);
1173da7f033dSHerbert Xu 
11748a525fcdSHerbert Xu 		aead_request_set_ad(req, template[i].alen);
1175da7f033dSHerbert Xu 
11767f397136SGilad Ben-Yossef 		ret = crypto_wait_req(enc ? crypto_aead_encrypt(req)
11777f397136SGilad Ben-Yossef 				      : crypto_aead_decrypt(req), &wait);
1178da7f033dSHerbert Xu 
1179da7f033dSHerbert Xu 		switch (ret) {
1180da7f033dSHerbert Xu 		case 0:
1181e44a1b44SJarod Wilson 			if (template[i].novrfy) {
1182e44a1b44SJarod Wilson 				/* verification was supposed to fail */
1183d8a32ac2SJussi Kivilinna 				pr_err("alg: aead%s: %s failed on test %d for %s: ret was 0, expected -EBADMSG\n",
1184d8a32ac2SJussi Kivilinna 				       d, e, j, algo);
1185e44a1b44SJarod Wilson 				/* so really, we got a bad message */
1186e44a1b44SJarod Wilson 				ret = -EBADMSG;
1187e44a1b44SJarod Wilson 				goto out;
1188e44a1b44SJarod Wilson 			}
1189da7f033dSHerbert Xu 			break;
1190e44a1b44SJarod Wilson 		case -EBADMSG:
1191e44a1b44SJarod Wilson 			if (template[i].novrfy)
1192e44a1b44SJarod Wilson 				/* verification failure was expected */
1193e44a1b44SJarod Wilson 				continue;
1194da7f033dSHerbert Xu 			/* fall through */
1195da7f033dSHerbert Xu 		default:
1196d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: %s failed on test %d for %s: ret=%d\n",
1197d8a32ac2SJussi Kivilinna 			       d, e, j, algo, -ret);
1198da7f033dSHerbert Xu 			goto out;
1199da7f033dSHerbert Xu 		}
1200da7f033dSHerbert Xu 
1201a0d608eeSEric Biggers 		if (memcmp(outbuf, expected_output, outlen)) {
1202d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: Test %d failed on %s for %s\n",
1203d8a32ac2SJussi Kivilinna 			       d, j, e, algo);
1204a0d608eeSEric Biggers 			hexdump(outbuf, outlen);
1205da7f033dSHerbert Xu 			ret = -EINVAL;
1206da7f033dSHerbert Xu 			goto out;
1207da7f033dSHerbert Xu 		}
1208da7f033dSHerbert Xu 	}
1209da7f033dSHerbert Xu 
1210da7f033dSHerbert Xu 	for (i = 0, j = 0; i < tcount; i++) {
1211a0d608eeSEric Biggers 		const char *input, *expected_output;
1212a0d608eeSEric Biggers 		unsigned int inlen, outlen;
1213a0d608eeSEric Biggers 
121458dcf548SJussi Kivilinna 		/* alignment tests are only done with continuous buffers */
121558dcf548SJussi Kivilinna 		if (align_offset != 0)
121658dcf548SJussi Kivilinna 			break;
121758dcf548SJussi Kivilinna 
121805b1d338SCristian Stoica 		if (!template[i].np)
121905b1d338SCristian Stoica 			continue;
122005b1d338SCristian Stoica 
1221a0d608eeSEric Biggers 		if (enc) {
1222a0d608eeSEric Biggers 			if (template[i].novrfy)
12235bc3de58SEric Biggers 				continue;
1224a0d608eeSEric Biggers 			input = template[i].ptext;
1225a0d608eeSEric Biggers 			inlen = template[i].plen;
1226a0d608eeSEric Biggers 			expected_output = template[i].ctext;
1227a0d608eeSEric Biggers 			outlen = template[i].clen;
1228a0d608eeSEric Biggers 		} else {
1229a0d608eeSEric Biggers 			input = template[i].ctext;
1230a0d608eeSEric Biggers 			inlen = template[i].clen;
1231a0d608eeSEric Biggers 			expected_output = template[i].ptext;
1232a0d608eeSEric Biggers 			outlen = template[i].plen;
1233a0d608eeSEric Biggers 		}
12345bc3de58SEric Biggers 
1235da7f033dSHerbert Xu 		j++;
1236da7f033dSHerbert Xu 
1237da7f033dSHerbert Xu 		if (template[i].iv)
1238abfa7f43SJerome Marchand 			memcpy(iv, template[i].iv, iv_len);
1239da7f033dSHerbert Xu 		else
1240da7f033dSHerbert Xu 			memset(iv, 0, MAX_IVLEN);
1241da7f033dSHerbert Xu 
1242da7f033dSHerbert Xu 		crypto_aead_clear_flags(tfm, ~0);
1243da7f033dSHerbert Xu 		if (template[i].wk)
1244231baecdSEric Biggers 			crypto_aead_set_flags(tfm,
1245231baecdSEric Biggers 					      CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
124629b77e5dSHoria Geanta 		if (template[i].klen > MAX_KEYLEN) {
124729b77e5dSHoria Geanta 			pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
124805b1d338SCristian Stoica 			       d, j, algo, template[i].klen, MAX_KEYLEN);
124929b77e5dSHoria Geanta 			ret = -EINVAL;
125029b77e5dSHoria Geanta 			goto out;
125129b77e5dSHoria Geanta 		}
125229b77e5dSHoria Geanta 		memcpy(key, template[i].key, template[i].klen);
1253da7f033dSHerbert Xu 
1254da7f033dSHerbert Xu 		ret = crypto_aead_setkey(tfm, key, template[i].klen);
12550fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
1256d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: setkey failed on chunk test %d for %s: flags=%x\n",
1257d8a32ac2SJussi Kivilinna 			       d, j, algo, crypto_aead_get_flags(tfm));
1258da7f033dSHerbert Xu 			goto out;
1259da7f033dSHerbert Xu 		} else if (ret)
1260da7f033dSHerbert Xu 			continue;
1261da7f033dSHerbert Xu 
1262a0d608eeSEric Biggers 		authsize = template[i].clen - template[i].plen;
1263da7f033dSHerbert Xu 
1264da7f033dSHerbert Xu 		ret = -EINVAL;
12658a525fcdSHerbert Xu 		sg_init_table(sg, template[i].anp + template[i].np);
1266d8a32ac2SJussi Kivilinna 		if (diff_dst)
12678a525fcdSHerbert Xu 			sg_init_table(sgout, template[i].anp + template[i].np);
12688a525fcdSHerbert Xu 
12698a525fcdSHerbert Xu 		ret = -EINVAL;
12708a525fcdSHerbert Xu 		for (k = 0, temp = 0; k < template[i].anp; k++) {
12718a525fcdSHerbert Xu 			if (WARN_ON(offset_in_page(IDX[k]) +
12728a525fcdSHerbert Xu 				    template[i].atap[k] > PAGE_SIZE))
12738a525fcdSHerbert Xu 				goto out;
12748a525fcdSHerbert Xu 			sg_set_buf(&sg[k],
12758a525fcdSHerbert Xu 				   memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
12768a525fcdSHerbert Xu 					  offset_in_page(IDX[k]),
12778a525fcdSHerbert Xu 					  template[i].assoc + temp,
12788a525fcdSHerbert Xu 					  template[i].atap[k]),
12798a525fcdSHerbert Xu 				   template[i].atap[k]);
12808a525fcdSHerbert Xu 			if (diff_dst)
12818a525fcdSHerbert Xu 				sg_set_buf(&sgout[k],
12828a525fcdSHerbert Xu 					   axbuf[IDX[k] >> PAGE_SHIFT] +
12838a525fcdSHerbert Xu 					   offset_in_page(IDX[k]),
12848a525fcdSHerbert Xu 					   template[i].atap[k]);
12858a525fcdSHerbert Xu 			temp += template[i].atap[k];
12868a525fcdSHerbert Xu 		}
12878a525fcdSHerbert Xu 
1288da7f033dSHerbert Xu 		for (k = 0, temp = 0; k < template[i].np; k++) {
1289a0d608eeSEric Biggers 			n = template[i].tap[k];
1290a0d608eeSEric Biggers 			if (k == template[i].np - 1 && !enc)
1291a0d608eeSEric Biggers 				n += authsize;
1292a0d608eeSEric Biggers 
1293a0d608eeSEric Biggers 			if (WARN_ON(offset_in_page(IDX[k]) + n > PAGE_SIZE))
1294da7f033dSHerbert Xu 				goto out;
1295da7f033dSHerbert Xu 
129605b1d338SCristian Stoica 			q = xbuf[IDX[k] >> PAGE_SHIFT] + offset_in_page(IDX[k]);
1297a0d608eeSEric Biggers 			memcpy(q, input + temp, n);
1298a0d608eeSEric Biggers 			sg_set_buf(&sg[template[i].anp + k], q, n);
1299d8a32ac2SJussi Kivilinna 
1300d8a32ac2SJussi Kivilinna 			if (diff_dst) {
1301d8a32ac2SJussi Kivilinna 				q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
1302d8a32ac2SJussi Kivilinna 				    offset_in_page(IDX[k]);
1303d8a32ac2SJussi Kivilinna 
1304a0d608eeSEric Biggers 				memset(q, 0, n);
1305d8a32ac2SJussi Kivilinna 
1306a0d608eeSEric Biggers 				sg_set_buf(&sgout[template[i].anp + k], q, n);
1307d8a32ac2SJussi Kivilinna 			}
1308d8a32ac2SJussi Kivilinna 
13098ec25c51SHoria Geanta 			if (k == template[i].np - 1 && enc)
13108ec25c51SHoria Geanta 				n += authsize;
13118ec25c51SHoria Geanta 			if (offset_in_page(q) + n < PAGE_SIZE)
13128ec25c51SHoria Geanta 				q[n] = 0;
13138ec25c51SHoria Geanta 
1314a0d608eeSEric Biggers 			temp += n;
1315da7f033dSHerbert Xu 		}
1316da7f033dSHerbert Xu 
1317da7f033dSHerbert Xu 		ret = crypto_aead_setauthsize(tfm, authsize);
1318da7f033dSHerbert Xu 		if (ret) {
1319d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: Failed to set authsize to %u on chunk test %d for %s\n",
1320d8a32ac2SJussi Kivilinna 			       d, authsize, j, algo);
1321da7f033dSHerbert Xu 			goto out;
1322da7f033dSHerbert Xu 		}
1323da7f033dSHerbert Xu 
1324da7f033dSHerbert Xu 		if (enc) {
13258a525fcdSHerbert Xu 			if (WARN_ON(sg[template[i].anp + k - 1].offset +
13268a525fcdSHerbert Xu 				    sg[template[i].anp + k - 1].length +
13278a525fcdSHerbert Xu 				    authsize > PAGE_SIZE)) {
1328da7f033dSHerbert Xu 				ret = -EINVAL;
1329da7f033dSHerbert Xu 				goto out;
1330da7f033dSHerbert Xu 			}
1331da7f033dSHerbert Xu 
1332d8a32ac2SJussi Kivilinna 			if (diff_dst)
13338a525fcdSHerbert Xu 				sgout[template[i].anp + k - 1].length +=
13348a525fcdSHerbert Xu 					authsize;
13358a525fcdSHerbert Xu 			sg[template[i].anp + k - 1].length += authsize;
1336da7f033dSHerbert Xu 		}
1337da7f033dSHerbert Xu 
1338d8a32ac2SJussi Kivilinna 		aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
1339a0d608eeSEric Biggers 				       inlen, iv);
1340da7f033dSHerbert Xu 
13418a525fcdSHerbert Xu 		aead_request_set_ad(req, template[i].alen);
1342da7f033dSHerbert Xu 
13437f397136SGilad Ben-Yossef 		ret = crypto_wait_req(enc ? crypto_aead_encrypt(req)
13447f397136SGilad Ben-Yossef 				      : crypto_aead_decrypt(req), &wait);
1345da7f033dSHerbert Xu 
1346da7f033dSHerbert Xu 		switch (ret) {
1347da7f033dSHerbert Xu 		case 0:
1348e44a1b44SJarod Wilson 			if (template[i].novrfy) {
1349e44a1b44SJarod Wilson 				/* verification was supposed to fail */
1350d8a32ac2SJussi Kivilinna 				pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret was 0, expected -EBADMSG\n",
1351d8a32ac2SJussi Kivilinna 				       d, e, j, algo);
1352e44a1b44SJarod Wilson 				/* so really, we got a bad message */
1353e44a1b44SJarod Wilson 				ret = -EBADMSG;
1354e44a1b44SJarod Wilson 				goto out;
1355e44a1b44SJarod Wilson 			}
1356da7f033dSHerbert Xu 			break;
1357e44a1b44SJarod Wilson 		case -EBADMSG:
1358e44a1b44SJarod Wilson 			if (template[i].novrfy)
1359e44a1b44SJarod Wilson 				/* verification failure was expected */
1360e44a1b44SJarod Wilson 				continue;
1361da7f033dSHerbert Xu 			/* fall through */
1362da7f033dSHerbert Xu 		default:
1363d8a32ac2SJussi Kivilinna 			pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret=%d\n",
1364d8a32ac2SJussi Kivilinna 			       d, e, j, algo, -ret);
1365da7f033dSHerbert Xu 			goto out;
1366da7f033dSHerbert Xu 		}
1367da7f033dSHerbert Xu 
1368da7f033dSHerbert Xu 		ret = -EINVAL;
1369da7f033dSHerbert Xu 		for (k = 0, temp = 0; k < template[i].np; k++) {
1370d8a32ac2SJussi Kivilinna 			if (diff_dst)
1371d8a32ac2SJussi Kivilinna 				q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
1372d8a32ac2SJussi Kivilinna 				    offset_in_page(IDX[k]);
1373d8a32ac2SJussi Kivilinna 			else
1374da7f033dSHerbert Xu 				q = xbuf[IDX[k] >> PAGE_SHIFT] +
1375da7f033dSHerbert Xu 				    offset_in_page(IDX[k]);
1376da7f033dSHerbert Xu 
1377da7f033dSHerbert Xu 			n = template[i].tap[k];
1378a0d608eeSEric Biggers 			if (k == template[i].np - 1 && enc)
1379a0d608eeSEric Biggers 				n += authsize;
1380da7f033dSHerbert Xu 
1381a0d608eeSEric Biggers 			if (memcmp(q, expected_output + temp, n)) {
1382d8a32ac2SJussi Kivilinna 				pr_err("alg: aead%s: Chunk test %d failed on %s at page %u for %s\n",
1383d8a32ac2SJussi Kivilinna 				       d, j, e, k, algo);
1384da7f033dSHerbert Xu 				hexdump(q, n);
1385da7f033dSHerbert Xu 				goto out;
1386da7f033dSHerbert Xu 			}
1387da7f033dSHerbert Xu 
1388da7f033dSHerbert Xu 			q += n;
1389da7f033dSHerbert Xu 			if (k == template[i].np - 1 && !enc) {
1390a0d608eeSEric Biggers 				if (!diff_dst && memcmp(q, input + temp + n,
1391a0d608eeSEric Biggers 							authsize))
1392da7f033dSHerbert Xu 					n = authsize;
1393da7f033dSHerbert Xu 				else
1394da7f033dSHerbert Xu 					n = 0;
1395da7f033dSHerbert Xu 			} else {
139605b1d338SCristian Stoica 				for (n = 0; offset_in_page(q + n) && q[n]; n++)
1397da7f033dSHerbert Xu 					;
1398da7f033dSHerbert Xu 			}
1399da7f033dSHerbert Xu 			if (n) {
1400d8a32ac2SJussi Kivilinna 				pr_err("alg: aead%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
1401d8a32ac2SJussi Kivilinna 				       d, j, e, k, algo, n);
1402da7f033dSHerbert Xu 				hexdump(q, n);
1403da7f033dSHerbert Xu 				goto out;
1404da7f033dSHerbert Xu 			}
1405da7f033dSHerbert Xu 
1406da7f033dSHerbert Xu 			temp += template[i].tap[k];
1407da7f033dSHerbert Xu 		}
1408da7f033dSHerbert Xu 	}
1409da7f033dSHerbert Xu 
1410da7f033dSHerbert Xu 	ret = 0;
1411da7f033dSHerbert Xu 
1412da7f033dSHerbert Xu out:
1413da7f033dSHerbert Xu 	aead_request_free(req);
1414d8a32ac2SJussi Kivilinna 	kfree(sg);
1415d8a32ac2SJussi Kivilinna out_nosg:
1416d8a32ac2SJussi Kivilinna 	if (diff_dst)
1417d8a32ac2SJussi Kivilinna 		testmgr_free_buf(xoutbuf);
1418d8a32ac2SJussi Kivilinna out_nooutbuf:
1419f8b0d4d0SHerbert Xu 	testmgr_free_buf(axbuf);
1420f8b0d4d0SHerbert Xu out_noaxbuf:
1421f8b0d4d0SHerbert Xu 	testmgr_free_buf(xbuf);
1422f8b0d4d0SHerbert Xu out_noxbuf:
142329b77e5dSHoria Geanta 	kfree(key);
14249bac019dSTadeusz Struk 	kfree(iv);
1425da7f033dSHerbert Xu 	return ret;
1426da7f033dSHerbert Xu }
1427da7f033dSHerbert Xu 
1428d8a32ac2SJussi Kivilinna static int test_aead(struct crypto_aead *tfm, int enc,
1429b13b1e0cSEric Biggers 		     const struct aead_testvec *template, unsigned int tcount)
1430d8a32ac2SJussi Kivilinna {
143158dcf548SJussi Kivilinna 	unsigned int alignmask;
1432d8a32ac2SJussi Kivilinna 	int ret;
1433d8a32ac2SJussi Kivilinna 
1434d8a32ac2SJussi Kivilinna 	/* test 'dst == src' case */
143558dcf548SJussi Kivilinna 	ret = __test_aead(tfm, enc, template, tcount, false, 0);
1436d8a32ac2SJussi Kivilinna 	if (ret)
1437d8a32ac2SJussi Kivilinna 		return ret;
1438d8a32ac2SJussi Kivilinna 
1439d8a32ac2SJussi Kivilinna 	/* test 'dst != src' case */
144058dcf548SJussi Kivilinna 	ret = __test_aead(tfm, enc, template, tcount, true, 0);
144158dcf548SJussi Kivilinna 	if (ret)
144258dcf548SJussi Kivilinna 		return ret;
144358dcf548SJussi Kivilinna 
144458dcf548SJussi Kivilinna 	/* test unaligned buffers, check with one byte offset */
144558dcf548SJussi Kivilinna 	ret = __test_aead(tfm, enc, template, tcount, true, 1);
144658dcf548SJussi Kivilinna 	if (ret)
144758dcf548SJussi Kivilinna 		return ret;
144858dcf548SJussi Kivilinna 
144958dcf548SJussi Kivilinna 	alignmask = crypto_tfm_alg_alignmask(&tfm->base);
145058dcf548SJussi Kivilinna 	if (alignmask) {
145158dcf548SJussi Kivilinna 		/* Check if alignment mask for tfm is correctly set. */
145258dcf548SJussi Kivilinna 		ret = __test_aead(tfm, enc, template, tcount, true,
145358dcf548SJussi Kivilinna 				  alignmask + 1);
145458dcf548SJussi Kivilinna 		if (ret)
145558dcf548SJussi Kivilinna 			return ret;
145658dcf548SJussi Kivilinna 	}
145758dcf548SJussi Kivilinna 
145858dcf548SJussi Kivilinna 	return 0;
1459d8a32ac2SJussi Kivilinna }
1460d8a32ac2SJussi Kivilinna 
14611aa4ecd9SHerbert Xu static int test_cipher(struct crypto_cipher *tfm, int enc,
1462b13b1e0cSEric Biggers 		       const struct cipher_testvec *template,
1463b13b1e0cSEric Biggers 		       unsigned int tcount)
14641aa4ecd9SHerbert Xu {
14651aa4ecd9SHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
14661aa4ecd9SHerbert Xu 	unsigned int i, j, k;
14671aa4ecd9SHerbert Xu 	char *q;
14681aa4ecd9SHerbert Xu 	const char *e;
146992a4c9feSEric Biggers 	const char *input, *result;
14701aa4ecd9SHerbert Xu 	void *data;
1471f8b0d4d0SHerbert Xu 	char *xbuf[XBUFSIZE];
1472f8b0d4d0SHerbert Xu 	int ret = -ENOMEM;
1473f8b0d4d0SHerbert Xu 
1474f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(xbuf))
1475f8b0d4d0SHerbert Xu 		goto out_nobuf;
14761aa4ecd9SHerbert Xu 
14771aa4ecd9SHerbert Xu 	if (enc == ENCRYPT)
14781aa4ecd9SHerbert Xu 	        e = "encryption";
14791aa4ecd9SHerbert Xu 	else
14801aa4ecd9SHerbert Xu 		e = "decryption";
14811aa4ecd9SHerbert Xu 
14821aa4ecd9SHerbert Xu 	j = 0;
14831aa4ecd9SHerbert Xu 	for (i = 0; i < tcount; i++) {
14841aa4ecd9SHerbert Xu 		if (template[i].np)
14851aa4ecd9SHerbert Xu 			continue;
14861aa4ecd9SHerbert Xu 
148710faa8c0SStephan Mueller 		if (fips_enabled && template[i].fips_skip)
148810faa8c0SStephan Mueller 			continue;
148910faa8c0SStephan Mueller 
149092a4c9feSEric Biggers 		input  = enc ? template[i].ptext : template[i].ctext;
149192a4c9feSEric Biggers 		result = enc ? template[i].ctext : template[i].ptext;
14921aa4ecd9SHerbert Xu 		j++;
14931aa4ecd9SHerbert Xu 
1494fd57f22aSHerbert Xu 		ret = -EINVAL;
149592a4c9feSEric Biggers 		if (WARN_ON(template[i].len > PAGE_SIZE))
1496fd57f22aSHerbert Xu 			goto out;
1497fd57f22aSHerbert Xu 
14981aa4ecd9SHerbert Xu 		data = xbuf[0];
149992a4c9feSEric Biggers 		memcpy(data, input, template[i].len);
15001aa4ecd9SHerbert Xu 
15011aa4ecd9SHerbert Xu 		crypto_cipher_clear_flags(tfm, ~0);
15021aa4ecd9SHerbert Xu 		if (template[i].wk)
1503231baecdSEric Biggers 			crypto_cipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
15041aa4ecd9SHerbert Xu 
15051aa4ecd9SHerbert Xu 		ret = crypto_cipher_setkey(tfm, template[i].key,
15061aa4ecd9SHerbert Xu 					   template[i].klen);
15070fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
15081aa4ecd9SHerbert Xu 			printk(KERN_ERR "alg: cipher: setkey failed "
15091aa4ecd9SHerbert Xu 			       "on test %d for %s: flags=%x\n", j,
15101aa4ecd9SHerbert Xu 			       algo, crypto_cipher_get_flags(tfm));
15111aa4ecd9SHerbert Xu 			goto out;
15121aa4ecd9SHerbert Xu 		} else if (ret)
15131aa4ecd9SHerbert Xu 			continue;
15141aa4ecd9SHerbert Xu 
151592a4c9feSEric Biggers 		for (k = 0; k < template[i].len;
15161aa4ecd9SHerbert Xu 		     k += crypto_cipher_blocksize(tfm)) {
15171aa4ecd9SHerbert Xu 			if (enc)
15181aa4ecd9SHerbert Xu 				crypto_cipher_encrypt_one(tfm, data + k,
15191aa4ecd9SHerbert Xu 							  data + k);
15201aa4ecd9SHerbert Xu 			else
15211aa4ecd9SHerbert Xu 				crypto_cipher_decrypt_one(tfm, data + k,
15221aa4ecd9SHerbert Xu 							  data + k);
15231aa4ecd9SHerbert Xu 		}
15241aa4ecd9SHerbert Xu 
15251aa4ecd9SHerbert Xu 		q = data;
152692a4c9feSEric Biggers 		if (memcmp(q, result, template[i].len)) {
15271aa4ecd9SHerbert Xu 			printk(KERN_ERR "alg: cipher: Test %d failed "
15281aa4ecd9SHerbert Xu 			       "on %s for %s\n", j, e, algo);
152992a4c9feSEric Biggers 			hexdump(q, template[i].len);
15301aa4ecd9SHerbert Xu 			ret = -EINVAL;
15311aa4ecd9SHerbert Xu 			goto out;
15321aa4ecd9SHerbert Xu 		}
15331aa4ecd9SHerbert Xu 	}
15341aa4ecd9SHerbert Xu 
15351aa4ecd9SHerbert Xu 	ret = 0;
15361aa4ecd9SHerbert Xu 
15371aa4ecd9SHerbert Xu out:
1538f8b0d4d0SHerbert Xu 	testmgr_free_buf(xbuf);
1539f8b0d4d0SHerbert Xu out_nobuf:
15401aa4ecd9SHerbert Xu 	return ret;
15411aa4ecd9SHerbert Xu }
15421aa4ecd9SHerbert Xu 
154312773d93SHerbert Xu static int __test_skcipher(struct crypto_skcipher *tfm, int enc,
1544b13b1e0cSEric Biggers 			   const struct cipher_testvec *template,
1545b13b1e0cSEric Biggers 			   unsigned int tcount,
15463a338f20SJussi Kivilinna 			   const bool diff_dst, const int align_offset)
1547da7f033dSHerbert Xu {
1548da7f033dSHerbert Xu 	const char *algo =
154912773d93SHerbert Xu 		crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm));
1550da7f033dSHerbert Xu 	unsigned int i, j, k, n, temp;
1551da7f033dSHerbert Xu 	char *q;
155212773d93SHerbert Xu 	struct skcipher_request *req;
1553da7f033dSHerbert Xu 	struct scatterlist sg[8];
155408d6af8cSJussi Kivilinna 	struct scatterlist sgout[8];
155508d6af8cSJussi Kivilinna 	const char *e, *d;
15567f397136SGilad Ben-Yossef 	struct crypto_wait wait;
155792a4c9feSEric Biggers 	const char *input, *result;
1558da7f033dSHerbert Xu 	void *data;
1559da7f033dSHerbert Xu 	char iv[MAX_IVLEN];
1560f8b0d4d0SHerbert Xu 	char *xbuf[XBUFSIZE];
156108d6af8cSJussi Kivilinna 	char *xoutbuf[XBUFSIZE];
1562f8b0d4d0SHerbert Xu 	int ret = -ENOMEM;
156384cba178SAndrey Ryabinin 	unsigned int ivsize = crypto_skcipher_ivsize(tfm);
1564f8b0d4d0SHerbert Xu 
1565f8b0d4d0SHerbert Xu 	if (testmgr_alloc_buf(xbuf))
1566f8b0d4d0SHerbert Xu 		goto out_nobuf;
1567da7f033dSHerbert Xu 
156808d6af8cSJussi Kivilinna 	if (diff_dst && testmgr_alloc_buf(xoutbuf))
156908d6af8cSJussi Kivilinna 		goto out_nooutbuf;
157008d6af8cSJussi Kivilinna 
157108d6af8cSJussi Kivilinna 	if (diff_dst)
157208d6af8cSJussi Kivilinna 		d = "-ddst";
157308d6af8cSJussi Kivilinna 	else
157408d6af8cSJussi Kivilinna 		d = "";
157508d6af8cSJussi Kivilinna 
1576da7f033dSHerbert Xu 	if (enc == ENCRYPT)
1577da7f033dSHerbert Xu 	        e = "encryption";
1578da7f033dSHerbert Xu 	else
1579da7f033dSHerbert Xu 		e = "decryption";
1580da7f033dSHerbert Xu 
15817f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
1582da7f033dSHerbert Xu 
158312773d93SHerbert Xu 	req = skcipher_request_alloc(tfm, GFP_KERNEL);
1584da7f033dSHerbert Xu 	if (!req) {
158508d6af8cSJussi Kivilinna 		pr_err("alg: skcipher%s: Failed to allocate request for %s\n",
158608d6af8cSJussi Kivilinna 		       d, algo);
1587da7f033dSHerbert Xu 		goto out;
1588da7f033dSHerbert Xu 	}
1589da7f033dSHerbert Xu 
159012773d93SHerbert Xu 	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
15917f397136SGilad Ben-Yossef 				      crypto_req_done, &wait);
1592da7f033dSHerbert Xu 
1593da7f033dSHerbert Xu 	j = 0;
1594da7f033dSHerbert Xu 	for (i = 0; i < tcount; i++) {
1595bbb9a7ddSCristian Stoica 		if (template[i].np && !template[i].also_non_np)
1596bbb9a7ddSCristian Stoica 			continue;
1597bbb9a7ddSCristian Stoica 
159810faa8c0SStephan Mueller 		if (fips_enabled && template[i].fips_skip)
159910faa8c0SStephan Mueller 			continue;
160010faa8c0SStephan Mueller 
160192a4c9feSEric Biggers 		if (template[i].iv && !(template[i].generates_iv && enc))
160284cba178SAndrey Ryabinin 			memcpy(iv, template[i].iv, ivsize);
1603da7f033dSHerbert Xu 		else
1604da7f033dSHerbert Xu 			memset(iv, 0, MAX_IVLEN);
1605da7f033dSHerbert Xu 
160692a4c9feSEric Biggers 		input  = enc ? template[i].ptext : template[i].ctext;
160792a4c9feSEric Biggers 		result = enc ? template[i].ctext : template[i].ptext;
1608da7f033dSHerbert Xu 		j++;
1609fd57f22aSHerbert Xu 		ret = -EINVAL;
161092a4c9feSEric Biggers 		if (WARN_ON(align_offset + template[i].len > PAGE_SIZE))
1611fd57f22aSHerbert Xu 			goto out;
1612fd57f22aSHerbert Xu 
1613da7f033dSHerbert Xu 		data = xbuf[0];
16143a338f20SJussi Kivilinna 		data += align_offset;
161592a4c9feSEric Biggers 		memcpy(data, input, template[i].len);
1616da7f033dSHerbert Xu 
161712773d93SHerbert Xu 		crypto_skcipher_clear_flags(tfm, ~0);
1618da7f033dSHerbert Xu 		if (template[i].wk)
1619231baecdSEric Biggers 			crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
1620da7f033dSHerbert Xu 
162112773d93SHerbert Xu 		ret = crypto_skcipher_setkey(tfm, template[i].key,
1622da7f033dSHerbert Xu 					     template[i].klen);
16230fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
162408d6af8cSJussi Kivilinna 			pr_err("alg: skcipher%s: setkey failed on test %d for %s: flags=%x\n",
162512773d93SHerbert Xu 			       d, j, algo, crypto_skcipher_get_flags(tfm));
1626da7f033dSHerbert Xu 			goto out;
1627da7f033dSHerbert Xu 		} else if (ret)
1628da7f033dSHerbert Xu 			continue;
1629da7f033dSHerbert Xu 
163092a4c9feSEric Biggers 		sg_init_one(&sg[0], data, template[i].len);
163108d6af8cSJussi Kivilinna 		if (diff_dst) {
163208d6af8cSJussi Kivilinna 			data = xoutbuf[0];
16333a338f20SJussi Kivilinna 			data += align_offset;
163492a4c9feSEric Biggers 			sg_init_one(&sgout[0], data, template[i].len);
163508d6af8cSJussi Kivilinna 		}
1636da7f033dSHerbert Xu 
163712773d93SHerbert Xu 		skcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
163892a4c9feSEric Biggers 					   template[i].len, iv);
16397f397136SGilad Ben-Yossef 		ret = crypto_wait_req(enc ? crypto_skcipher_encrypt(req) :
16407f397136SGilad Ben-Yossef 				      crypto_skcipher_decrypt(req), &wait);
1641da7f033dSHerbert Xu 
16427f397136SGilad Ben-Yossef 		if (ret) {
164308d6af8cSJussi Kivilinna 			pr_err("alg: skcipher%s: %s failed on test %d for %s: ret=%d\n",
164408d6af8cSJussi Kivilinna 			       d, e, j, algo, -ret);
1645da7f033dSHerbert Xu 			goto out;
1646da7f033dSHerbert Xu 		}
1647da7f033dSHerbert Xu 
1648da7f033dSHerbert Xu 		q = data;
164992a4c9feSEric Biggers 		if (memcmp(q, result, template[i].len)) {
16508a826a34SBoris BREZILLON 			pr_err("alg: skcipher%s: Test %d failed (invalid result) on %s for %s\n",
165108d6af8cSJussi Kivilinna 			       d, j, e, algo);
165292a4c9feSEric Biggers 			hexdump(q, template[i].len);
1653da7f033dSHerbert Xu 			ret = -EINVAL;
1654da7f033dSHerbert Xu 			goto out;
1655da7f033dSHerbert Xu 		}
16568a826a34SBoris BREZILLON 
165792a4c9feSEric Biggers 		if (template[i].generates_iv && enc &&
165892a4c9feSEric Biggers 		    memcmp(iv, template[i].iv, crypto_skcipher_ivsize(tfm))) {
16598a826a34SBoris BREZILLON 			pr_err("alg: skcipher%s: Test %d failed (invalid output IV) on %s for %s\n",
16608a826a34SBoris BREZILLON 			       d, j, e, algo);
16618a826a34SBoris BREZILLON 			hexdump(iv, crypto_skcipher_ivsize(tfm));
16628a826a34SBoris BREZILLON 			ret = -EINVAL;
16638a826a34SBoris BREZILLON 			goto out;
16648a826a34SBoris BREZILLON 		}
1665da7f033dSHerbert Xu 	}
1666da7f033dSHerbert Xu 
1667da7f033dSHerbert Xu 	j = 0;
1668da7f033dSHerbert Xu 	for (i = 0; i < tcount; i++) {
16693a338f20SJussi Kivilinna 		/* alignment tests are only done with continuous buffers */
16703a338f20SJussi Kivilinna 		if (align_offset != 0)
16713a338f20SJussi Kivilinna 			break;
1672da7f033dSHerbert Xu 
1673bbb9a7ddSCristian Stoica 		if (!template[i].np)
1674bbb9a7ddSCristian Stoica 			continue;
1675bbb9a7ddSCristian Stoica 
167610faa8c0SStephan Mueller 		if (fips_enabled && template[i].fips_skip)
167710faa8c0SStephan Mueller 			continue;
167810faa8c0SStephan Mueller 
167992a4c9feSEric Biggers 		if (template[i].iv && !(template[i].generates_iv && enc))
168084cba178SAndrey Ryabinin 			memcpy(iv, template[i].iv, ivsize);
1681da7f033dSHerbert Xu 		else
1682da7f033dSHerbert Xu 			memset(iv, 0, MAX_IVLEN);
1683da7f033dSHerbert Xu 
168492a4c9feSEric Biggers 		input  = enc ? template[i].ptext : template[i].ctext;
168592a4c9feSEric Biggers 		result = enc ? template[i].ctext : template[i].ptext;
1686da7f033dSHerbert Xu 		j++;
168712773d93SHerbert Xu 		crypto_skcipher_clear_flags(tfm, ~0);
1688da7f033dSHerbert Xu 		if (template[i].wk)
1689231baecdSEric Biggers 			crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
1690da7f033dSHerbert Xu 
169112773d93SHerbert Xu 		ret = crypto_skcipher_setkey(tfm, template[i].key,
1692da7f033dSHerbert Xu 					     template[i].klen);
16930fae0c1eSYanjiang Jin 		if (template[i].fail == !ret) {
169408d6af8cSJussi Kivilinna 			pr_err("alg: skcipher%s: setkey failed on chunk test %d for %s: flags=%x\n",
169512773d93SHerbert Xu 			       d, j, algo, crypto_skcipher_get_flags(tfm));
1696da7f033dSHerbert Xu 			goto out;
1697da7f033dSHerbert Xu 		} else if (ret)
1698da7f033dSHerbert Xu 			continue;
1699da7f033dSHerbert Xu 
1700da7f033dSHerbert Xu 		temp = 0;
1701da7f033dSHerbert Xu 		ret = -EINVAL;
1702da7f033dSHerbert Xu 		sg_init_table(sg, template[i].np);
170308d6af8cSJussi Kivilinna 		if (diff_dst)
170408d6af8cSJussi Kivilinna 			sg_init_table(sgout, template[i].np);
1705da7f033dSHerbert Xu 		for (k = 0; k < template[i].np; k++) {
1706da7f033dSHerbert Xu 			if (WARN_ON(offset_in_page(IDX[k]) +
1707da7f033dSHerbert Xu 				    template[i].tap[k] > PAGE_SIZE))
1708da7f033dSHerbert Xu 				goto out;
1709da7f033dSHerbert Xu 
1710a1aa44a2SCristian Stoica 			q = xbuf[IDX[k] >> PAGE_SHIFT] + offset_in_page(IDX[k]);
1711da7f033dSHerbert Xu 
171292a4c9feSEric Biggers 			memcpy(q, input + temp, template[i].tap[k]);
1713da7f033dSHerbert Xu 
1714a1aa44a2SCristian Stoica 			if (offset_in_page(q) + template[i].tap[k] < PAGE_SIZE)
1715da7f033dSHerbert Xu 				q[template[i].tap[k]] = 0;
1716da7f033dSHerbert Xu 
1717da7f033dSHerbert Xu 			sg_set_buf(&sg[k], q, template[i].tap[k]);
171808d6af8cSJussi Kivilinna 			if (diff_dst) {
171908d6af8cSJussi Kivilinna 				q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
172008d6af8cSJussi Kivilinna 				    offset_in_page(IDX[k]);
172108d6af8cSJussi Kivilinna 
1722a1aa44a2SCristian Stoica 				sg_set_buf(&sgout[k], q, template[i].tap[k]);
172308d6af8cSJussi Kivilinna 
172408d6af8cSJussi Kivilinna 				memset(q, 0, template[i].tap[k]);
172508d6af8cSJussi Kivilinna 				if (offset_in_page(q) +
172608d6af8cSJussi Kivilinna 				    template[i].tap[k] < PAGE_SIZE)
172708d6af8cSJussi Kivilinna 					q[template[i].tap[k]] = 0;
172808d6af8cSJussi Kivilinna 			}
1729da7f033dSHerbert Xu 
1730da7f033dSHerbert Xu 			temp += template[i].tap[k];
1731da7f033dSHerbert Xu 		}
1732da7f033dSHerbert Xu 
173312773d93SHerbert Xu 		skcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
173492a4c9feSEric Biggers 					   template[i].len, iv);
1735da7f033dSHerbert Xu 
17367f397136SGilad Ben-Yossef 		ret = crypto_wait_req(enc ? crypto_skcipher_encrypt(req) :
17377f397136SGilad Ben-Yossef 				      crypto_skcipher_decrypt(req), &wait);
1738da7f033dSHerbert Xu 
17397f397136SGilad Ben-Yossef 		if (ret) {
174008d6af8cSJussi Kivilinna 			pr_err("alg: skcipher%s: %s failed on chunk test %d for %s: ret=%d\n",
174108d6af8cSJussi Kivilinna 			       d, e, j, algo, -ret);
1742da7f033dSHerbert Xu 			goto out;
1743da7f033dSHerbert Xu 		}
1744da7f033dSHerbert Xu 
1745da7f033dSHerbert Xu 		temp = 0;
1746da7f033dSHerbert Xu 		ret = -EINVAL;
1747da7f033dSHerbert Xu 		for (k = 0; k < template[i].np; k++) {
174808d6af8cSJussi Kivilinna 			if (diff_dst)
174908d6af8cSJussi Kivilinna 				q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
175008d6af8cSJussi Kivilinna 				    offset_in_page(IDX[k]);
175108d6af8cSJussi Kivilinna 			else
1752da7f033dSHerbert Xu 				q = xbuf[IDX[k] >> PAGE_SHIFT] +
1753da7f033dSHerbert Xu 				    offset_in_page(IDX[k]);
1754da7f033dSHerbert Xu 
175592a4c9feSEric Biggers 			if (memcmp(q, result + temp, template[i].tap[k])) {
175608d6af8cSJussi Kivilinna 				pr_err("alg: skcipher%s: Chunk test %d failed on %s at page %u for %s\n",
175708d6af8cSJussi Kivilinna 				       d, j, e, k, algo);
1758da7f033dSHerbert Xu 				hexdump(q, template[i].tap[k]);
1759da7f033dSHerbert Xu 				goto out;
1760da7f033dSHerbert Xu 			}
1761da7f033dSHerbert Xu 
1762da7f033dSHerbert Xu 			q += template[i].tap[k];
1763da7f033dSHerbert Xu 			for (n = 0; offset_in_page(q + n) && q[n]; n++)
1764da7f033dSHerbert Xu 				;
1765da7f033dSHerbert Xu 			if (n) {
176608d6af8cSJussi Kivilinna 				pr_err("alg: skcipher%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
176708d6af8cSJussi Kivilinna 				       d, j, e, k, algo, n);
1768da7f033dSHerbert Xu 				hexdump(q, n);
1769da7f033dSHerbert Xu 				goto out;
1770da7f033dSHerbert Xu 			}
1771da7f033dSHerbert Xu 			temp += template[i].tap[k];
1772da7f033dSHerbert Xu 		}
1773da7f033dSHerbert Xu 	}
1774da7f033dSHerbert Xu 
1775da7f033dSHerbert Xu 	ret = 0;
1776da7f033dSHerbert Xu 
1777da7f033dSHerbert Xu out:
177812773d93SHerbert Xu 	skcipher_request_free(req);
177908d6af8cSJussi Kivilinna 	if (diff_dst)
178008d6af8cSJussi Kivilinna 		testmgr_free_buf(xoutbuf);
178108d6af8cSJussi Kivilinna out_nooutbuf:
1782f8b0d4d0SHerbert Xu 	testmgr_free_buf(xbuf);
1783f8b0d4d0SHerbert Xu out_nobuf:
1784da7f033dSHerbert Xu 	return ret;
1785da7f033dSHerbert Xu }
1786da7f033dSHerbert Xu 
178712773d93SHerbert Xu static int test_skcipher(struct crypto_skcipher *tfm, int enc,
1788b13b1e0cSEric Biggers 			 const struct cipher_testvec *template,
1789b13b1e0cSEric Biggers 			 unsigned int tcount)
179008d6af8cSJussi Kivilinna {
17913a338f20SJussi Kivilinna 	unsigned int alignmask;
179208d6af8cSJussi Kivilinna 	int ret;
179308d6af8cSJussi Kivilinna 
179408d6af8cSJussi Kivilinna 	/* test 'dst == src' case */
17953a338f20SJussi Kivilinna 	ret = __test_skcipher(tfm, enc, template, tcount, false, 0);
179608d6af8cSJussi Kivilinna 	if (ret)
179708d6af8cSJussi Kivilinna 		return ret;
179808d6af8cSJussi Kivilinna 
179908d6af8cSJussi Kivilinna 	/* test 'dst != src' case */
18003a338f20SJussi Kivilinna 	ret = __test_skcipher(tfm, enc, template, tcount, true, 0);
18013a338f20SJussi Kivilinna 	if (ret)
18023a338f20SJussi Kivilinna 		return ret;
18033a338f20SJussi Kivilinna 
18043a338f20SJussi Kivilinna 	/* test unaligned buffers, check with one byte offset */
18053a338f20SJussi Kivilinna 	ret = __test_skcipher(tfm, enc, template, tcount, true, 1);
18063a338f20SJussi Kivilinna 	if (ret)
18073a338f20SJussi Kivilinna 		return ret;
18083a338f20SJussi Kivilinna 
18093a338f20SJussi Kivilinna 	alignmask = crypto_tfm_alg_alignmask(&tfm->base);
18103a338f20SJussi Kivilinna 	if (alignmask) {
18113a338f20SJussi Kivilinna 		/* Check if alignment mask for tfm is correctly set. */
18123a338f20SJussi Kivilinna 		ret = __test_skcipher(tfm, enc, template, tcount, true,
18133a338f20SJussi Kivilinna 				      alignmask + 1);
18143a338f20SJussi Kivilinna 		if (ret)
18153a338f20SJussi Kivilinna 			return ret;
18163a338f20SJussi Kivilinna 	}
18173a338f20SJussi Kivilinna 
18183a338f20SJussi Kivilinna 	return 0;
181908d6af8cSJussi Kivilinna }
182008d6af8cSJussi Kivilinna 
1821b13b1e0cSEric Biggers static int test_comp(struct crypto_comp *tfm,
1822b13b1e0cSEric Biggers 		     const struct comp_testvec *ctemplate,
1823b13b1e0cSEric Biggers 		     const struct comp_testvec *dtemplate,
1824b13b1e0cSEric Biggers 		     int ctcount, int dtcount)
1825da7f033dSHerbert Xu {
1826da7f033dSHerbert Xu 	const char *algo = crypto_tfm_alg_driver_name(crypto_comp_tfm(tfm));
182733607384SMahipal Challa 	char *output, *decomp_output;
1828da7f033dSHerbert Xu 	unsigned int i;
1829da7f033dSHerbert Xu 	int ret;
1830da7f033dSHerbert Xu 
183133607384SMahipal Challa 	output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
183233607384SMahipal Challa 	if (!output)
183333607384SMahipal Challa 		return -ENOMEM;
183433607384SMahipal Challa 
183533607384SMahipal Challa 	decomp_output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
183633607384SMahipal Challa 	if (!decomp_output) {
183733607384SMahipal Challa 		kfree(output);
183833607384SMahipal Challa 		return -ENOMEM;
183933607384SMahipal Challa 	}
184033607384SMahipal Challa 
1841da7f033dSHerbert Xu 	for (i = 0; i < ctcount; i++) {
1842c79cf910SGeert Uytterhoeven 		int ilen;
1843c79cf910SGeert Uytterhoeven 		unsigned int dlen = COMP_BUF_SIZE;
1844da7f033dSHerbert Xu 
184522a8118dSMichael Schupikov 		memset(output, 0, COMP_BUF_SIZE);
184622a8118dSMichael Schupikov 		memset(decomp_output, 0, COMP_BUF_SIZE);
1847da7f033dSHerbert Xu 
1848da7f033dSHerbert Xu 		ilen = ctemplate[i].inlen;
1849da7f033dSHerbert Xu 		ret = crypto_comp_compress(tfm, ctemplate[i].input,
185033607384SMahipal Challa 					   ilen, output, &dlen);
1851da7f033dSHerbert Xu 		if (ret) {
1852da7f033dSHerbert Xu 			printk(KERN_ERR "alg: comp: compression failed "
1853da7f033dSHerbert Xu 			       "on test %d for %s: ret=%d\n", i + 1, algo,
1854da7f033dSHerbert Xu 			       -ret);
1855da7f033dSHerbert Xu 			goto out;
1856da7f033dSHerbert Xu 		}
1857da7f033dSHerbert Xu 
185833607384SMahipal Challa 		ilen = dlen;
185933607384SMahipal Challa 		dlen = COMP_BUF_SIZE;
186033607384SMahipal Challa 		ret = crypto_comp_decompress(tfm, output,
186133607384SMahipal Challa 					     ilen, decomp_output, &dlen);
186233607384SMahipal Challa 		if (ret) {
186333607384SMahipal Challa 			pr_err("alg: comp: compression failed: decompress: on test %d for %s failed: ret=%d\n",
186433607384SMahipal Challa 			       i + 1, algo, -ret);
186533607384SMahipal Challa 			goto out;
186633607384SMahipal Challa 		}
186733607384SMahipal Challa 
186833607384SMahipal Challa 		if (dlen != ctemplate[i].inlen) {
1869b812eb00SGeert Uytterhoeven 			printk(KERN_ERR "alg: comp: Compression test %d "
1870b812eb00SGeert Uytterhoeven 			       "failed for %s: output len = %d\n", i + 1, algo,
1871b812eb00SGeert Uytterhoeven 			       dlen);
1872b812eb00SGeert Uytterhoeven 			ret = -EINVAL;
1873b812eb00SGeert Uytterhoeven 			goto out;
1874b812eb00SGeert Uytterhoeven 		}
1875b812eb00SGeert Uytterhoeven 
187633607384SMahipal Challa 		if (memcmp(decomp_output, ctemplate[i].input,
187733607384SMahipal Challa 			   ctemplate[i].inlen)) {
187833607384SMahipal Challa 			pr_err("alg: comp: compression failed: output differs: on test %d for %s\n",
187933607384SMahipal Challa 			       i + 1, algo);
188033607384SMahipal Challa 			hexdump(decomp_output, dlen);
1881da7f033dSHerbert Xu 			ret = -EINVAL;
1882da7f033dSHerbert Xu 			goto out;
1883da7f033dSHerbert Xu 		}
1884da7f033dSHerbert Xu 	}
1885da7f033dSHerbert Xu 
1886da7f033dSHerbert Xu 	for (i = 0; i < dtcount; i++) {
1887c79cf910SGeert Uytterhoeven 		int ilen;
1888c79cf910SGeert Uytterhoeven 		unsigned int dlen = COMP_BUF_SIZE;
1889da7f033dSHerbert Xu 
189022a8118dSMichael Schupikov 		memset(decomp_output, 0, COMP_BUF_SIZE);
1891da7f033dSHerbert Xu 
1892da7f033dSHerbert Xu 		ilen = dtemplate[i].inlen;
1893da7f033dSHerbert Xu 		ret = crypto_comp_decompress(tfm, dtemplate[i].input,
189433607384SMahipal Challa 					     ilen, decomp_output, &dlen);
1895da7f033dSHerbert Xu 		if (ret) {
1896da7f033dSHerbert Xu 			printk(KERN_ERR "alg: comp: decompression failed "
1897da7f033dSHerbert Xu 			       "on test %d for %s: ret=%d\n", i + 1, algo,
1898da7f033dSHerbert Xu 			       -ret);
1899da7f033dSHerbert Xu 			goto out;
1900da7f033dSHerbert Xu 		}
1901da7f033dSHerbert Xu 
1902b812eb00SGeert Uytterhoeven 		if (dlen != dtemplate[i].outlen) {
1903b812eb00SGeert Uytterhoeven 			printk(KERN_ERR "alg: comp: Decompression test %d "
1904b812eb00SGeert Uytterhoeven 			       "failed for %s: output len = %d\n", i + 1, algo,
1905b812eb00SGeert Uytterhoeven 			       dlen);
1906b812eb00SGeert Uytterhoeven 			ret = -EINVAL;
1907b812eb00SGeert Uytterhoeven 			goto out;
1908b812eb00SGeert Uytterhoeven 		}
1909b812eb00SGeert Uytterhoeven 
191033607384SMahipal Challa 		if (memcmp(decomp_output, dtemplate[i].output, dlen)) {
1911da7f033dSHerbert Xu 			printk(KERN_ERR "alg: comp: Decompression test %d "
1912da7f033dSHerbert Xu 			       "failed for %s\n", i + 1, algo);
191333607384SMahipal Challa 			hexdump(decomp_output, dlen);
1914da7f033dSHerbert Xu 			ret = -EINVAL;
1915da7f033dSHerbert Xu 			goto out;
1916da7f033dSHerbert Xu 		}
1917da7f033dSHerbert Xu 	}
1918da7f033dSHerbert Xu 
1919da7f033dSHerbert Xu 	ret = 0;
1920da7f033dSHerbert Xu 
1921da7f033dSHerbert Xu out:
192233607384SMahipal Challa 	kfree(decomp_output);
192333607384SMahipal Challa 	kfree(output);
1924da7f033dSHerbert Xu 	return ret;
1925da7f033dSHerbert Xu }
1926da7f033dSHerbert Xu 
1927b13b1e0cSEric Biggers static int test_acomp(struct crypto_acomp *tfm,
1928b13b1e0cSEric Biggers 			      const struct comp_testvec *ctemplate,
1929b13b1e0cSEric Biggers 		      const struct comp_testvec *dtemplate,
1930b13b1e0cSEric Biggers 		      int ctcount, int dtcount)
1931d7db7a88SGiovanni Cabiddu {
1932d7db7a88SGiovanni Cabiddu 	const char *algo = crypto_tfm_alg_driver_name(crypto_acomp_tfm(tfm));
1933d7db7a88SGiovanni Cabiddu 	unsigned int i;
1934a9943a0aSGiovanni Cabiddu 	char *output, *decomp_out;
1935d7db7a88SGiovanni Cabiddu 	int ret;
1936d7db7a88SGiovanni Cabiddu 	struct scatterlist src, dst;
1937d7db7a88SGiovanni Cabiddu 	struct acomp_req *req;
19387f397136SGilad Ben-Yossef 	struct crypto_wait wait;
1939d7db7a88SGiovanni Cabiddu 
1940eb095593SEric Biggers 	output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
1941eb095593SEric Biggers 	if (!output)
1942eb095593SEric Biggers 		return -ENOMEM;
1943eb095593SEric Biggers 
1944a9943a0aSGiovanni Cabiddu 	decomp_out = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
1945a9943a0aSGiovanni Cabiddu 	if (!decomp_out) {
1946a9943a0aSGiovanni Cabiddu 		kfree(output);
1947a9943a0aSGiovanni Cabiddu 		return -ENOMEM;
1948a9943a0aSGiovanni Cabiddu 	}
1949a9943a0aSGiovanni Cabiddu 
1950d7db7a88SGiovanni Cabiddu 	for (i = 0; i < ctcount; i++) {
1951d7db7a88SGiovanni Cabiddu 		unsigned int dlen = COMP_BUF_SIZE;
1952d7db7a88SGiovanni Cabiddu 		int ilen = ctemplate[i].inlen;
195302608e02SLaura Abbott 		void *input_vec;
1954d7db7a88SGiovanni Cabiddu 
1955d2110224SEric Biggers 		input_vec = kmemdup(ctemplate[i].input, ilen, GFP_KERNEL);
195602608e02SLaura Abbott 		if (!input_vec) {
195702608e02SLaura Abbott 			ret = -ENOMEM;
195802608e02SLaura Abbott 			goto out;
195902608e02SLaura Abbott 		}
196002608e02SLaura Abbott 
1961eb095593SEric Biggers 		memset(output, 0, dlen);
19627f397136SGilad Ben-Yossef 		crypto_init_wait(&wait);
196302608e02SLaura Abbott 		sg_init_one(&src, input_vec, ilen);
1964d7db7a88SGiovanni Cabiddu 		sg_init_one(&dst, output, dlen);
1965d7db7a88SGiovanni Cabiddu 
1966d7db7a88SGiovanni Cabiddu 		req = acomp_request_alloc(tfm);
1967d7db7a88SGiovanni Cabiddu 		if (!req) {
1968d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: request alloc failed for %s\n",
1969d7db7a88SGiovanni Cabiddu 			       algo);
197002608e02SLaura Abbott 			kfree(input_vec);
1971d7db7a88SGiovanni Cabiddu 			ret = -ENOMEM;
1972d7db7a88SGiovanni Cabiddu 			goto out;
1973d7db7a88SGiovanni Cabiddu 		}
1974d7db7a88SGiovanni Cabiddu 
1975d7db7a88SGiovanni Cabiddu 		acomp_request_set_params(req, &src, &dst, ilen, dlen);
1976d7db7a88SGiovanni Cabiddu 		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
19777f397136SGilad Ben-Yossef 					   crypto_req_done, &wait);
1978d7db7a88SGiovanni Cabiddu 
19797f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_acomp_compress(req), &wait);
1980d7db7a88SGiovanni Cabiddu 		if (ret) {
1981d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
1982d7db7a88SGiovanni Cabiddu 			       i + 1, algo, -ret);
198302608e02SLaura Abbott 			kfree(input_vec);
1984d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
1985d7db7a88SGiovanni Cabiddu 			goto out;
1986d7db7a88SGiovanni Cabiddu 		}
1987d7db7a88SGiovanni Cabiddu 
1988a9943a0aSGiovanni Cabiddu 		ilen = req->dlen;
1989a9943a0aSGiovanni Cabiddu 		dlen = COMP_BUF_SIZE;
1990a9943a0aSGiovanni Cabiddu 		sg_init_one(&src, output, ilen);
1991a9943a0aSGiovanni Cabiddu 		sg_init_one(&dst, decomp_out, dlen);
19927f397136SGilad Ben-Yossef 		crypto_init_wait(&wait);
1993a9943a0aSGiovanni Cabiddu 		acomp_request_set_params(req, &src, &dst, ilen, dlen);
1994a9943a0aSGiovanni Cabiddu 
19957f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
1996a9943a0aSGiovanni Cabiddu 		if (ret) {
1997a9943a0aSGiovanni Cabiddu 			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
1998a9943a0aSGiovanni Cabiddu 			       i + 1, algo, -ret);
1999a9943a0aSGiovanni Cabiddu 			kfree(input_vec);
2000a9943a0aSGiovanni Cabiddu 			acomp_request_free(req);
2001a9943a0aSGiovanni Cabiddu 			goto out;
2002a9943a0aSGiovanni Cabiddu 		}
2003a9943a0aSGiovanni Cabiddu 
2004a9943a0aSGiovanni Cabiddu 		if (req->dlen != ctemplate[i].inlen) {
2005d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Compression test %d failed for %s: output len = %d\n",
2006d7db7a88SGiovanni Cabiddu 			       i + 1, algo, req->dlen);
2007d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
200802608e02SLaura Abbott 			kfree(input_vec);
2009d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2010d7db7a88SGiovanni Cabiddu 			goto out;
2011d7db7a88SGiovanni Cabiddu 		}
2012d7db7a88SGiovanni Cabiddu 
2013a9943a0aSGiovanni Cabiddu 		if (memcmp(input_vec, decomp_out, req->dlen)) {
2014d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Compression test %d failed for %s\n",
2015d7db7a88SGiovanni Cabiddu 			       i + 1, algo);
2016d7db7a88SGiovanni Cabiddu 			hexdump(output, req->dlen);
2017d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
201802608e02SLaura Abbott 			kfree(input_vec);
2019d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2020d7db7a88SGiovanni Cabiddu 			goto out;
2021d7db7a88SGiovanni Cabiddu 		}
2022d7db7a88SGiovanni Cabiddu 
202302608e02SLaura Abbott 		kfree(input_vec);
2024d7db7a88SGiovanni Cabiddu 		acomp_request_free(req);
2025d7db7a88SGiovanni Cabiddu 	}
2026d7db7a88SGiovanni Cabiddu 
2027d7db7a88SGiovanni Cabiddu 	for (i = 0; i < dtcount; i++) {
2028d7db7a88SGiovanni Cabiddu 		unsigned int dlen = COMP_BUF_SIZE;
2029d7db7a88SGiovanni Cabiddu 		int ilen = dtemplate[i].inlen;
203002608e02SLaura Abbott 		void *input_vec;
2031d7db7a88SGiovanni Cabiddu 
2032d2110224SEric Biggers 		input_vec = kmemdup(dtemplate[i].input, ilen, GFP_KERNEL);
203302608e02SLaura Abbott 		if (!input_vec) {
203402608e02SLaura Abbott 			ret = -ENOMEM;
203502608e02SLaura Abbott 			goto out;
203602608e02SLaura Abbott 		}
203702608e02SLaura Abbott 
2038eb095593SEric Biggers 		memset(output, 0, dlen);
20397f397136SGilad Ben-Yossef 		crypto_init_wait(&wait);
204002608e02SLaura Abbott 		sg_init_one(&src, input_vec, ilen);
2041d7db7a88SGiovanni Cabiddu 		sg_init_one(&dst, output, dlen);
2042d7db7a88SGiovanni Cabiddu 
2043d7db7a88SGiovanni Cabiddu 		req = acomp_request_alloc(tfm);
2044d7db7a88SGiovanni Cabiddu 		if (!req) {
2045d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: request alloc failed for %s\n",
2046d7db7a88SGiovanni Cabiddu 			       algo);
204702608e02SLaura Abbott 			kfree(input_vec);
2048d7db7a88SGiovanni Cabiddu 			ret = -ENOMEM;
2049d7db7a88SGiovanni Cabiddu 			goto out;
2050d7db7a88SGiovanni Cabiddu 		}
2051d7db7a88SGiovanni Cabiddu 
2052d7db7a88SGiovanni Cabiddu 		acomp_request_set_params(req, &src, &dst, ilen, dlen);
2053d7db7a88SGiovanni Cabiddu 		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
20547f397136SGilad Ben-Yossef 					   crypto_req_done, &wait);
2055d7db7a88SGiovanni Cabiddu 
20567f397136SGilad Ben-Yossef 		ret = crypto_wait_req(crypto_acomp_decompress(req), &wait);
2057d7db7a88SGiovanni Cabiddu 		if (ret) {
2058d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: decompression failed on test %d for %s: ret=%d\n",
2059d7db7a88SGiovanni Cabiddu 			       i + 1, algo, -ret);
206002608e02SLaura Abbott 			kfree(input_vec);
2061d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2062d7db7a88SGiovanni Cabiddu 			goto out;
2063d7db7a88SGiovanni Cabiddu 		}
2064d7db7a88SGiovanni Cabiddu 
2065d7db7a88SGiovanni Cabiddu 		if (req->dlen != dtemplate[i].outlen) {
2066d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Decompression test %d failed for %s: output len = %d\n",
2067d7db7a88SGiovanni Cabiddu 			       i + 1, algo, req->dlen);
2068d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
206902608e02SLaura Abbott 			kfree(input_vec);
2070d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2071d7db7a88SGiovanni Cabiddu 			goto out;
2072d7db7a88SGiovanni Cabiddu 		}
2073d7db7a88SGiovanni Cabiddu 
2074d7db7a88SGiovanni Cabiddu 		if (memcmp(output, dtemplate[i].output, req->dlen)) {
2075d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Decompression test %d failed for %s\n",
2076d7db7a88SGiovanni Cabiddu 			       i + 1, algo);
2077d7db7a88SGiovanni Cabiddu 			hexdump(output, req->dlen);
2078d7db7a88SGiovanni Cabiddu 			ret = -EINVAL;
207902608e02SLaura Abbott 			kfree(input_vec);
2080d7db7a88SGiovanni Cabiddu 			acomp_request_free(req);
2081d7db7a88SGiovanni Cabiddu 			goto out;
2082d7db7a88SGiovanni Cabiddu 		}
2083d7db7a88SGiovanni Cabiddu 
208402608e02SLaura Abbott 		kfree(input_vec);
2085d7db7a88SGiovanni Cabiddu 		acomp_request_free(req);
2086d7db7a88SGiovanni Cabiddu 	}
2087d7db7a88SGiovanni Cabiddu 
2088d7db7a88SGiovanni Cabiddu 	ret = 0;
2089d7db7a88SGiovanni Cabiddu 
2090d7db7a88SGiovanni Cabiddu out:
2091a9943a0aSGiovanni Cabiddu 	kfree(decomp_out);
2092eb095593SEric Biggers 	kfree(output);
2093d7db7a88SGiovanni Cabiddu 	return ret;
2094d7db7a88SGiovanni Cabiddu }
2095d7db7a88SGiovanni Cabiddu 
2096b13b1e0cSEric Biggers static int test_cprng(struct crypto_rng *tfm,
2097b13b1e0cSEric Biggers 		      const struct cprng_testvec *template,
20987647d6ceSJarod Wilson 		      unsigned int tcount)
20997647d6ceSJarod Wilson {
21007647d6ceSJarod Wilson 	const char *algo = crypto_tfm_alg_driver_name(crypto_rng_tfm(tfm));
2101fa4ef8a6SFelipe Contreras 	int err = 0, i, j, seedsize;
21027647d6ceSJarod Wilson 	u8 *seed;
21037647d6ceSJarod Wilson 	char result[32];
21047647d6ceSJarod Wilson 
21057647d6ceSJarod Wilson 	seedsize = crypto_rng_seedsize(tfm);
21067647d6ceSJarod Wilson 
21077647d6ceSJarod Wilson 	seed = kmalloc(seedsize, GFP_KERNEL);
21087647d6ceSJarod Wilson 	if (!seed) {
21097647d6ceSJarod Wilson 		printk(KERN_ERR "alg: cprng: Failed to allocate seed space "
21107647d6ceSJarod Wilson 		       "for %s\n", algo);
21117647d6ceSJarod Wilson 		return -ENOMEM;
21127647d6ceSJarod Wilson 	}
21137647d6ceSJarod Wilson 
21147647d6ceSJarod Wilson 	for (i = 0; i < tcount; i++) {
21157647d6ceSJarod Wilson 		memset(result, 0, 32);
21167647d6ceSJarod Wilson 
21177647d6ceSJarod Wilson 		memcpy(seed, template[i].v, template[i].vlen);
21187647d6ceSJarod Wilson 		memcpy(seed + template[i].vlen, template[i].key,
21197647d6ceSJarod Wilson 		       template[i].klen);
21207647d6ceSJarod Wilson 		memcpy(seed + template[i].vlen + template[i].klen,
21217647d6ceSJarod Wilson 		       template[i].dt, template[i].dtlen);
21227647d6ceSJarod Wilson 
21237647d6ceSJarod Wilson 		err = crypto_rng_reset(tfm, seed, seedsize);
21247647d6ceSJarod Wilson 		if (err) {
21257647d6ceSJarod Wilson 			printk(KERN_ERR "alg: cprng: Failed to reset rng "
21267647d6ceSJarod Wilson 			       "for %s\n", algo);
21277647d6ceSJarod Wilson 			goto out;
21287647d6ceSJarod Wilson 		}
21297647d6ceSJarod Wilson 
21307647d6ceSJarod Wilson 		for (j = 0; j < template[i].loops; j++) {
21317647d6ceSJarod Wilson 			err = crypto_rng_get_bytes(tfm, result,
21327647d6ceSJarod Wilson 						   template[i].rlen);
213319e60e13SStephan Mueller 			if (err < 0) {
21347647d6ceSJarod Wilson 				printk(KERN_ERR "alg: cprng: Failed to obtain "
21357647d6ceSJarod Wilson 				       "the correct amount of random data for "
213619e60e13SStephan Mueller 				       "%s (requested %d)\n", algo,
213719e60e13SStephan Mueller 				       template[i].rlen);
21387647d6ceSJarod Wilson 				goto out;
21397647d6ceSJarod Wilson 			}
21407647d6ceSJarod Wilson 		}
21417647d6ceSJarod Wilson 
21427647d6ceSJarod Wilson 		err = memcmp(result, template[i].result,
21437647d6ceSJarod Wilson 			     template[i].rlen);
21447647d6ceSJarod Wilson 		if (err) {
21457647d6ceSJarod Wilson 			printk(KERN_ERR "alg: cprng: Test %d failed for %s\n",
21467647d6ceSJarod Wilson 			       i, algo);
21477647d6ceSJarod Wilson 			hexdump(result, template[i].rlen);
21487647d6ceSJarod Wilson 			err = -EINVAL;
21497647d6ceSJarod Wilson 			goto out;
21507647d6ceSJarod Wilson 		}
21517647d6ceSJarod Wilson 	}
21527647d6ceSJarod Wilson 
21537647d6ceSJarod Wilson out:
21547647d6ceSJarod Wilson 	kfree(seed);
21557647d6ceSJarod Wilson 	return err;
21567647d6ceSJarod Wilson }
21577647d6ceSJarod Wilson 
2158da7f033dSHerbert Xu static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
2159da7f033dSHerbert Xu 			 u32 type, u32 mask)
2160da7f033dSHerbert Xu {
2161a0d608eeSEric Biggers 	const struct aead_test_suite *suite = &desc->suite.aead;
2162da7f033dSHerbert Xu 	struct crypto_aead *tfm;
2163a0d608eeSEric Biggers 	int err;
2164da7f033dSHerbert Xu 
2165eed93e0cSHerbert Xu 	tfm = crypto_alloc_aead(driver, type, mask);
2166da7f033dSHerbert Xu 	if (IS_ERR(tfm)) {
2167da7f033dSHerbert Xu 		printk(KERN_ERR "alg: aead: Failed to load transform for %s: "
2168da7f033dSHerbert Xu 		       "%ld\n", driver, PTR_ERR(tfm));
2169da7f033dSHerbert Xu 		return PTR_ERR(tfm);
2170da7f033dSHerbert Xu 	}
2171da7f033dSHerbert Xu 
2172a0d608eeSEric Biggers 	err = test_aead(tfm, ENCRYPT, suite->vecs, suite->count);
2173a0d608eeSEric Biggers 	if (!err)
2174a0d608eeSEric Biggers 		err = test_aead(tfm, DECRYPT, suite->vecs, suite->count);
2175da7f033dSHerbert Xu 
2176da7f033dSHerbert Xu 	crypto_free_aead(tfm);
2177da7f033dSHerbert Xu 	return err;
2178da7f033dSHerbert Xu }
2179da7f033dSHerbert Xu 
2180da7f033dSHerbert Xu static int alg_test_cipher(const struct alg_test_desc *desc,
2181da7f033dSHerbert Xu 			   const char *driver, u32 type, u32 mask)
2182da7f033dSHerbert Xu {
218392a4c9feSEric Biggers 	const struct cipher_test_suite *suite = &desc->suite.cipher;
21841aa4ecd9SHerbert Xu 	struct crypto_cipher *tfm;
218592a4c9feSEric Biggers 	int err;
2186da7f033dSHerbert Xu 
2187eed93e0cSHerbert Xu 	tfm = crypto_alloc_cipher(driver, type, mask);
2188da7f033dSHerbert Xu 	if (IS_ERR(tfm)) {
2189da7f033dSHerbert Xu 		printk(KERN_ERR "alg: cipher: Failed to load transform for "
2190da7f033dSHerbert Xu 		       "%s: %ld\n", driver, PTR_ERR(tfm));
2191da7f033dSHerbert Xu 		return PTR_ERR(tfm);
2192da7f033dSHerbert Xu 	}
2193da7f033dSHerbert Xu 
219492a4c9feSEric Biggers 	err = test_cipher(tfm, ENCRYPT, suite->vecs, suite->count);
219592a4c9feSEric Biggers 	if (!err)
219692a4c9feSEric Biggers 		err = test_cipher(tfm, DECRYPT, suite->vecs, suite->count);
2197da7f033dSHerbert Xu 
21981aa4ecd9SHerbert Xu 	crypto_free_cipher(tfm);
21991aa4ecd9SHerbert Xu 	return err;
22001aa4ecd9SHerbert Xu }
22011aa4ecd9SHerbert Xu 
22021aa4ecd9SHerbert Xu static int alg_test_skcipher(const struct alg_test_desc *desc,
22031aa4ecd9SHerbert Xu 			     const char *driver, u32 type, u32 mask)
22041aa4ecd9SHerbert Xu {
220592a4c9feSEric Biggers 	const struct cipher_test_suite *suite = &desc->suite.cipher;
220612773d93SHerbert Xu 	struct crypto_skcipher *tfm;
220792a4c9feSEric Biggers 	int err;
22081aa4ecd9SHerbert Xu 
2209eed93e0cSHerbert Xu 	tfm = crypto_alloc_skcipher(driver, type, mask);
22101aa4ecd9SHerbert Xu 	if (IS_ERR(tfm)) {
22111aa4ecd9SHerbert Xu 		printk(KERN_ERR "alg: skcipher: Failed to load transform for "
22121aa4ecd9SHerbert Xu 		       "%s: %ld\n", driver, PTR_ERR(tfm));
22131aa4ecd9SHerbert Xu 		return PTR_ERR(tfm);
22141aa4ecd9SHerbert Xu 	}
22151aa4ecd9SHerbert Xu 
221692a4c9feSEric Biggers 	err = test_skcipher(tfm, ENCRYPT, suite->vecs, suite->count);
221792a4c9feSEric Biggers 	if (!err)
221892a4c9feSEric Biggers 		err = test_skcipher(tfm, DECRYPT, suite->vecs, suite->count);
22191aa4ecd9SHerbert Xu 
222012773d93SHerbert Xu 	crypto_free_skcipher(tfm);
2221da7f033dSHerbert Xu 	return err;
2222da7f033dSHerbert Xu }
2223da7f033dSHerbert Xu 
2224da7f033dSHerbert Xu static int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
2225da7f033dSHerbert Xu 			 u32 type, u32 mask)
2226da7f033dSHerbert Xu {
2227d7db7a88SGiovanni Cabiddu 	struct crypto_comp *comp;
2228d7db7a88SGiovanni Cabiddu 	struct crypto_acomp *acomp;
2229da7f033dSHerbert Xu 	int err;
2230d7db7a88SGiovanni Cabiddu 	u32 algo_type = type & CRYPTO_ALG_TYPE_ACOMPRESS_MASK;
2231da7f033dSHerbert Xu 
2232d7db7a88SGiovanni Cabiddu 	if (algo_type == CRYPTO_ALG_TYPE_ACOMPRESS) {
2233d7db7a88SGiovanni Cabiddu 		acomp = crypto_alloc_acomp(driver, type, mask);
2234d7db7a88SGiovanni Cabiddu 		if (IS_ERR(acomp)) {
2235d7db7a88SGiovanni Cabiddu 			pr_err("alg: acomp: Failed to load transform for %s: %ld\n",
2236d7db7a88SGiovanni Cabiddu 			       driver, PTR_ERR(acomp));
2237d7db7a88SGiovanni Cabiddu 			return PTR_ERR(acomp);
2238d7db7a88SGiovanni Cabiddu 		}
2239d7db7a88SGiovanni Cabiddu 		err = test_acomp(acomp, desc->suite.comp.comp.vecs,
2240d7db7a88SGiovanni Cabiddu 				 desc->suite.comp.decomp.vecs,
2241d7db7a88SGiovanni Cabiddu 				 desc->suite.comp.comp.count,
2242d7db7a88SGiovanni Cabiddu 				 desc->suite.comp.decomp.count);
2243d7db7a88SGiovanni Cabiddu 		crypto_free_acomp(acomp);
2244d7db7a88SGiovanni Cabiddu 	} else {
2245d7db7a88SGiovanni Cabiddu 		comp = crypto_alloc_comp(driver, type, mask);
2246d7db7a88SGiovanni Cabiddu 		if (IS_ERR(comp)) {
2247d7db7a88SGiovanni Cabiddu 			pr_err("alg: comp: Failed to load transform for %s: %ld\n",
2248d7db7a88SGiovanni Cabiddu 			       driver, PTR_ERR(comp));
2249d7db7a88SGiovanni Cabiddu 			return PTR_ERR(comp);
2250da7f033dSHerbert Xu 		}
2251da7f033dSHerbert Xu 
2252d7db7a88SGiovanni Cabiddu 		err = test_comp(comp, desc->suite.comp.comp.vecs,
2253da7f033dSHerbert Xu 				desc->suite.comp.decomp.vecs,
2254da7f033dSHerbert Xu 				desc->suite.comp.comp.count,
2255da7f033dSHerbert Xu 				desc->suite.comp.decomp.count);
2256da7f033dSHerbert Xu 
2257d7db7a88SGiovanni Cabiddu 		crypto_free_comp(comp);
2258d7db7a88SGiovanni Cabiddu 	}
2259da7f033dSHerbert Xu 	return err;
2260da7f033dSHerbert Xu }
2261da7f033dSHerbert Xu 
22629b3abc01SEric Biggers static int __alg_test_hash(const struct hash_testvec *template,
22639b3abc01SEric Biggers 			   unsigned int tcount, const char *driver,
2264da7f033dSHerbert Xu 			   u32 type, u32 mask)
2265da7f033dSHerbert Xu {
2266da7f033dSHerbert Xu 	struct crypto_ahash *tfm;
2267da7f033dSHerbert Xu 	int err;
2268da7f033dSHerbert Xu 
2269eed93e0cSHerbert Xu 	tfm = crypto_alloc_ahash(driver, type, mask);
2270da7f033dSHerbert Xu 	if (IS_ERR(tfm)) {
2271da7f033dSHerbert Xu 		printk(KERN_ERR "alg: hash: Failed to load transform for %s: "
2272da7f033dSHerbert Xu 		       "%ld\n", driver, PTR_ERR(tfm));
2273da7f033dSHerbert Xu 		return PTR_ERR(tfm);
2274da7f033dSHerbert Xu 	}
2275da7f033dSHerbert Xu 
227676715095SGilad Ben-Yossef 	err = test_hash(tfm, template, tcount, HASH_TEST_DIGEST);
2277a8f1a052SDavid S. Miller 	if (!err)
227876715095SGilad Ben-Yossef 		err = test_hash(tfm, template, tcount, HASH_TEST_FINAL);
227976715095SGilad Ben-Yossef 	if (!err)
228076715095SGilad Ben-Yossef 		err = test_hash(tfm, template, tcount, HASH_TEST_FINUP);
2281da7f033dSHerbert Xu 	crypto_free_ahash(tfm);
2282da7f033dSHerbert Xu 	return err;
2283da7f033dSHerbert Xu }
2284da7f033dSHerbert Xu 
22859b3abc01SEric Biggers static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
22869b3abc01SEric Biggers 			 u32 type, u32 mask)
22879b3abc01SEric Biggers {
22889b3abc01SEric Biggers 	const struct hash_testvec *template = desc->suite.hash.vecs;
22899b3abc01SEric Biggers 	unsigned int tcount = desc->suite.hash.count;
22909b3abc01SEric Biggers 	unsigned int nr_unkeyed, nr_keyed;
22919b3abc01SEric Biggers 	int err;
22929b3abc01SEric Biggers 
22939b3abc01SEric Biggers 	/*
22949b3abc01SEric Biggers 	 * For OPTIONAL_KEY algorithms, we have to do all the unkeyed tests
22959b3abc01SEric Biggers 	 * first, before setting a key on the tfm.  To make this easier, we
22969b3abc01SEric Biggers 	 * require that the unkeyed test vectors (if any) are listed first.
22979b3abc01SEric Biggers 	 */
22989b3abc01SEric Biggers 
22999b3abc01SEric Biggers 	for (nr_unkeyed = 0; nr_unkeyed < tcount; nr_unkeyed++) {
23009b3abc01SEric Biggers 		if (template[nr_unkeyed].ksize)
23019b3abc01SEric Biggers 			break;
23029b3abc01SEric Biggers 	}
23039b3abc01SEric Biggers 	for (nr_keyed = 0; nr_unkeyed + nr_keyed < tcount; nr_keyed++) {
23049b3abc01SEric Biggers 		if (!template[nr_unkeyed + nr_keyed].ksize) {
23059b3abc01SEric Biggers 			pr_err("alg: hash: test vectors for %s out of order, "
23069b3abc01SEric Biggers 			       "unkeyed ones must come first\n", desc->alg);
23079b3abc01SEric Biggers 			return -EINVAL;
23089b3abc01SEric Biggers 		}
23099b3abc01SEric Biggers 	}
23109b3abc01SEric Biggers 
23119b3abc01SEric Biggers 	err = 0;
23129b3abc01SEric Biggers 	if (nr_unkeyed) {
23139b3abc01SEric Biggers 		err = __alg_test_hash(template, nr_unkeyed, driver, type, mask);
23149b3abc01SEric Biggers 		template += nr_unkeyed;
23159b3abc01SEric Biggers 	}
23169b3abc01SEric Biggers 
23179b3abc01SEric Biggers 	if (!err && nr_keyed)
23189b3abc01SEric Biggers 		err = __alg_test_hash(template, nr_keyed, driver, type, mask);
23199b3abc01SEric Biggers 
23209b3abc01SEric Biggers 	return err;
23219b3abc01SEric Biggers }
23229b3abc01SEric Biggers 
23238e3ee85eSHerbert Xu static int alg_test_crc32c(const struct alg_test_desc *desc,
23248e3ee85eSHerbert Xu 			   const char *driver, u32 type, u32 mask)
23258e3ee85eSHerbert Xu {
23268e3ee85eSHerbert Xu 	struct crypto_shash *tfm;
2327cb9dde88SEric Biggers 	__le32 val;
23288e3ee85eSHerbert Xu 	int err;
23298e3ee85eSHerbert Xu 
23308e3ee85eSHerbert Xu 	err = alg_test_hash(desc, driver, type, mask);
23318e3ee85eSHerbert Xu 	if (err)
2332eb5e6730SEric Biggers 		return err;
23338e3ee85eSHerbert Xu 
2334eed93e0cSHerbert Xu 	tfm = crypto_alloc_shash(driver, type, mask);
23358e3ee85eSHerbert Xu 	if (IS_ERR(tfm)) {
2336eb5e6730SEric Biggers 		if (PTR_ERR(tfm) == -ENOENT) {
2337eb5e6730SEric Biggers 			/*
2338eb5e6730SEric Biggers 			 * This crc32c implementation is only available through
2339eb5e6730SEric Biggers 			 * ahash API, not the shash API, so the remaining part
2340eb5e6730SEric Biggers 			 * of the test is not applicable to it.
2341eb5e6730SEric Biggers 			 */
2342eb5e6730SEric Biggers 			return 0;
2343eb5e6730SEric Biggers 		}
23448e3ee85eSHerbert Xu 		printk(KERN_ERR "alg: crc32c: Failed to load transform for %s: "
23458e3ee85eSHerbert Xu 		       "%ld\n", driver, PTR_ERR(tfm));
2346eb5e6730SEric Biggers 		return PTR_ERR(tfm);
23478e3ee85eSHerbert Xu 	}
23488e3ee85eSHerbert Xu 
23498e3ee85eSHerbert Xu 	do {
23504c5c3024SJan-Simon Möller 		SHASH_DESC_ON_STACK(shash, tfm);
23514c5c3024SJan-Simon Möller 		u32 *ctx = (u32 *)shash_desc_ctx(shash);
23528e3ee85eSHerbert Xu 
23534c5c3024SJan-Simon Möller 		shash->tfm = tfm;
23544c5c3024SJan-Simon Möller 		shash->flags = 0;
23558e3ee85eSHerbert Xu 
2356cb9dde88SEric Biggers 		*ctx = 420553207;
23574c5c3024SJan-Simon Möller 		err = crypto_shash_final(shash, (u8 *)&val);
23588e3ee85eSHerbert Xu 		if (err) {
23598e3ee85eSHerbert Xu 			printk(KERN_ERR "alg: crc32c: Operation failed for "
23608e3ee85eSHerbert Xu 			       "%s: %d\n", driver, err);
23618e3ee85eSHerbert Xu 			break;
23628e3ee85eSHerbert Xu 		}
23638e3ee85eSHerbert Xu 
2364cb9dde88SEric Biggers 		if (val != cpu_to_le32(~420553207)) {
2365cb9dde88SEric Biggers 			pr_err("alg: crc32c: Test failed for %s: %u\n",
2366cb9dde88SEric Biggers 			       driver, le32_to_cpu(val));
23678e3ee85eSHerbert Xu 			err = -EINVAL;
23688e3ee85eSHerbert Xu 		}
23698e3ee85eSHerbert Xu 	} while (0);
23708e3ee85eSHerbert Xu 
23718e3ee85eSHerbert Xu 	crypto_free_shash(tfm);
23728e3ee85eSHerbert Xu 
23738e3ee85eSHerbert Xu 	return err;
23748e3ee85eSHerbert Xu }
23758e3ee85eSHerbert Xu 
23767647d6ceSJarod Wilson static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
23777647d6ceSJarod Wilson 			  u32 type, u32 mask)
23787647d6ceSJarod Wilson {
23797647d6ceSJarod Wilson 	struct crypto_rng *rng;
23807647d6ceSJarod Wilson 	int err;
23817647d6ceSJarod Wilson 
2382eed93e0cSHerbert Xu 	rng = crypto_alloc_rng(driver, type, mask);
23837647d6ceSJarod Wilson 	if (IS_ERR(rng)) {
23847647d6ceSJarod Wilson 		printk(KERN_ERR "alg: cprng: Failed to load transform for %s: "
23857647d6ceSJarod Wilson 		       "%ld\n", driver, PTR_ERR(rng));
23867647d6ceSJarod Wilson 		return PTR_ERR(rng);
23877647d6ceSJarod Wilson 	}
23887647d6ceSJarod Wilson 
23897647d6ceSJarod Wilson 	err = test_cprng(rng, desc->suite.cprng.vecs, desc->suite.cprng.count);
23907647d6ceSJarod Wilson 
23917647d6ceSJarod Wilson 	crypto_free_rng(rng);
23927647d6ceSJarod Wilson 
23937647d6ceSJarod Wilson 	return err;
23947647d6ceSJarod Wilson }
23957647d6ceSJarod Wilson 
239664d1cdfbSStephan Mueller 
2397b13b1e0cSEric Biggers static int drbg_cavs_test(const struct drbg_testvec *test, int pr,
239864d1cdfbSStephan Mueller 			  const char *driver, u32 type, u32 mask)
239964d1cdfbSStephan Mueller {
240064d1cdfbSStephan Mueller 	int ret = -EAGAIN;
240164d1cdfbSStephan Mueller 	struct crypto_rng *drng;
240264d1cdfbSStephan Mueller 	struct drbg_test_data test_data;
240364d1cdfbSStephan Mueller 	struct drbg_string addtl, pers, testentropy;
240464d1cdfbSStephan Mueller 	unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
240564d1cdfbSStephan Mueller 
240664d1cdfbSStephan Mueller 	if (!buf)
240764d1cdfbSStephan Mueller 		return -ENOMEM;
240864d1cdfbSStephan Mueller 
2409eed93e0cSHerbert Xu 	drng = crypto_alloc_rng(driver, type, mask);
241064d1cdfbSStephan Mueller 	if (IS_ERR(drng)) {
241164d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for "
241264d1cdfbSStephan Mueller 		       "%s\n", driver);
241364d1cdfbSStephan Mueller 		kzfree(buf);
241464d1cdfbSStephan Mueller 		return -ENOMEM;
241564d1cdfbSStephan Mueller 	}
241664d1cdfbSStephan Mueller 
241764d1cdfbSStephan Mueller 	test_data.testentropy = &testentropy;
241864d1cdfbSStephan Mueller 	drbg_string_fill(&testentropy, test->entropy, test->entropylen);
241964d1cdfbSStephan Mueller 	drbg_string_fill(&pers, test->pers, test->perslen);
242064d1cdfbSStephan Mueller 	ret = crypto_drbg_reset_test(drng, &pers, &test_data);
242164d1cdfbSStephan Mueller 	if (ret) {
242264d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
242364d1cdfbSStephan Mueller 		goto outbuf;
242464d1cdfbSStephan Mueller 	}
242564d1cdfbSStephan Mueller 
242664d1cdfbSStephan Mueller 	drbg_string_fill(&addtl, test->addtla, test->addtllen);
242764d1cdfbSStephan Mueller 	if (pr) {
242864d1cdfbSStephan Mueller 		drbg_string_fill(&testentropy, test->entpra, test->entprlen);
242964d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl_test(drng,
243064d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl,	&test_data);
243164d1cdfbSStephan Mueller 	} else {
243264d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl(drng,
243364d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl);
243464d1cdfbSStephan Mueller 	}
243519e60e13SStephan Mueller 	if (ret < 0) {
243664d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: could not obtain random data for "
243764d1cdfbSStephan Mueller 		       "driver %s\n", driver);
243864d1cdfbSStephan Mueller 		goto outbuf;
243964d1cdfbSStephan Mueller 	}
244064d1cdfbSStephan Mueller 
244164d1cdfbSStephan Mueller 	drbg_string_fill(&addtl, test->addtlb, test->addtllen);
244264d1cdfbSStephan Mueller 	if (pr) {
244364d1cdfbSStephan Mueller 		drbg_string_fill(&testentropy, test->entprb, test->entprlen);
244464d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl_test(drng,
244564d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl, &test_data);
244664d1cdfbSStephan Mueller 	} else {
244764d1cdfbSStephan Mueller 		ret = crypto_drbg_get_bytes_addtl(drng,
244864d1cdfbSStephan Mueller 			buf, test->expectedlen, &addtl);
244964d1cdfbSStephan Mueller 	}
245019e60e13SStephan Mueller 	if (ret < 0) {
245164d1cdfbSStephan Mueller 		printk(KERN_ERR "alg: drbg: could not obtain random data for "
245264d1cdfbSStephan Mueller 		       "driver %s\n", driver);
245364d1cdfbSStephan Mueller 		goto outbuf;
245464d1cdfbSStephan Mueller 	}
245564d1cdfbSStephan Mueller 
245664d1cdfbSStephan Mueller 	ret = memcmp(test->expected, buf, test->expectedlen);
245764d1cdfbSStephan Mueller 
245864d1cdfbSStephan Mueller outbuf:
245964d1cdfbSStephan Mueller 	crypto_free_rng(drng);
246064d1cdfbSStephan Mueller 	kzfree(buf);
246164d1cdfbSStephan Mueller 	return ret;
246264d1cdfbSStephan Mueller }
246364d1cdfbSStephan Mueller 
246464d1cdfbSStephan Mueller 
246564d1cdfbSStephan Mueller static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
246664d1cdfbSStephan Mueller 			 u32 type, u32 mask)
246764d1cdfbSStephan Mueller {
246864d1cdfbSStephan Mueller 	int err = 0;
246964d1cdfbSStephan Mueller 	int pr = 0;
247064d1cdfbSStephan Mueller 	int i = 0;
2471b13b1e0cSEric Biggers 	const struct drbg_testvec *template = desc->suite.drbg.vecs;
247264d1cdfbSStephan Mueller 	unsigned int tcount = desc->suite.drbg.count;
247364d1cdfbSStephan Mueller 
247464d1cdfbSStephan Mueller 	if (0 == memcmp(driver, "drbg_pr_", 8))
247564d1cdfbSStephan Mueller 		pr = 1;
247664d1cdfbSStephan Mueller 
247764d1cdfbSStephan Mueller 	for (i = 0; i < tcount; i++) {
247864d1cdfbSStephan Mueller 		err = drbg_cavs_test(&template[i], pr, driver, type, mask);
247964d1cdfbSStephan Mueller 		if (err) {
248064d1cdfbSStephan Mueller 			printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
248164d1cdfbSStephan Mueller 			       i, driver);
248264d1cdfbSStephan Mueller 			err = -EINVAL;
248364d1cdfbSStephan Mueller 			break;
248464d1cdfbSStephan Mueller 		}
248564d1cdfbSStephan Mueller 	}
248664d1cdfbSStephan Mueller 	return err;
248764d1cdfbSStephan Mueller 
248864d1cdfbSStephan Mueller }
248964d1cdfbSStephan Mueller 
2490b13b1e0cSEric Biggers static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
2491802c7f1cSSalvatore Benedetto 		       const char *alg)
2492802c7f1cSSalvatore Benedetto {
2493802c7f1cSSalvatore Benedetto 	struct kpp_request *req;
2494802c7f1cSSalvatore Benedetto 	void *input_buf = NULL;
2495802c7f1cSSalvatore Benedetto 	void *output_buf = NULL;
249647d3fd39STudor-Dan Ambarus 	void *a_public = NULL;
249747d3fd39STudor-Dan Ambarus 	void *a_ss = NULL;
249847d3fd39STudor-Dan Ambarus 	void *shared_secret = NULL;
24997f397136SGilad Ben-Yossef 	struct crypto_wait wait;
2500802c7f1cSSalvatore Benedetto 	unsigned int out_len_max;
2501802c7f1cSSalvatore Benedetto 	int err = -ENOMEM;
2502802c7f1cSSalvatore Benedetto 	struct scatterlist src, dst;
2503802c7f1cSSalvatore Benedetto 
2504802c7f1cSSalvatore Benedetto 	req = kpp_request_alloc(tfm, GFP_KERNEL);
2505802c7f1cSSalvatore Benedetto 	if (!req)
2506802c7f1cSSalvatore Benedetto 		return err;
2507802c7f1cSSalvatore Benedetto 
25087f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
2509802c7f1cSSalvatore Benedetto 
2510802c7f1cSSalvatore Benedetto 	err = crypto_kpp_set_secret(tfm, vec->secret, vec->secret_size);
2511802c7f1cSSalvatore Benedetto 	if (err < 0)
2512802c7f1cSSalvatore Benedetto 		goto free_req;
2513802c7f1cSSalvatore Benedetto 
2514802c7f1cSSalvatore Benedetto 	out_len_max = crypto_kpp_maxsize(tfm);
2515802c7f1cSSalvatore Benedetto 	output_buf = kzalloc(out_len_max, GFP_KERNEL);
2516802c7f1cSSalvatore Benedetto 	if (!output_buf) {
2517802c7f1cSSalvatore Benedetto 		err = -ENOMEM;
2518802c7f1cSSalvatore Benedetto 		goto free_req;
2519802c7f1cSSalvatore Benedetto 	}
2520802c7f1cSSalvatore Benedetto 
2521802c7f1cSSalvatore Benedetto 	/* Use appropriate parameter as base */
2522802c7f1cSSalvatore Benedetto 	kpp_request_set_input(req, NULL, 0);
2523802c7f1cSSalvatore Benedetto 	sg_init_one(&dst, output_buf, out_len_max);
2524802c7f1cSSalvatore Benedetto 	kpp_request_set_output(req, &dst, out_len_max);
2525802c7f1cSSalvatore Benedetto 	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
25267f397136SGilad Ben-Yossef 				 crypto_req_done, &wait);
2527802c7f1cSSalvatore Benedetto 
252847d3fd39STudor-Dan Ambarus 	/* Compute party A's public key */
25297f397136SGilad Ben-Yossef 	err = crypto_wait_req(crypto_kpp_generate_public_key(req), &wait);
2530802c7f1cSSalvatore Benedetto 	if (err) {
253147d3fd39STudor-Dan Ambarus 		pr_err("alg: %s: Party A: generate public key test failed. err %d\n",
2532802c7f1cSSalvatore Benedetto 		       alg, err);
2533802c7f1cSSalvatore Benedetto 		goto free_output;
2534802c7f1cSSalvatore Benedetto 	}
253547d3fd39STudor-Dan Ambarus 
253647d3fd39STudor-Dan Ambarus 	if (vec->genkey) {
253747d3fd39STudor-Dan Ambarus 		/* Save party A's public key */
2538e3d90e52SChristopher Diaz Riveros 		a_public = kmemdup(sg_virt(req->dst), out_len_max, GFP_KERNEL);
253947d3fd39STudor-Dan Ambarus 		if (!a_public) {
254047d3fd39STudor-Dan Ambarus 			err = -ENOMEM;
254147d3fd39STudor-Dan Ambarus 			goto free_output;
254247d3fd39STudor-Dan Ambarus 		}
254347d3fd39STudor-Dan Ambarus 	} else {
2544802c7f1cSSalvatore Benedetto 		/* Verify calculated public key */
2545802c7f1cSSalvatore Benedetto 		if (memcmp(vec->expected_a_public, sg_virt(req->dst),
2546802c7f1cSSalvatore Benedetto 			   vec->expected_a_public_size)) {
254747d3fd39STudor-Dan Ambarus 			pr_err("alg: %s: Party A: generate public key test failed. Invalid output\n",
2548802c7f1cSSalvatore Benedetto 			       alg);
2549802c7f1cSSalvatore Benedetto 			err = -EINVAL;
2550802c7f1cSSalvatore Benedetto 			goto free_output;
2551802c7f1cSSalvatore Benedetto 		}
255247d3fd39STudor-Dan Ambarus 	}
2553802c7f1cSSalvatore Benedetto 
2554802c7f1cSSalvatore Benedetto 	/* Calculate shared secret key by using counter part (b) public key. */
2555e3d90e52SChristopher Diaz Riveros 	input_buf = kmemdup(vec->b_public, vec->b_public_size, GFP_KERNEL);
2556802c7f1cSSalvatore Benedetto 	if (!input_buf) {
2557802c7f1cSSalvatore Benedetto 		err = -ENOMEM;
2558802c7f1cSSalvatore Benedetto 		goto free_output;
2559802c7f1cSSalvatore Benedetto 	}
2560802c7f1cSSalvatore Benedetto 
2561802c7f1cSSalvatore Benedetto 	sg_init_one(&src, input_buf, vec->b_public_size);
2562802c7f1cSSalvatore Benedetto 	sg_init_one(&dst, output_buf, out_len_max);
2563802c7f1cSSalvatore Benedetto 	kpp_request_set_input(req, &src, vec->b_public_size);
2564802c7f1cSSalvatore Benedetto 	kpp_request_set_output(req, &dst, out_len_max);
2565802c7f1cSSalvatore Benedetto 	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
25667f397136SGilad Ben-Yossef 				 crypto_req_done, &wait);
25677f397136SGilad Ben-Yossef 	err = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait);
2568802c7f1cSSalvatore Benedetto 	if (err) {
256947d3fd39STudor-Dan Ambarus 		pr_err("alg: %s: Party A: compute shared secret test failed. err %d\n",
2570802c7f1cSSalvatore Benedetto 		       alg, err);
2571802c7f1cSSalvatore Benedetto 		goto free_all;
2572802c7f1cSSalvatore Benedetto 	}
257347d3fd39STudor-Dan Ambarus 
257447d3fd39STudor-Dan Ambarus 	if (vec->genkey) {
257547d3fd39STudor-Dan Ambarus 		/* Save the shared secret obtained by party A */
2576e3d90e52SChristopher Diaz Riveros 		a_ss = kmemdup(sg_virt(req->dst), vec->expected_ss_size, GFP_KERNEL);
257747d3fd39STudor-Dan Ambarus 		if (!a_ss) {
257847d3fd39STudor-Dan Ambarus 			err = -ENOMEM;
257947d3fd39STudor-Dan Ambarus 			goto free_all;
258047d3fd39STudor-Dan Ambarus 		}
258147d3fd39STudor-Dan Ambarus 
258247d3fd39STudor-Dan Ambarus 		/*
258347d3fd39STudor-Dan Ambarus 		 * Calculate party B's shared secret by using party A's
258447d3fd39STudor-Dan Ambarus 		 * public key.
258547d3fd39STudor-Dan Ambarus 		 */
258647d3fd39STudor-Dan Ambarus 		err = crypto_kpp_set_secret(tfm, vec->b_secret,
258747d3fd39STudor-Dan Ambarus 					    vec->b_secret_size);
258847d3fd39STudor-Dan Ambarus 		if (err < 0)
258947d3fd39STudor-Dan Ambarus 			goto free_all;
259047d3fd39STudor-Dan Ambarus 
259147d3fd39STudor-Dan Ambarus 		sg_init_one(&src, a_public, vec->expected_a_public_size);
259247d3fd39STudor-Dan Ambarus 		sg_init_one(&dst, output_buf, out_len_max);
259347d3fd39STudor-Dan Ambarus 		kpp_request_set_input(req, &src, vec->expected_a_public_size);
259447d3fd39STudor-Dan Ambarus 		kpp_request_set_output(req, &dst, out_len_max);
259547d3fd39STudor-Dan Ambarus 		kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
25967f397136SGilad Ben-Yossef 					 crypto_req_done, &wait);
25977f397136SGilad Ben-Yossef 		err = crypto_wait_req(crypto_kpp_compute_shared_secret(req),
25987f397136SGilad Ben-Yossef 				      &wait);
259947d3fd39STudor-Dan Ambarus 		if (err) {
260047d3fd39STudor-Dan Ambarus 			pr_err("alg: %s: Party B: compute shared secret failed. err %d\n",
260147d3fd39STudor-Dan Ambarus 			       alg, err);
260247d3fd39STudor-Dan Ambarus 			goto free_all;
260347d3fd39STudor-Dan Ambarus 		}
260447d3fd39STudor-Dan Ambarus 
260547d3fd39STudor-Dan Ambarus 		shared_secret = a_ss;
260647d3fd39STudor-Dan Ambarus 	} else {
260747d3fd39STudor-Dan Ambarus 		shared_secret = (void *)vec->expected_ss;
260847d3fd39STudor-Dan Ambarus 	}
260947d3fd39STudor-Dan Ambarus 
2610802c7f1cSSalvatore Benedetto 	/*
2611802c7f1cSSalvatore Benedetto 	 * verify shared secret from which the user will derive
2612802c7f1cSSalvatore Benedetto 	 * secret key by executing whatever hash it has chosen
2613802c7f1cSSalvatore Benedetto 	 */
261447d3fd39STudor-Dan Ambarus 	if (memcmp(shared_secret, sg_virt(req->dst),
2615802c7f1cSSalvatore Benedetto 		   vec->expected_ss_size)) {
2616802c7f1cSSalvatore Benedetto 		pr_err("alg: %s: compute shared secret test failed. Invalid output\n",
2617802c7f1cSSalvatore Benedetto 		       alg);
2618802c7f1cSSalvatore Benedetto 		err = -EINVAL;
2619802c7f1cSSalvatore Benedetto 	}
2620802c7f1cSSalvatore Benedetto 
2621802c7f1cSSalvatore Benedetto free_all:
262247d3fd39STudor-Dan Ambarus 	kfree(a_ss);
2623802c7f1cSSalvatore Benedetto 	kfree(input_buf);
2624802c7f1cSSalvatore Benedetto free_output:
262547d3fd39STudor-Dan Ambarus 	kfree(a_public);
2626802c7f1cSSalvatore Benedetto 	kfree(output_buf);
2627802c7f1cSSalvatore Benedetto free_req:
2628802c7f1cSSalvatore Benedetto 	kpp_request_free(req);
2629802c7f1cSSalvatore Benedetto 	return err;
2630802c7f1cSSalvatore Benedetto }
2631802c7f1cSSalvatore Benedetto 
2632802c7f1cSSalvatore Benedetto static int test_kpp(struct crypto_kpp *tfm, const char *alg,
2633b13b1e0cSEric Biggers 		    const struct kpp_testvec *vecs, unsigned int tcount)
2634802c7f1cSSalvatore Benedetto {
2635802c7f1cSSalvatore Benedetto 	int ret, i;
2636802c7f1cSSalvatore Benedetto 
2637802c7f1cSSalvatore Benedetto 	for (i = 0; i < tcount; i++) {
2638802c7f1cSSalvatore Benedetto 		ret = do_test_kpp(tfm, vecs++, alg);
2639802c7f1cSSalvatore Benedetto 		if (ret) {
2640802c7f1cSSalvatore Benedetto 			pr_err("alg: %s: test failed on vector %d, err=%d\n",
2641802c7f1cSSalvatore Benedetto 			       alg, i + 1, ret);
2642802c7f1cSSalvatore Benedetto 			return ret;
2643802c7f1cSSalvatore Benedetto 		}
2644802c7f1cSSalvatore Benedetto 	}
2645802c7f1cSSalvatore Benedetto 	return 0;
2646802c7f1cSSalvatore Benedetto }
2647802c7f1cSSalvatore Benedetto 
2648802c7f1cSSalvatore Benedetto static int alg_test_kpp(const struct alg_test_desc *desc, const char *driver,
2649802c7f1cSSalvatore Benedetto 			u32 type, u32 mask)
2650802c7f1cSSalvatore Benedetto {
2651802c7f1cSSalvatore Benedetto 	struct crypto_kpp *tfm;
2652802c7f1cSSalvatore Benedetto 	int err = 0;
2653802c7f1cSSalvatore Benedetto 
2654eed93e0cSHerbert Xu 	tfm = crypto_alloc_kpp(driver, type, mask);
2655802c7f1cSSalvatore Benedetto 	if (IS_ERR(tfm)) {
2656802c7f1cSSalvatore Benedetto 		pr_err("alg: kpp: Failed to load tfm for %s: %ld\n",
2657802c7f1cSSalvatore Benedetto 		       driver, PTR_ERR(tfm));
2658802c7f1cSSalvatore Benedetto 		return PTR_ERR(tfm);
2659802c7f1cSSalvatore Benedetto 	}
2660802c7f1cSSalvatore Benedetto 	if (desc->suite.kpp.vecs)
2661802c7f1cSSalvatore Benedetto 		err = test_kpp(tfm, desc->alg, desc->suite.kpp.vecs,
2662802c7f1cSSalvatore Benedetto 			       desc->suite.kpp.count);
2663802c7f1cSSalvatore Benedetto 
2664802c7f1cSSalvatore Benedetto 	crypto_free_kpp(tfm);
2665802c7f1cSSalvatore Benedetto 	return err;
2666802c7f1cSSalvatore Benedetto }
2667802c7f1cSSalvatore Benedetto 
266850d2b643SHerbert Xu static int test_akcipher_one(struct crypto_akcipher *tfm,
2669b13b1e0cSEric Biggers 			     const struct akcipher_testvec *vecs)
2670946cc463STadeusz Struk {
2671df27b26fSHerbert Xu 	char *xbuf[XBUFSIZE];
2672946cc463STadeusz Struk 	struct akcipher_request *req;
2673946cc463STadeusz Struk 	void *outbuf_enc = NULL;
2674946cc463STadeusz Struk 	void *outbuf_dec = NULL;
26757f397136SGilad Ben-Yossef 	struct crypto_wait wait;
2676946cc463STadeusz Struk 	unsigned int out_len_max, out_len = 0;
2677946cc463STadeusz Struk 	int err = -ENOMEM;
267822287b0bSTadeusz Struk 	struct scatterlist src, dst, src_tab[2];
26790507de94SVitaly Chikunov 	const char *m, *c;
26800507de94SVitaly Chikunov 	unsigned int m_size, c_size;
26810507de94SVitaly Chikunov 	const char *op;
2682946cc463STadeusz Struk 
2683df27b26fSHerbert Xu 	if (testmgr_alloc_buf(xbuf))
2684df27b26fSHerbert Xu 		return err;
2685df27b26fSHerbert Xu 
2686946cc463STadeusz Struk 	req = akcipher_request_alloc(tfm, GFP_KERNEL);
2687946cc463STadeusz Struk 	if (!req)
2688df27b26fSHerbert Xu 		goto free_xbuf;
2689946cc463STadeusz Struk 
26907f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
269122287b0bSTadeusz Struk 
269222287b0bSTadeusz Struk 	if (vecs->public_key_vec)
269322287b0bSTadeusz Struk 		err = crypto_akcipher_set_pub_key(tfm, vecs->key,
269422287b0bSTadeusz Struk 						  vecs->key_len);
269522287b0bSTadeusz Struk 	else
269622287b0bSTadeusz Struk 		err = crypto_akcipher_set_priv_key(tfm, vecs->key,
269722287b0bSTadeusz Struk 						   vecs->key_len);
2698946cc463STadeusz Struk 	if (err)
2699946cc463STadeusz Struk 		goto free_req;
2700946cc463STadeusz Struk 
270157763f5eSSalvatore Benedetto 	err = -ENOMEM;
270222287b0bSTadeusz Struk 	out_len_max = crypto_akcipher_maxsize(tfm);
27030507de94SVitaly Chikunov 
27040507de94SVitaly Chikunov 	/*
27050507de94SVitaly Chikunov 	 * First run test which do not require a private key, such as
27060507de94SVitaly Chikunov 	 * encrypt or verify.
27070507de94SVitaly Chikunov 	 */
2708946cc463STadeusz Struk 	outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
2709946cc463STadeusz Struk 	if (!outbuf_enc)
2710946cc463STadeusz Struk 		goto free_req;
2711946cc463STadeusz Struk 
27120507de94SVitaly Chikunov 	if (!vecs->siggen_sigver_test) {
27130507de94SVitaly Chikunov 		m = vecs->m;
27140507de94SVitaly Chikunov 		m_size = vecs->m_size;
27150507de94SVitaly Chikunov 		c = vecs->c;
27160507de94SVitaly Chikunov 		c_size = vecs->c_size;
27170507de94SVitaly Chikunov 		op = "encrypt";
27180507de94SVitaly Chikunov 	} else {
27190507de94SVitaly Chikunov 		/* Swap args so we could keep plaintext (digest)
27200507de94SVitaly Chikunov 		 * in vecs->m, and cooked signature in vecs->c.
27210507de94SVitaly Chikunov 		 */
27220507de94SVitaly Chikunov 		m = vecs->c; /* signature */
27230507de94SVitaly Chikunov 		m_size = vecs->c_size;
27240507de94SVitaly Chikunov 		c = vecs->m; /* digest */
27250507de94SVitaly Chikunov 		c_size = vecs->m_size;
27260507de94SVitaly Chikunov 		op = "verify";
27270507de94SVitaly Chikunov 	}
2728df27b26fSHerbert Xu 
27290507de94SVitaly Chikunov 	if (WARN_ON(m_size > PAGE_SIZE))
27300507de94SVitaly Chikunov 		goto free_all;
27310507de94SVitaly Chikunov 	memcpy(xbuf[0], m, m_size);
2732df27b26fSHerbert Xu 
273322287b0bSTadeusz Struk 	sg_init_table(src_tab, 2);
2734df27b26fSHerbert Xu 	sg_set_buf(&src_tab[0], xbuf[0], 8);
27350507de94SVitaly Chikunov 	sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8);
273622287b0bSTadeusz Struk 	sg_init_one(&dst, outbuf_enc, out_len_max);
27370507de94SVitaly Chikunov 	akcipher_request_set_crypt(req, src_tab, &dst, m_size,
273822287b0bSTadeusz Struk 				   out_len_max);
2739946cc463STadeusz Struk 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
27407f397136SGilad Ben-Yossef 				      crypto_req_done, &wait);
2741946cc463STadeusz Struk 
27427f397136SGilad Ben-Yossef 	err = crypto_wait_req(vecs->siggen_sigver_test ?
27430507de94SVitaly Chikunov 			      /* Run asymmetric signature verification */
27440507de94SVitaly Chikunov 			      crypto_akcipher_verify(req) :
27451207107cSStephan Mueller 			      /* Run asymmetric encrypt */
27467f397136SGilad Ben-Yossef 			      crypto_akcipher_encrypt(req), &wait);
2747946cc463STadeusz Struk 	if (err) {
27480507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
2749946cc463STadeusz Struk 		goto free_all;
2750946cc463STadeusz Struk 	}
27510507de94SVitaly Chikunov 	if (req->dst_len != c_size) {
27520507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output len\n",
27530507de94SVitaly Chikunov 		       op);
2754946cc463STadeusz Struk 		err = -EINVAL;
2755946cc463STadeusz Struk 		goto free_all;
2756946cc463STadeusz Struk 	}
2757946cc463STadeusz Struk 	/* verify that encrypted message is equal to expected */
27580507de94SVitaly Chikunov 	if (memcmp(c, outbuf_enc, c_size)) {
27590507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output\n", op);
27600507de94SVitaly Chikunov 		hexdump(outbuf_enc, c_size);
2761946cc463STadeusz Struk 		err = -EINVAL;
2762946cc463STadeusz Struk 		goto free_all;
2763946cc463STadeusz Struk 	}
27640507de94SVitaly Chikunov 
27650507de94SVitaly Chikunov 	/*
27660507de94SVitaly Chikunov 	 * Don't invoke (decrypt or sign) test which require a private key
27670507de94SVitaly Chikunov 	 * for vectors with only a public key.
27680507de94SVitaly Chikunov 	 */
2769946cc463STadeusz Struk 	if (vecs->public_key_vec) {
2770946cc463STadeusz Struk 		err = 0;
2771946cc463STadeusz Struk 		goto free_all;
2772946cc463STadeusz Struk 	}
2773946cc463STadeusz Struk 	outbuf_dec = kzalloc(out_len_max, GFP_KERNEL);
2774946cc463STadeusz Struk 	if (!outbuf_dec) {
2775946cc463STadeusz Struk 		err = -ENOMEM;
2776946cc463STadeusz Struk 		goto free_all;
2777946cc463STadeusz Struk 	}
2778df27b26fSHerbert Xu 
27790507de94SVitaly Chikunov 	op = vecs->siggen_sigver_test ? "sign" : "decrypt";
27800507de94SVitaly Chikunov 	if (WARN_ON(c_size > PAGE_SIZE))
2781df27b26fSHerbert Xu 		goto free_all;
27820507de94SVitaly Chikunov 	memcpy(xbuf[0], c, c_size);
2783df27b26fSHerbert Xu 
27840507de94SVitaly Chikunov 	sg_init_one(&src, xbuf[0], c_size);
278522287b0bSTadeusz Struk 	sg_init_one(&dst, outbuf_dec, out_len_max);
27867f397136SGilad Ben-Yossef 	crypto_init_wait(&wait);
27870507de94SVitaly Chikunov 	akcipher_request_set_crypt(req, &src, &dst, c_size, out_len_max);
2788946cc463STadeusz Struk 
27897f397136SGilad Ben-Yossef 	err = crypto_wait_req(vecs->siggen_sigver_test ?
27900507de94SVitaly Chikunov 			      /* Run asymmetric signature generation */
27910507de94SVitaly Chikunov 			      crypto_akcipher_sign(req) :
27921207107cSStephan Mueller 			      /* Run asymmetric decrypt */
27937f397136SGilad Ben-Yossef 			      crypto_akcipher_decrypt(req), &wait);
2794946cc463STadeusz Struk 	if (err) {
27950507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
2796946cc463STadeusz Struk 		goto free_all;
2797946cc463STadeusz Struk 	}
2798946cc463STadeusz Struk 	out_len = req->dst_len;
27990507de94SVitaly Chikunov 	if (out_len < m_size) {
28000507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output len %u\n",
28010507de94SVitaly Chikunov 		       op, out_len);
2802946cc463STadeusz Struk 		err = -EINVAL;
2803946cc463STadeusz Struk 		goto free_all;
2804946cc463STadeusz Struk 	}
2805946cc463STadeusz Struk 	/* verify that decrypted message is equal to the original msg */
28060507de94SVitaly Chikunov 	if (memchr_inv(outbuf_dec, 0, out_len - m_size) ||
28070507de94SVitaly Chikunov 	    memcmp(m, outbuf_dec + out_len - m_size, m_size)) {
28080507de94SVitaly Chikunov 		pr_err("alg: akcipher: %s test failed. Invalid output\n", op);
280950d2b643SHerbert Xu 		hexdump(outbuf_dec, out_len);
2810946cc463STadeusz Struk 		err = -EINVAL;
2811946cc463STadeusz Struk 	}
2812946cc463STadeusz Struk free_all:
2813946cc463STadeusz Struk 	kfree(outbuf_dec);
2814946cc463STadeusz Struk 	kfree(outbuf_enc);
2815946cc463STadeusz Struk free_req:
2816946cc463STadeusz Struk 	akcipher_request_free(req);
2817df27b26fSHerbert Xu free_xbuf:
2818df27b26fSHerbert Xu 	testmgr_free_buf(xbuf);
2819946cc463STadeusz Struk 	return err;
2820946cc463STadeusz Struk }
2821946cc463STadeusz Struk 
282250d2b643SHerbert Xu static int test_akcipher(struct crypto_akcipher *tfm, const char *alg,
2823b13b1e0cSEric Biggers 			 const struct akcipher_testvec *vecs,
2824b13b1e0cSEric Biggers 			 unsigned int tcount)
2825946cc463STadeusz Struk {
282615226e48SHerbert Xu 	const char *algo =
282715226e48SHerbert Xu 		crypto_tfm_alg_driver_name(crypto_akcipher_tfm(tfm));
2828946cc463STadeusz Struk 	int ret, i;
2829946cc463STadeusz Struk 
2830946cc463STadeusz Struk 	for (i = 0; i < tcount; i++) {
283150d2b643SHerbert Xu 		ret = test_akcipher_one(tfm, vecs++);
283250d2b643SHerbert Xu 		if (!ret)
283350d2b643SHerbert Xu 			continue;
283450d2b643SHerbert Xu 
283515226e48SHerbert Xu 		pr_err("alg: akcipher: test %d failed for %s, err=%d\n",
283615226e48SHerbert Xu 		       i + 1, algo, ret);
2837946cc463STadeusz Struk 		return ret;
2838946cc463STadeusz Struk 	}
2839946cc463STadeusz Struk 	return 0;
2840946cc463STadeusz Struk }
2841946cc463STadeusz Struk 
2842946cc463STadeusz Struk static int alg_test_akcipher(const struct alg_test_desc *desc,
2843946cc463STadeusz Struk 			     const char *driver, u32 type, u32 mask)
2844946cc463STadeusz Struk {
2845946cc463STadeusz Struk 	struct crypto_akcipher *tfm;
2846946cc463STadeusz Struk 	int err = 0;
2847946cc463STadeusz Struk 
2848eed93e0cSHerbert Xu 	tfm = crypto_alloc_akcipher(driver, type, mask);
2849946cc463STadeusz Struk 	if (IS_ERR(tfm)) {
2850946cc463STadeusz Struk 		pr_err("alg: akcipher: Failed to load tfm for %s: %ld\n",
2851946cc463STadeusz Struk 		       driver, PTR_ERR(tfm));
2852946cc463STadeusz Struk 		return PTR_ERR(tfm);
2853946cc463STadeusz Struk 	}
2854946cc463STadeusz Struk 	if (desc->suite.akcipher.vecs)
2855946cc463STadeusz Struk 		err = test_akcipher(tfm, desc->alg, desc->suite.akcipher.vecs,
2856946cc463STadeusz Struk 				    desc->suite.akcipher.count);
2857946cc463STadeusz Struk 
2858946cc463STadeusz Struk 	crypto_free_akcipher(tfm);
2859946cc463STadeusz Struk 	return err;
2860946cc463STadeusz Struk }
2861946cc463STadeusz Struk 
2862863b557aSYouquan, Song static int alg_test_null(const struct alg_test_desc *desc,
2863863b557aSYouquan, Song 			     const char *driver, u32 type, u32 mask)
2864863b557aSYouquan, Song {
2865863b557aSYouquan, Song 	return 0;
2866863b557aSYouquan, Song }
2867863b557aSYouquan, Song 
286821c8e720SArd Biesheuvel #define __VECS(tv)	{ .vecs = tv, .count = ARRAY_SIZE(tv) }
286921c8e720SArd Biesheuvel 
2870da7f033dSHerbert Xu /* Please keep this list sorted by algorithm name. */
2871da7f033dSHerbert Xu static const struct alg_test_desc alg_test_descs[] = {
2872da7f033dSHerbert Xu 	{
2873059c2a4dSEric Biggers 		.alg = "adiantum(xchacha12,aes)",
2874059c2a4dSEric Biggers 		.test = alg_test_skcipher,
2875059c2a4dSEric Biggers 		.suite = {
2876059c2a4dSEric Biggers 			.cipher = __VECS(adiantum_xchacha12_aes_tv_template)
2877059c2a4dSEric Biggers 		},
2878059c2a4dSEric Biggers 	}, {
2879059c2a4dSEric Biggers 		.alg = "adiantum(xchacha20,aes)",
2880059c2a4dSEric Biggers 		.test = alg_test_skcipher,
2881059c2a4dSEric Biggers 		.suite = {
2882059c2a4dSEric Biggers 			.cipher = __VECS(adiantum_xchacha20_aes_tv_template)
2883059c2a4dSEric Biggers 		},
2884059c2a4dSEric Biggers 	}, {
2885b87dc203SOndrej Mosnacek 		.alg = "aegis128",
2886b87dc203SOndrej Mosnacek 		.test = alg_test_aead,
2887b87dc203SOndrej Mosnacek 		.suite = {
2888a0d608eeSEric Biggers 			.aead = __VECS(aegis128_tv_template)
2889b87dc203SOndrej Mosnacek 		}
2890b87dc203SOndrej Mosnacek 	}, {
2891b87dc203SOndrej Mosnacek 		.alg = "aegis128l",
2892b87dc203SOndrej Mosnacek 		.test = alg_test_aead,
2893b87dc203SOndrej Mosnacek 		.suite = {
2894a0d608eeSEric Biggers 			.aead = __VECS(aegis128l_tv_template)
2895b87dc203SOndrej Mosnacek 		}
2896b87dc203SOndrej Mosnacek 	}, {
2897b87dc203SOndrej Mosnacek 		.alg = "aegis256",
2898b87dc203SOndrej Mosnacek 		.test = alg_test_aead,
2899b87dc203SOndrej Mosnacek 		.suite = {
2900a0d608eeSEric Biggers 			.aead = __VECS(aegis256_tv_template)
2901b87dc203SOndrej Mosnacek 		}
2902b87dc203SOndrej Mosnacek 	}, {
2903e08ca2daSJarod Wilson 		.alg = "ansi_cprng",
2904e08ca2daSJarod Wilson 		.test = alg_test_cprng,
2905e08ca2daSJarod Wilson 		.suite = {
290621c8e720SArd Biesheuvel 			.cprng = __VECS(ansi_cprng_aes_tv_template)
2907e08ca2daSJarod Wilson 		}
2908e08ca2daSJarod Wilson 	}, {
2909bca4feb0SHoria Geanta 		.alg = "authenc(hmac(md5),ecb(cipher_null))",
2910bca4feb0SHoria Geanta 		.test = alg_test_aead,
2911bca4feb0SHoria Geanta 		.suite = {
2912a0d608eeSEric Biggers 			.aead = __VECS(hmac_md5_ecb_cipher_null_tv_template)
2913bca4feb0SHoria Geanta 		}
2914bca4feb0SHoria Geanta 	}, {
2915a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha1),cbc(aes))",
2916e46e9a46SHoria Geanta 		.test = alg_test_aead,
2917bcf741cbSHerbert Xu 		.fips_allowed = 1,
2918e46e9a46SHoria Geanta 		.suite = {
2919a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_aes_cbc_tv_temp)
29205208ed2cSNitesh Lal 		}
29215208ed2cSNitesh Lal 	}, {
2922a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha1),cbc(des))",
29235208ed2cSNitesh Lal 		.test = alg_test_aead,
29245208ed2cSNitesh Lal 		.suite = {
2925a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_des_cbc_tv_temp)
29265208ed2cSNitesh Lal 		}
29275208ed2cSNitesh Lal 	}, {
2928a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha1),cbc(des3_ede))",
29295208ed2cSNitesh Lal 		.test = alg_test_aead,
2930ed1afac9SMarcus Meissner 		.fips_allowed = 1,
29315208ed2cSNitesh Lal 		.suite = {
2932a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_des3_ede_cbc_tv_temp)
2933e46e9a46SHoria Geanta 		}
2934e46e9a46SHoria Geanta 	}, {
2935fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha1),ctr(aes))",
2936fb16abc2SMarcus Meissner 		.test = alg_test_null,
2937fb16abc2SMarcus Meissner 		.fips_allowed = 1,
2938fb16abc2SMarcus Meissner 	}, {
2939bca4feb0SHoria Geanta 		.alg = "authenc(hmac(sha1),ecb(cipher_null))",
2940bca4feb0SHoria Geanta 		.test = alg_test_aead,
2941bca4feb0SHoria Geanta 		.suite = {
2942a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha1_ecb_cipher_null_tv_temp)
29435208ed2cSNitesh Lal 		}
29445208ed2cSNitesh Lal 	}, {
29458888690eSMarcus Meissner 		.alg = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
29468888690eSMarcus Meissner 		.test = alg_test_null,
29478888690eSMarcus Meissner 		.fips_allowed = 1,
29488888690eSMarcus Meissner 	}, {
2949a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha224),cbc(des))",
29505208ed2cSNitesh Lal 		.test = alg_test_aead,
29515208ed2cSNitesh Lal 		.suite = {
2952a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha224_des_cbc_tv_temp)
29535208ed2cSNitesh Lal 		}
29545208ed2cSNitesh Lal 	}, {
2955a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha224),cbc(des3_ede))",
29565208ed2cSNitesh Lal 		.test = alg_test_aead,
2957ed1afac9SMarcus Meissner 		.fips_allowed = 1,
29585208ed2cSNitesh Lal 		.suite = {
2959a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha224_des3_ede_cbc_tv_temp)
2960bca4feb0SHoria Geanta 		}
2961bca4feb0SHoria Geanta 	}, {
2962a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha256),cbc(aes))",
2963e46e9a46SHoria Geanta 		.test = alg_test_aead,
2964ed1afac9SMarcus Meissner 		.fips_allowed = 1,
2965e46e9a46SHoria Geanta 		.suite = {
2966a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha256_aes_cbc_tv_temp)
29675208ed2cSNitesh Lal 		}
29685208ed2cSNitesh Lal 	}, {
2969a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha256),cbc(des))",
29705208ed2cSNitesh Lal 		.test = alg_test_aead,
29715208ed2cSNitesh Lal 		.suite = {
2972a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha256_des_cbc_tv_temp)
29735208ed2cSNitesh Lal 		}
29745208ed2cSNitesh Lal 	}, {
2975a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha256),cbc(des3_ede))",
29765208ed2cSNitesh Lal 		.test = alg_test_aead,
2977ed1afac9SMarcus Meissner 		.fips_allowed = 1,
29785208ed2cSNitesh Lal 		.suite = {
2979a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha256_des3_ede_cbc_tv_temp)
29805208ed2cSNitesh Lal 		}
29815208ed2cSNitesh Lal 	}, {
2982fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha256),ctr(aes))",
2983fb16abc2SMarcus Meissner 		.test = alg_test_null,
2984fb16abc2SMarcus Meissner 		.fips_allowed = 1,
2985fb16abc2SMarcus Meissner 	}, {
29868888690eSMarcus Meissner 		.alg = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
29878888690eSMarcus Meissner 		.test = alg_test_null,
29888888690eSMarcus Meissner 		.fips_allowed = 1,
29898888690eSMarcus Meissner 	}, {
2990a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha384),cbc(des))",
29915208ed2cSNitesh Lal 		.test = alg_test_aead,
29925208ed2cSNitesh Lal 		.suite = {
2993a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha384_des_cbc_tv_temp)
29945208ed2cSNitesh Lal 		}
29955208ed2cSNitesh Lal 	}, {
2996a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha384),cbc(des3_ede))",
29975208ed2cSNitesh Lal 		.test = alg_test_aead,
2998ed1afac9SMarcus Meissner 		.fips_allowed = 1,
29995208ed2cSNitesh Lal 		.suite = {
3000a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha384_des3_ede_cbc_tv_temp)
3001e46e9a46SHoria Geanta 		}
3002e46e9a46SHoria Geanta 	}, {
3003fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha384),ctr(aes))",
3004fb16abc2SMarcus Meissner 		.test = alg_test_null,
3005fb16abc2SMarcus Meissner 		.fips_allowed = 1,
3006fb16abc2SMarcus Meissner 	}, {
30078888690eSMarcus Meissner 		.alg = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
30088888690eSMarcus Meissner 		.test = alg_test_null,
30098888690eSMarcus Meissner 		.fips_allowed = 1,
30108888690eSMarcus Meissner 	}, {
3011a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha512),cbc(aes))",
3012ed1afac9SMarcus Meissner 		.fips_allowed = 1,
3013e46e9a46SHoria Geanta 		.test = alg_test_aead,
3014e46e9a46SHoria Geanta 		.suite = {
3015a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha512_aes_cbc_tv_temp)
30165208ed2cSNitesh Lal 		}
30175208ed2cSNitesh Lal 	}, {
3018a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha512),cbc(des))",
30195208ed2cSNitesh Lal 		.test = alg_test_aead,
30205208ed2cSNitesh Lal 		.suite = {
3021a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha512_des_cbc_tv_temp)
30225208ed2cSNitesh Lal 		}
30235208ed2cSNitesh Lal 	}, {
3024a4198fd4SHerbert Xu 		.alg = "authenc(hmac(sha512),cbc(des3_ede))",
30255208ed2cSNitesh Lal 		.test = alg_test_aead,
3026ed1afac9SMarcus Meissner 		.fips_allowed = 1,
30275208ed2cSNitesh Lal 		.suite = {
3028a0d608eeSEric Biggers 			.aead = __VECS(hmac_sha512_des3_ede_cbc_tv_temp)
3029e46e9a46SHoria Geanta 		}
3030e46e9a46SHoria Geanta 	}, {
3031fb16abc2SMarcus Meissner 		.alg = "authenc(hmac(sha512),ctr(aes))",
3032fb16abc2SMarcus Meissner 		.test = alg_test_null,
3033fb16abc2SMarcus Meissner 		.fips_allowed = 1,
3034fb16abc2SMarcus Meissner 	}, {
30358888690eSMarcus Meissner 		.alg = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
30368888690eSMarcus Meissner 		.test = alg_test_null,
30378888690eSMarcus Meissner 		.fips_allowed = 1,
30388888690eSMarcus Meissner 	}, {
3039da7f033dSHerbert Xu 		.alg = "cbc(aes)",
30401aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3041a1915d51SJarod Wilson 		.fips_allowed = 1,
3042da7f033dSHerbert Xu 		.suite = {
304392a4c9feSEric Biggers 			.cipher = __VECS(aes_cbc_tv_template)
304492a4c9feSEric Biggers 		},
3045da7f033dSHerbert Xu 	}, {
3046da7f033dSHerbert Xu 		.alg = "cbc(anubis)",
30471aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3048da7f033dSHerbert Xu 		.suite = {
304992a4c9feSEric Biggers 			.cipher = __VECS(anubis_cbc_tv_template)
305092a4c9feSEric Biggers 		},
3051da7f033dSHerbert Xu 	}, {
3052da7f033dSHerbert Xu 		.alg = "cbc(blowfish)",
30531aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3054da7f033dSHerbert Xu 		.suite = {
305592a4c9feSEric Biggers 			.cipher = __VECS(bf_cbc_tv_template)
305692a4c9feSEric Biggers 		},
3057da7f033dSHerbert Xu 	}, {
3058da7f033dSHerbert Xu 		.alg = "cbc(camellia)",
30591aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3060da7f033dSHerbert Xu 		.suite = {
306192a4c9feSEric Biggers 			.cipher = __VECS(camellia_cbc_tv_template)
306292a4c9feSEric Biggers 		},
3063da7f033dSHerbert Xu 	}, {
3064a2c58260SJohannes Goetzfried 		.alg = "cbc(cast5)",
3065a2c58260SJohannes Goetzfried 		.test = alg_test_skcipher,
3066a2c58260SJohannes Goetzfried 		.suite = {
306792a4c9feSEric Biggers 			.cipher = __VECS(cast5_cbc_tv_template)
306892a4c9feSEric Biggers 		},
3069a2c58260SJohannes Goetzfried 	}, {
30709b8b0405SJohannes Goetzfried 		.alg = "cbc(cast6)",
30719b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
30729b8b0405SJohannes Goetzfried 		.suite = {
307392a4c9feSEric Biggers 			.cipher = __VECS(cast6_cbc_tv_template)
307492a4c9feSEric Biggers 		},
30759b8b0405SJohannes Goetzfried 	}, {
3076da7f033dSHerbert Xu 		.alg = "cbc(des)",
30771aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3078da7f033dSHerbert Xu 		.suite = {
307992a4c9feSEric Biggers 			.cipher = __VECS(des_cbc_tv_template)
308092a4c9feSEric Biggers 		},
3081da7f033dSHerbert Xu 	}, {
3082da7f033dSHerbert Xu 		.alg = "cbc(des3_ede)",
30831aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3084a1915d51SJarod Wilson 		.fips_allowed = 1,
3085da7f033dSHerbert Xu 		.suite = {
308692a4c9feSEric Biggers 			.cipher = __VECS(des3_ede_cbc_tv_template)
308792a4c9feSEric Biggers 		},
3088da7f033dSHerbert Xu 	}, {
3089a794d8d8SGilad Ben-Yossef 		/* Same as cbc(aes) except the key is stored in
3090a794d8d8SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
3091a794d8d8SGilad Ben-Yossef 		 */
3092a794d8d8SGilad Ben-Yossef 		.alg = "cbc(paes)",
3093a794d8d8SGilad Ben-Yossef 		.test = alg_test_null,
3094a794d8d8SGilad Ben-Yossef 		.fips_allowed = 1,
3095a794d8d8SGilad Ben-Yossef 	}, {
30969d25917dSJussi Kivilinna 		.alg = "cbc(serpent)",
30979d25917dSJussi Kivilinna 		.test = alg_test_skcipher,
30989d25917dSJussi Kivilinna 		.suite = {
309992a4c9feSEric Biggers 			.cipher = __VECS(serpent_cbc_tv_template)
310092a4c9feSEric Biggers 		},
31019d25917dSJussi Kivilinna 	}, {
310295ba5973SGilad Ben-Yossef 		.alg = "cbc(sm4)",
310395ba5973SGilad Ben-Yossef 		.test = alg_test_skcipher,
310495ba5973SGilad Ben-Yossef 		.suite = {
310595ba5973SGilad Ben-Yossef 			.cipher = __VECS(sm4_cbc_tv_template)
310695ba5973SGilad Ben-Yossef 		}
310795ba5973SGilad Ben-Yossef 	}, {
3108da7f033dSHerbert Xu 		.alg = "cbc(twofish)",
31091aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3110da7f033dSHerbert Xu 		.suite = {
311192a4c9feSEric Biggers 			.cipher = __VECS(tf_cbc_tv_template)
311292a4c9feSEric Biggers 		},
3113da7f033dSHerbert Xu 	}, {
3114092acf06SArd Biesheuvel 		.alg = "cbcmac(aes)",
3115092acf06SArd Biesheuvel 		.fips_allowed = 1,
3116092acf06SArd Biesheuvel 		.test = alg_test_hash,
3117092acf06SArd Biesheuvel 		.suite = {
3118092acf06SArd Biesheuvel 			.hash = __VECS(aes_cbcmac_tv_template)
3119092acf06SArd Biesheuvel 		}
3120092acf06SArd Biesheuvel 	}, {
3121da7f033dSHerbert Xu 		.alg = "ccm(aes)",
3122da7f033dSHerbert Xu 		.test = alg_test_aead,
3123a1915d51SJarod Wilson 		.fips_allowed = 1,
3124da7f033dSHerbert Xu 		.suite = {
3125a0d608eeSEric Biggers 			.aead = __VECS(aes_ccm_tv_template)
3126da7f033dSHerbert Xu 		}
3127da7f033dSHerbert Xu 	}, {
31287da66670SDmitry Eremin-Solenikov 		.alg = "cfb(aes)",
31297da66670SDmitry Eremin-Solenikov 		.test = alg_test_skcipher,
31307da66670SDmitry Eremin-Solenikov 		.fips_allowed = 1,
31317da66670SDmitry Eremin-Solenikov 		.suite = {
31327da66670SDmitry Eremin-Solenikov 			.cipher = __VECS(aes_cfb_tv_template)
31337da66670SDmitry Eremin-Solenikov 		},
31347da66670SDmitry Eremin-Solenikov 	}, {
31353590ebf2SMartin Willi 		.alg = "chacha20",
31363590ebf2SMartin Willi 		.test = alg_test_skcipher,
31373590ebf2SMartin Willi 		.suite = {
313892a4c9feSEric Biggers 			.cipher = __VECS(chacha20_tv_template)
313992a4c9feSEric Biggers 		},
31403590ebf2SMartin Willi 	}, {
314193b5e86aSJussi Kivilinna 		.alg = "cmac(aes)",
31428f183751SStephan Mueller 		.fips_allowed = 1,
314393b5e86aSJussi Kivilinna 		.test = alg_test_hash,
314493b5e86aSJussi Kivilinna 		.suite = {
314521c8e720SArd Biesheuvel 			.hash = __VECS(aes_cmac128_tv_template)
314693b5e86aSJussi Kivilinna 		}
314793b5e86aSJussi Kivilinna 	}, {
314893b5e86aSJussi Kivilinna 		.alg = "cmac(des3_ede)",
31498f183751SStephan Mueller 		.fips_allowed = 1,
315093b5e86aSJussi Kivilinna 		.test = alg_test_hash,
315193b5e86aSJussi Kivilinna 		.suite = {
315221c8e720SArd Biesheuvel 			.hash = __VECS(des3_ede_cmac64_tv_template)
315393b5e86aSJussi Kivilinna 		}
315493b5e86aSJussi Kivilinna 	}, {
3155e448370dSJussi Kivilinna 		.alg = "compress_null",
3156e448370dSJussi Kivilinna 		.test = alg_test_null,
3157e448370dSJussi Kivilinna 	}, {
3158ebb3472fSArd Biesheuvel 		.alg = "crc32",
3159ebb3472fSArd Biesheuvel 		.test = alg_test_hash,
3160a8a34416SMilan Broz 		.fips_allowed = 1,
3161ebb3472fSArd Biesheuvel 		.suite = {
316221c8e720SArd Biesheuvel 			.hash = __VECS(crc32_tv_template)
3163ebb3472fSArd Biesheuvel 		}
3164ebb3472fSArd Biesheuvel 	}, {
3165da7f033dSHerbert Xu 		.alg = "crc32c",
31668e3ee85eSHerbert Xu 		.test = alg_test_crc32c,
3167a1915d51SJarod Wilson 		.fips_allowed = 1,
3168da7f033dSHerbert Xu 		.suite = {
316921c8e720SArd Biesheuvel 			.hash = __VECS(crc32c_tv_template)
3170da7f033dSHerbert Xu 		}
3171da7f033dSHerbert Xu 	}, {
317268411521SHerbert Xu 		.alg = "crct10dif",
317368411521SHerbert Xu 		.test = alg_test_hash,
317468411521SHerbert Xu 		.fips_allowed = 1,
317568411521SHerbert Xu 		.suite = {
317621c8e720SArd Biesheuvel 			.hash = __VECS(crct10dif_tv_template)
317768411521SHerbert Xu 		}
317868411521SHerbert Xu 	}, {
3179f7cb80f2SJarod Wilson 		.alg = "ctr(aes)",
3180f7cb80f2SJarod Wilson 		.test = alg_test_skcipher,
3181a1915d51SJarod Wilson 		.fips_allowed = 1,
3182f7cb80f2SJarod Wilson 		.suite = {
318392a4c9feSEric Biggers 			.cipher = __VECS(aes_ctr_tv_template)
3184f7cb80f2SJarod Wilson 		}
3185f7cb80f2SJarod Wilson 	}, {
318685b63e34SJussi Kivilinna 		.alg = "ctr(blowfish)",
318785b63e34SJussi Kivilinna 		.test = alg_test_skcipher,
318885b63e34SJussi Kivilinna 		.suite = {
318992a4c9feSEric Biggers 			.cipher = __VECS(bf_ctr_tv_template)
319085b63e34SJussi Kivilinna 		}
319185b63e34SJussi Kivilinna 	}, {
31920840605eSJussi Kivilinna 		.alg = "ctr(camellia)",
31930840605eSJussi Kivilinna 		.test = alg_test_skcipher,
31940840605eSJussi Kivilinna 		.suite = {
319592a4c9feSEric Biggers 			.cipher = __VECS(camellia_ctr_tv_template)
31960840605eSJussi Kivilinna 		}
31970840605eSJussi Kivilinna 	}, {
3198a2c58260SJohannes Goetzfried 		.alg = "ctr(cast5)",
3199a2c58260SJohannes Goetzfried 		.test = alg_test_skcipher,
3200a2c58260SJohannes Goetzfried 		.suite = {
320192a4c9feSEric Biggers 			.cipher = __VECS(cast5_ctr_tv_template)
3202a2c58260SJohannes Goetzfried 		}
3203a2c58260SJohannes Goetzfried 	}, {
32049b8b0405SJohannes Goetzfried 		.alg = "ctr(cast6)",
32059b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
32069b8b0405SJohannes Goetzfried 		.suite = {
320792a4c9feSEric Biggers 			.cipher = __VECS(cast6_ctr_tv_template)
32089b8b0405SJohannes Goetzfried 		}
32099b8b0405SJohannes Goetzfried 	}, {
32108163fc30SJussi Kivilinna 		.alg = "ctr(des)",
32118163fc30SJussi Kivilinna 		.test = alg_test_skcipher,
32128163fc30SJussi Kivilinna 		.suite = {
321392a4c9feSEric Biggers 			.cipher = __VECS(des_ctr_tv_template)
32148163fc30SJussi Kivilinna 		}
32158163fc30SJussi Kivilinna 	}, {
3216e080b17aSJussi Kivilinna 		.alg = "ctr(des3_ede)",
3217e080b17aSJussi Kivilinna 		.test = alg_test_skcipher,
32180d8da104SMarcelo Cerri 		.fips_allowed = 1,
3219e080b17aSJussi Kivilinna 		.suite = {
322092a4c9feSEric Biggers 			.cipher = __VECS(des3_ede_ctr_tv_template)
3221e080b17aSJussi Kivilinna 		}
3222e080b17aSJussi Kivilinna 	}, {
3223a794d8d8SGilad Ben-Yossef 		/* Same as ctr(aes) except the key is stored in
3224a794d8d8SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
3225a794d8d8SGilad Ben-Yossef 		 */
3226a794d8d8SGilad Ben-Yossef 		.alg = "ctr(paes)",
3227a794d8d8SGilad Ben-Yossef 		.test = alg_test_null,
3228a794d8d8SGilad Ben-Yossef 		.fips_allowed = 1,
3229a794d8d8SGilad Ben-Yossef 	}, {
32309d25917dSJussi Kivilinna 		.alg = "ctr(serpent)",
32319d25917dSJussi Kivilinna 		.test = alg_test_skcipher,
32329d25917dSJussi Kivilinna 		.suite = {
323392a4c9feSEric Biggers 			.cipher = __VECS(serpent_ctr_tv_template)
32349d25917dSJussi Kivilinna 		}
32359d25917dSJussi Kivilinna 	}, {
323695ba5973SGilad Ben-Yossef 		.alg = "ctr(sm4)",
323795ba5973SGilad Ben-Yossef 		.test = alg_test_skcipher,
323895ba5973SGilad Ben-Yossef 		.suite = {
323995ba5973SGilad Ben-Yossef 			.cipher = __VECS(sm4_ctr_tv_template)
324095ba5973SGilad Ben-Yossef 		}
324195ba5973SGilad Ben-Yossef 	}, {
3242573da620SJussi Kivilinna 		.alg = "ctr(twofish)",
3243573da620SJussi Kivilinna 		.test = alg_test_skcipher,
3244573da620SJussi Kivilinna 		.suite = {
324592a4c9feSEric Biggers 			.cipher = __VECS(tf_ctr_tv_template)
3246573da620SJussi Kivilinna 		}
3247573da620SJussi Kivilinna 	}, {
3248da7f033dSHerbert Xu 		.alg = "cts(cbc(aes))",
32491aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3250196ad604SGilad Ben-Yossef 		.fips_allowed = 1,
3251da7f033dSHerbert Xu 		.suite = {
325292a4c9feSEric Biggers 			.cipher = __VECS(cts_mode_tv_template)
3253da7f033dSHerbert Xu 		}
3254da7f033dSHerbert Xu 	}, {
3255da7f033dSHerbert Xu 		.alg = "deflate",
3256da7f033dSHerbert Xu 		.test = alg_test_comp,
32570818904dSMilan Broz 		.fips_allowed = 1,
3258da7f033dSHerbert Xu 		.suite = {
3259da7f033dSHerbert Xu 			.comp = {
326021c8e720SArd Biesheuvel 				.comp = __VECS(deflate_comp_tv_template),
326121c8e720SArd Biesheuvel 				.decomp = __VECS(deflate_decomp_tv_template)
3262da7f033dSHerbert Xu 			}
3263da7f033dSHerbert Xu 		}
3264da7f033dSHerbert Xu 	}, {
3265802c7f1cSSalvatore Benedetto 		.alg = "dh",
3266802c7f1cSSalvatore Benedetto 		.test = alg_test_kpp,
3267802c7f1cSSalvatore Benedetto 		.fips_allowed = 1,
3268802c7f1cSSalvatore Benedetto 		.suite = {
326921c8e720SArd Biesheuvel 			.kpp = __VECS(dh_tv_template)
3270802c7f1cSSalvatore Benedetto 		}
3271802c7f1cSSalvatore Benedetto 	}, {
3272e448370dSJussi Kivilinna 		.alg = "digest_null",
3273e448370dSJussi Kivilinna 		.test = alg_test_null,
3274e448370dSJussi Kivilinna 	}, {
327564d1cdfbSStephan Mueller 		.alg = "drbg_nopr_ctr_aes128",
327664d1cdfbSStephan Mueller 		.test = alg_test_drbg,
327764d1cdfbSStephan Mueller 		.fips_allowed = 1,
327864d1cdfbSStephan Mueller 		.suite = {
327921c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_ctr_aes128_tv_template)
328064d1cdfbSStephan Mueller 		}
328164d1cdfbSStephan Mueller 	}, {
328264d1cdfbSStephan Mueller 		.alg = "drbg_nopr_ctr_aes192",
328364d1cdfbSStephan Mueller 		.test = alg_test_drbg,
328464d1cdfbSStephan Mueller 		.fips_allowed = 1,
328564d1cdfbSStephan Mueller 		.suite = {
328621c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_ctr_aes192_tv_template)
328764d1cdfbSStephan Mueller 		}
328864d1cdfbSStephan Mueller 	}, {
328964d1cdfbSStephan Mueller 		.alg = "drbg_nopr_ctr_aes256",
329064d1cdfbSStephan Mueller 		.test = alg_test_drbg,
329164d1cdfbSStephan Mueller 		.fips_allowed = 1,
329264d1cdfbSStephan Mueller 		.suite = {
329321c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_ctr_aes256_tv_template)
329464d1cdfbSStephan Mueller 		}
329564d1cdfbSStephan Mueller 	}, {
329664d1cdfbSStephan Mueller 		/*
329764d1cdfbSStephan Mueller 		 * There is no need to specifically test the DRBG with every
329864d1cdfbSStephan Mueller 		 * backend cipher -- covered by drbg_nopr_hmac_sha256 test
329964d1cdfbSStephan Mueller 		 */
330064d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha1",
330164d1cdfbSStephan Mueller 		.fips_allowed = 1,
330264d1cdfbSStephan Mueller 		.test = alg_test_null,
330364d1cdfbSStephan Mueller 	}, {
330464d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha256",
330564d1cdfbSStephan Mueller 		.test = alg_test_drbg,
330664d1cdfbSStephan Mueller 		.fips_allowed = 1,
330764d1cdfbSStephan Mueller 		.suite = {
330821c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_hmac_sha256_tv_template)
330964d1cdfbSStephan Mueller 		}
331064d1cdfbSStephan Mueller 	}, {
331164d1cdfbSStephan Mueller 		/* covered by drbg_nopr_hmac_sha256 test */
331264d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha384",
331364d1cdfbSStephan Mueller 		.fips_allowed = 1,
331464d1cdfbSStephan Mueller 		.test = alg_test_null,
331564d1cdfbSStephan Mueller 	}, {
331664d1cdfbSStephan Mueller 		.alg = "drbg_nopr_hmac_sha512",
331764d1cdfbSStephan Mueller 		.test = alg_test_null,
331864d1cdfbSStephan Mueller 		.fips_allowed = 1,
331964d1cdfbSStephan Mueller 	}, {
332064d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha1",
332164d1cdfbSStephan Mueller 		.fips_allowed = 1,
332264d1cdfbSStephan Mueller 		.test = alg_test_null,
332364d1cdfbSStephan Mueller 	}, {
332464d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha256",
332564d1cdfbSStephan Mueller 		.test = alg_test_drbg,
332664d1cdfbSStephan Mueller 		.fips_allowed = 1,
332764d1cdfbSStephan Mueller 		.suite = {
332821c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_nopr_sha256_tv_template)
332964d1cdfbSStephan Mueller 		}
333064d1cdfbSStephan Mueller 	}, {
333164d1cdfbSStephan Mueller 		/* covered by drbg_nopr_sha256 test */
333264d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha384",
333364d1cdfbSStephan Mueller 		.fips_allowed = 1,
333464d1cdfbSStephan Mueller 		.test = alg_test_null,
333564d1cdfbSStephan Mueller 	}, {
333664d1cdfbSStephan Mueller 		.alg = "drbg_nopr_sha512",
333764d1cdfbSStephan Mueller 		.fips_allowed = 1,
333864d1cdfbSStephan Mueller 		.test = alg_test_null,
333964d1cdfbSStephan Mueller 	}, {
334064d1cdfbSStephan Mueller 		.alg = "drbg_pr_ctr_aes128",
334164d1cdfbSStephan Mueller 		.test = alg_test_drbg,
334264d1cdfbSStephan Mueller 		.fips_allowed = 1,
334364d1cdfbSStephan Mueller 		.suite = {
334421c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_pr_ctr_aes128_tv_template)
334564d1cdfbSStephan Mueller 		}
334664d1cdfbSStephan Mueller 	}, {
334764d1cdfbSStephan Mueller 		/* covered by drbg_pr_ctr_aes128 test */
334864d1cdfbSStephan Mueller 		.alg = "drbg_pr_ctr_aes192",
334964d1cdfbSStephan Mueller 		.fips_allowed = 1,
335064d1cdfbSStephan Mueller 		.test = alg_test_null,
335164d1cdfbSStephan Mueller 	}, {
335264d1cdfbSStephan Mueller 		.alg = "drbg_pr_ctr_aes256",
335364d1cdfbSStephan Mueller 		.fips_allowed = 1,
335464d1cdfbSStephan Mueller 		.test = alg_test_null,
335564d1cdfbSStephan Mueller 	}, {
335664d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha1",
335764d1cdfbSStephan Mueller 		.fips_allowed = 1,
335864d1cdfbSStephan Mueller 		.test = alg_test_null,
335964d1cdfbSStephan Mueller 	}, {
336064d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha256",
336164d1cdfbSStephan Mueller 		.test = alg_test_drbg,
336264d1cdfbSStephan Mueller 		.fips_allowed = 1,
336364d1cdfbSStephan Mueller 		.suite = {
336421c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_pr_hmac_sha256_tv_template)
336564d1cdfbSStephan Mueller 		}
336664d1cdfbSStephan Mueller 	}, {
336764d1cdfbSStephan Mueller 		/* covered by drbg_pr_hmac_sha256 test */
336864d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha384",
336964d1cdfbSStephan Mueller 		.fips_allowed = 1,
337064d1cdfbSStephan Mueller 		.test = alg_test_null,
337164d1cdfbSStephan Mueller 	}, {
337264d1cdfbSStephan Mueller 		.alg = "drbg_pr_hmac_sha512",
337364d1cdfbSStephan Mueller 		.test = alg_test_null,
337464d1cdfbSStephan Mueller 		.fips_allowed = 1,
337564d1cdfbSStephan Mueller 	}, {
337664d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha1",
337764d1cdfbSStephan Mueller 		.fips_allowed = 1,
337864d1cdfbSStephan Mueller 		.test = alg_test_null,
337964d1cdfbSStephan Mueller 	}, {
338064d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha256",
338164d1cdfbSStephan Mueller 		.test = alg_test_drbg,
338264d1cdfbSStephan Mueller 		.fips_allowed = 1,
338364d1cdfbSStephan Mueller 		.suite = {
338421c8e720SArd Biesheuvel 			.drbg = __VECS(drbg_pr_sha256_tv_template)
338564d1cdfbSStephan Mueller 		}
338664d1cdfbSStephan Mueller 	}, {
338764d1cdfbSStephan Mueller 		/* covered by drbg_pr_sha256 test */
338864d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha384",
338964d1cdfbSStephan Mueller 		.fips_allowed = 1,
339064d1cdfbSStephan Mueller 		.test = alg_test_null,
339164d1cdfbSStephan Mueller 	}, {
339264d1cdfbSStephan Mueller 		.alg = "drbg_pr_sha512",
339364d1cdfbSStephan Mueller 		.fips_allowed = 1,
339464d1cdfbSStephan Mueller 		.test = alg_test_null,
339564d1cdfbSStephan Mueller 	}, {
3396da7f033dSHerbert Xu 		.alg = "ecb(aes)",
33971aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3398a1915d51SJarod Wilson 		.fips_allowed = 1,
3399da7f033dSHerbert Xu 		.suite = {
340092a4c9feSEric Biggers 			.cipher = __VECS(aes_tv_template)
3401da7f033dSHerbert Xu 		}
3402da7f033dSHerbert Xu 	}, {
3403da7f033dSHerbert Xu 		.alg = "ecb(anubis)",
34041aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3405da7f033dSHerbert Xu 		.suite = {
340692a4c9feSEric Biggers 			.cipher = __VECS(anubis_tv_template)
3407da7f033dSHerbert Xu 		}
3408da7f033dSHerbert Xu 	}, {
3409da7f033dSHerbert Xu 		.alg = "ecb(arc4)",
34101aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3411da7f033dSHerbert Xu 		.suite = {
341292a4c9feSEric Biggers 			.cipher = __VECS(arc4_tv_template)
3413da7f033dSHerbert Xu 		}
3414da7f033dSHerbert Xu 	}, {
3415da7f033dSHerbert Xu 		.alg = "ecb(blowfish)",
34161aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3417da7f033dSHerbert Xu 		.suite = {
341892a4c9feSEric Biggers 			.cipher = __VECS(bf_tv_template)
3419da7f033dSHerbert Xu 		}
3420da7f033dSHerbert Xu 	}, {
3421da7f033dSHerbert Xu 		.alg = "ecb(camellia)",
34221aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3423da7f033dSHerbert Xu 		.suite = {
342492a4c9feSEric Biggers 			.cipher = __VECS(camellia_tv_template)
3425da7f033dSHerbert Xu 		}
3426da7f033dSHerbert Xu 	}, {
3427da7f033dSHerbert Xu 		.alg = "ecb(cast5)",
34281aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3429da7f033dSHerbert Xu 		.suite = {
343092a4c9feSEric Biggers 			.cipher = __VECS(cast5_tv_template)
3431da7f033dSHerbert Xu 		}
3432da7f033dSHerbert Xu 	}, {
3433da7f033dSHerbert Xu 		.alg = "ecb(cast6)",
34341aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3435da7f033dSHerbert Xu 		.suite = {
343692a4c9feSEric Biggers 			.cipher = __VECS(cast6_tv_template)
3437da7f033dSHerbert Xu 		}
3438da7f033dSHerbert Xu 	}, {
3439e448370dSJussi Kivilinna 		.alg = "ecb(cipher_null)",
3440e448370dSJussi Kivilinna 		.test = alg_test_null,
34416175ca2bSMilan Broz 		.fips_allowed = 1,
3442e448370dSJussi Kivilinna 	}, {
3443da7f033dSHerbert Xu 		.alg = "ecb(des)",
34441aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3445da7f033dSHerbert Xu 		.suite = {
344692a4c9feSEric Biggers 			.cipher = __VECS(des_tv_template)
3447da7f033dSHerbert Xu 		}
3448da7f033dSHerbert Xu 	}, {
3449da7f033dSHerbert Xu 		.alg = "ecb(des3_ede)",
34501aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3451a1915d51SJarod Wilson 		.fips_allowed = 1,
3452da7f033dSHerbert Xu 		.suite = {
345392a4c9feSEric Biggers 			.cipher = __VECS(des3_ede_tv_template)
3454da7f033dSHerbert Xu 		}
3455da7f033dSHerbert Xu 	}, {
345666e5bd00SJussi Kivilinna 		.alg = "ecb(fcrypt)",
345766e5bd00SJussi Kivilinna 		.test = alg_test_skcipher,
345866e5bd00SJussi Kivilinna 		.suite = {
345966e5bd00SJussi Kivilinna 			.cipher = {
346092a4c9feSEric Biggers 				.vecs = fcrypt_pcbc_tv_template,
346166e5bd00SJussi Kivilinna 				.count = 1
346266e5bd00SJussi Kivilinna 			}
346366e5bd00SJussi Kivilinna 		}
346466e5bd00SJussi Kivilinna 	}, {
3465da7f033dSHerbert Xu 		.alg = "ecb(khazad)",
34661aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3467da7f033dSHerbert Xu 		.suite = {
346892a4c9feSEric Biggers 			.cipher = __VECS(khazad_tv_template)
3469da7f033dSHerbert Xu 		}
3470da7f033dSHerbert Xu 	}, {
347115f47ce5SGilad Ben-Yossef 		/* Same as ecb(aes) except the key is stored in
347215f47ce5SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
347315f47ce5SGilad Ben-Yossef 		 */
347415f47ce5SGilad Ben-Yossef 		.alg = "ecb(paes)",
347515f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
347615f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
347715f47ce5SGilad Ben-Yossef 	}, {
3478da7f033dSHerbert Xu 		.alg = "ecb(seed)",
34791aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3480da7f033dSHerbert Xu 		.suite = {
348192a4c9feSEric Biggers 			.cipher = __VECS(seed_tv_template)
3482da7f033dSHerbert Xu 		}
3483da7f033dSHerbert Xu 	}, {
3484da7f033dSHerbert Xu 		.alg = "ecb(serpent)",
34851aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3486da7f033dSHerbert Xu 		.suite = {
348792a4c9feSEric Biggers 			.cipher = __VECS(serpent_tv_template)
3488da7f033dSHerbert Xu 		}
3489da7f033dSHerbert Xu 	}, {
3490cd83a8a7SGilad Ben-Yossef 		.alg = "ecb(sm4)",
3491cd83a8a7SGilad Ben-Yossef 		.test = alg_test_skcipher,
3492cd83a8a7SGilad Ben-Yossef 		.suite = {
349392a4c9feSEric Biggers 			.cipher = __VECS(sm4_tv_template)
3494cd83a8a7SGilad Ben-Yossef 		}
3495cd83a8a7SGilad Ben-Yossef 	}, {
3496da7f033dSHerbert Xu 		.alg = "ecb(tea)",
34971aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3498da7f033dSHerbert Xu 		.suite = {
349992a4c9feSEric Biggers 			.cipher = __VECS(tea_tv_template)
3500da7f033dSHerbert Xu 		}
3501da7f033dSHerbert Xu 	}, {
3502da7f033dSHerbert Xu 		.alg = "ecb(tnepres)",
35031aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3504da7f033dSHerbert Xu 		.suite = {
350592a4c9feSEric Biggers 			.cipher = __VECS(tnepres_tv_template)
3506da7f033dSHerbert Xu 		}
3507da7f033dSHerbert Xu 	}, {
3508da7f033dSHerbert Xu 		.alg = "ecb(twofish)",
35091aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3510da7f033dSHerbert Xu 		.suite = {
351192a4c9feSEric Biggers 			.cipher = __VECS(tf_tv_template)
3512da7f033dSHerbert Xu 		}
3513da7f033dSHerbert Xu 	}, {
3514da7f033dSHerbert Xu 		.alg = "ecb(xeta)",
35151aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3516da7f033dSHerbert Xu 		.suite = {
351792a4c9feSEric Biggers 			.cipher = __VECS(xeta_tv_template)
3518da7f033dSHerbert Xu 		}
3519da7f033dSHerbert Xu 	}, {
3520da7f033dSHerbert Xu 		.alg = "ecb(xtea)",
35211aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3522da7f033dSHerbert Xu 		.suite = {
352392a4c9feSEric Biggers 			.cipher = __VECS(xtea_tv_template)
3524da7f033dSHerbert Xu 		}
3525da7f033dSHerbert Xu 	}, {
35263c4b2390SSalvatore Benedetto 		.alg = "ecdh",
35273c4b2390SSalvatore Benedetto 		.test = alg_test_kpp,
35283c4b2390SSalvatore Benedetto 		.fips_allowed = 1,
35293c4b2390SSalvatore Benedetto 		.suite = {
353021c8e720SArd Biesheuvel 			.kpp = __VECS(ecdh_tv_template)
35313c4b2390SSalvatore Benedetto 		}
35323c4b2390SSalvatore Benedetto 	}, {
3533da7f033dSHerbert Xu 		.alg = "gcm(aes)",
3534da7f033dSHerbert Xu 		.test = alg_test_aead,
3535a1915d51SJarod Wilson 		.fips_allowed = 1,
3536da7f033dSHerbert Xu 		.suite = {
3537a0d608eeSEric Biggers 			.aead = __VECS(aes_gcm_tv_template)
3538da7f033dSHerbert Xu 		}
3539da7f033dSHerbert Xu 	}, {
3540507069c9SYouquan, Song 		.alg = "ghash",
3541507069c9SYouquan, Song 		.test = alg_test_hash,
354218c0ebd2SJarod Wilson 		.fips_allowed = 1,
3543507069c9SYouquan, Song 		.suite = {
354421c8e720SArd Biesheuvel 			.hash = __VECS(ghash_tv_template)
3545507069c9SYouquan, Song 		}
3546507069c9SYouquan, Song 	}, {
3547da7f033dSHerbert Xu 		.alg = "hmac(md5)",
3548da7f033dSHerbert Xu 		.test = alg_test_hash,
3549da7f033dSHerbert Xu 		.suite = {
355021c8e720SArd Biesheuvel 			.hash = __VECS(hmac_md5_tv_template)
3551da7f033dSHerbert Xu 		}
3552da7f033dSHerbert Xu 	}, {
3553da7f033dSHerbert Xu 		.alg = "hmac(rmd128)",
3554da7f033dSHerbert Xu 		.test = alg_test_hash,
3555da7f033dSHerbert Xu 		.suite = {
355621c8e720SArd Biesheuvel 			.hash = __VECS(hmac_rmd128_tv_template)
3557da7f033dSHerbert Xu 		}
3558da7f033dSHerbert Xu 	}, {
3559da7f033dSHerbert Xu 		.alg = "hmac(rmd160)",
3560da7f033dSHerbert Xu 		.test = alg_test_hash,
3561da7f033dSHerbert Xu 		.suite = {
356221c8e720SArd Biesheuvel 			.hash = __VECS(hmac_rmd160_tv_template)
3563da7f033dSHerbert Xu 		}
3564da7f033dSHerbert Xu 	}, {
3565da7f033dSHerbert Xu 		.alg = "hmac(sha1)",
3566da7f033dSHerbert Xu 		.test = alg_test_hash,
3567a1915d51SJarod Wilson 		.fips_allowed = 1,
3568da7f033dSHerbert Xu 		.suite = {
356921c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha1_tv_template)
3570da7f033dSHerbert Xu 		}
3571da7f033dSHerbert Xu 	}, {
3572da7f033dSHerbert Xu 		.alg = "hmac(sha224)",
3573da7f033dSHerbert Xu 		.test = alg_test_hash,
3574a1915d51SJarod Wilson 		.fips_allowed = 1,
3575da7f033dSHerbert Xu 		.suite = {
357621c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha224_tv_template)
3577da7f033dSHerbert Xu 		}
3578da7f033dSHerbert Xu 	}, {
3579da7f033dSHerbert Xu 		.alg = "hmac(sha256)",
3580da7f033dSHerbert Xu 		.test = alg_test_hash,
3581a1915d51SJarod Wilson 		.fips_allowed = 1,
3582da7f033dSHerbert Xu 		.suite = {
358321c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha256_tv_template)
3584da7f033dSHerbert Xu 		}
3585da7f033dSHerbert Xu 	}, {
358698eca72fSraveendra padasalagi 		.alg = "hmac(sha3-224)",
358798eca72fSraveendra padasalagi 		.test = alg_test_hash,
358898eca72fSraveendra padasalagi 		.fips_allowed = 1,
358998eca72fSraveendra padasalagi 		.suite = {
359021c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_224_tv_template)
359198eca72fSraveendra padasalagi 		}
359298eca72fSraveendra padasalagi 	}, {
359398eca72fSraveendra padasalagi 		.alg = "hmac(sha3-256)",
359498eca72fSraveendra padasalagi 		.test = alg_test_hash,
359598eca72fSraveendra padasalagi 		.fips_allowed = 1,
359698eca72fSraveendra padasalagi 		.suite = {
359721c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_256_tv_template)
359898eca72fSraveendra padasalagi 		}
359998eca72fSraveendra padasalagi 	}, {
360098eca72fSraveendra padasalagi 		.alg = "hmac(sha3-384)",
360198eca72fSraveendra padasalagi 		.test = alg_test_hash,
360298eca72fSraveendra padasalagi 		.fips_allowed = 1,
360398eca72fSraveendra padasalagi 		.suite = {
360421c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_384_tv_template)
360598eca72fSraveendra padasalagi 		}
360698eca72fSraveendra padasalagi 	}, {
360798eca72fSraveendra padasalagi 		.alg = "hmac(sha3-512)",
360898eca72fSraveendra padasalagi 		.test = alg_test_hash,
360998eca72fSraveendra padasalagi 		.fips_allowed = 1,
361098eca72fSraveendra padasalagi 		.suite = {
361121c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha3_512_tv_template)
361298eca72fSraveendra padasalagi 		}
361398eca72fSraveendra padasalagi 	}, {
3614da7f033dSHerbert Xu 		.alg = "hmac(sha384)",
3615da7f033dSHerbert Xu 		.test = alg_test_hash,
3616a1915d51SJarod Wilson 		.fips_allowed = 1,
3617da7f033dSHerbert Xu 		.suite = {
361821c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha384_tv_template)
3619da7f033dSHerbert Xu 		}
3620da7f033dSHerbert Xu 	}, {
3621da7f033dSHerbert Xu 		.alg = "hmac(sha512)",
3622da7f033dSHerbert Xu 		.test = alg_test_hash,
3623a1915d51SJarod Wilson 		.fips_allowed = 1,
3624da7f033dSHerbert Xu 		.suite = {
362521c8e720SArd Biesheuvel 			.hash = __VECS(hmac_sha512_tv_template)
3626da7f033dSHerbert Xu 		}
3627da7f033dSHerbert Xu 	}, {
362825a0b9d4SVitaly Chikunov 		.alg = "hmac(streebog256)",
362925a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
363025a0b9d4SVitaly Chikunov 		.suite = {
363125a0b9d4SVitaly Chikunov 			.hash = __VECS(hmac_streebog256_tv_template)
363225a0b9d4SVitaly Chikunov 		}
363325a0b9d4SVitaly Chikunov 	}, {
363425a0b9d4SVitaly Chikunov 		.alg = "hmac(streebog512)",
363525a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
363625a0b9d4SVitaly Chikunov 		.suite = {
363725a0b9d4SVitaly Chikunov 			.hash = __VECS(hmac_streebog512_tv_template)
363825a0b9d4SVitaly Chikunov 		}
363925a0b9d4SVitaly Chikunov 	}, {
3640bb5530e4SStephan Mueller 		.alg = "jitterentropy_rng",
3641bb5530e4SStephan Mueller 		.fips_allowed = 1,
3642bb5530e4SStephan Mueller 		.test = alg_test_null,
3643bb5530e4SStephan Mueller 	}, {
364435351988SStephan Mueller 		.alg = "kw(aes)",
364535351988SStephan Mueller 		.test = alg_test_skcipher,
364635351988SStephan Mueller 		.fips_allowed = 1,
364735351988SStephan Mueller 		.suite = {
364892a4c9feSEric Biggers 			.cipher = __VECS(aes_kw_tv_template)
364935351988SStephan Mueller 		}
365035351988SStephan Mueller 	}, {
3651da7f033dSHerbert Xu 		.alg = "lrw(aes)",
36521aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3653da7f033dSHerbert Xu 		.suite = {
365492a4c9feSEric Biggers 			.cipher = __VECS(aes_lrw_tv_template)
3655da7f033dSHerbert Xu 		}
3656da7f033dSHerbert Xu 	}, {
36570840605eSJussi Kivilinna 		.alg = "lrw(camellia)",
36580840605eSJussi Kivilinna 		.test = alg_test_skcipher,
36590840605eSJussi Kivilinna 		.suite = {
366092a4c9feSEric Biggers 			.cipher = __VECS(camellia_lrw_tv_template)
36610840605eSJussi Kivilinna 		}
36620840605eSJussi Kivilinna 	}, {
36639b8b0405SJohannes Goetzfried 		.alg = "lrw(cast6)",
36649b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
36659b8b0405SJohannes Goetzfried 		.suite = {
366692a4c9feSEric Biggers 			.cipher = __VECS(cast6_lrw_tv_template)
36679b8b0405SJohannes Goetzfried 		}
36689b8b0405SJohannes Goetzfried 	}, {
3669d7bfc0faSJussi Kivilinna 		.alg = "lrw(serpent)",
3670d7bfc0faSJussi Kivilinna 		.test = alg_test_skcipher,
3671d7bfc0faSJussi Kivilinna 		.suite = {
367292a4c9feSEric Biggers 			.cipher = __VECS(serpent_lrw_tv_template)
3673d7bfc0faSJussi Kivilinna 		}
3674d7bfc0faSJussi Kivilinna 	}, {
36750b2a1551SJussi Kivilinna 		.alg = "lrw(twofish)",
36760b2a1551SJussi Kivilinna 		.test = alg_test_skcipher,
36770b2a1551SJussi Kivilinna 		.suite = {
367892a4c9feSEric Biggers 			.cipher = __VECS(tf_lrw_tv_template)
36790b2a1551SJussi Kivilinna 		}
36800b2a1551SJussi Kivilinna 	}, {
36811443cc9bSKOVACS Krisztian 		.alg = "lz4",
36821443cc9bSKOVACS Krisztian 		.test = alg_test_comp,
36831443cc9bSKOVACS Krisztian 		.fips_allowed = 1,
36841443cc9bSKOVACS Krisztian 		.suite = {
36851443cc9bSKOVACS Krisztian 			.comp = {
368621c8e720SArd Biesheuvel 				.comp = __VECS(lz4_comp_tv_template),
368721c8e720SArd Biesheuvel 				.decomp = __VECS(lz4_decomp_tv_template)
36881443cc9bSKOVACS Krisztian 			}
36891443cc9bSKOVACS Krisztian 		}
36901443cc9bSKOVACS Krisztian 	}, {
36911443cc9bSKOVACS Krisztian 		.alg = "lz4hc",
36921443cc9bSKOVACS Krisztian 		.test = alg_test_comp,
36931443cc9bSKOVACS Krisztian 		.fips_allowed = 1,
36941443cc9bSKOVACS Krisztian 		.suite = {
36951443cc9bSKOVACS Krisztian 			.comp = {
369621c8e720SArd Biesheuvel 				.comp = __VECS(lz4hc_comp_tv_template),
369721c8e720SArd Biesheuvel 				.decomp = __VECS(lz4hc_decomp_tv_template)
36981443cc9bSKOVACS Krisztian 			}
36991443cc9bSKOVACS Krisztian 		}
37001443cc9bSKOVACS Krisztian 	}, {
3701da7f033dSHerbert Xu 		.alg = "lzo",
3702da7f033dSHerbert Xu 		.test = alg_test_comp,
37030818904dSMilan Broz 		.fips_allowed = 1,
3704da7f033dSHerbert Xu 		.suite = {
3705da7f033dSHerbert Xu 			.comp = {
370621c8e720SArd Biesheuvel 				.comp = __VECS(lzo_comp_tv_template),
370721c8e720SArd Biesheuvel 				.decomp = __VECS(lzo_decomp_tv_template)
3708da7f033dSHerbert Xu 			}
3709da7f033dSHerbert Xu 		}
3710da7f033dSHerbert Xu 	}, {
3711da7f033dSHerbert Xu 		.alg = "md4",
3712da7f033dSHerbert Xu 		.test = alg_test_hash,
3713da7f033dSHerbert Xu 		.suite = {
371421c8e720SArd Biesheuvel 			.hash = __VECS(md4_tv_template)
3715da7f033dSHerbert Xu 		}
3716da7f033dSHerbert Xu 	}, {
3717da7f033dSHerbert Xu 		.alg = "md5",
3718da7f033dSHerbert Xu 		.test = alg_test_hash,
3719da7f033dSHerbert Xu 		.suite = {
372021c8e720SArd Biesheuvel 			.hash = __VECS(md5_tv_template)
3721da7f033dSHerbert Xu 		}
3722da7f033dSHerbert Xu 	}, {
3723da7f033dSHerbert Xu 		.alg = "michael_mic",
3724da7f033dSHerbert Xu 		.test = alg_test_hash,
3725da7f033dSHerbert Xu 		.suite = {
372621c8e720SArd Biesheuvel 			.hash = __VECS(michael_mic_tv_template)
3727da7f033dSHerbert Xu 		}
3728da7f033dSHerbert Xu 	}, {
37294feb4c59SOndrej Mosnacek 		.alg = "morus1280",
37304feb4c59SOndrej Mosnacek 		.test = alg_test_aead,
37314feb4c59SOndrej Mosnacek 		.suite = {
3732a0d608eeSEric Biggers 			.aead = __VECS(morus1280_tv_template)
37334feb4c59SOndrej Mosnacek 		}
37344feb4c59SOndrej Mosnacek 	}, {
37354feb4c59SOndrej Mosnacek 		.alg = "morus640",
37364feb4c59SOndrej Mosnacek 		.test = alg_test_aead,
37374feb4c59SOndrej Mosnacek 		.suite = {
3738a0d608eeSEric Biggers 			.aead = __VECS(morus640_tv_template)
37394feb4c59SOndrej Mosnacek 		}
37404feb4c59SOndrej Mosnacek 	}, {
374126609a21SEric Biggers 		.alg = "nhpoly1305",
374226609a21SEric Biggers 		.test = alg_test_hash,
374326609a21SEric Biggers 		.suite = {
374426609a21SEric Biggers 			.hash = __VECS(nhpoly1305_tv_template)
374526609a21SEric Biggers 		}
374626609a21SEric Biggers 	}, {
3747ba0e14acSPuneet Saxena 		.alg = "ofb(aes)",
3748ba0e14acSPuneet Saxena 		.test = alg_test_skcipher,
3749ba0e14acSPuneet Saxena 		.fips_allowed = 1,
3750ba0e14acSPuneet Saxena 		.suite = {
375192a4c9feSEric Biggers 			.cipher = __VECS(aes_ofb_tv_template)
3752ba0e14acSPuneet Saxena 		}
3753ba0e14acSPuneet Saxena 	}, {
3754a794d8d8SGilad Ben-Yossef 		/* Same as ofb(aes) except the key is stored in
3755a794d8d8SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
3756a794d8d8SGilad Ben-Yossef 		 */
3757a794d8d8SGilad Ben-Yossef 		.alg = "ofb(paes)",
3758a794d8d8SGilad Ben-Yossef 		.test = alg_test_null,
3759a794d8d8SGilad Ben-Yossef 		.fips_allowed = 1,
3760a794d8d8SGilad Ben-Yossef 	}, {
3761da7f033dSHerbert Xu 		.alg = "pcbc(fcrypt)",
37621aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3763da7f033dSHerbert Xu 		.suite = {
376492a4c9feSEric Biggers 			.cipher = __VECS(fcrypt_pcbc_tv_template)
3765da7f033dSHerbert Xu 		}
3766da7f033dSHerbert Xu 	}, {
37671207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha224)",
37681207107cSStephan Mueller 		.test = alg_test_null,
37691207107cSStephan Mueller 		.fips_allowed = 1,
37701207107cSStephan Mueller 	}, {
37711207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha256)",
37721207107cSStephan Mueller 		.test = alg_test_akcipher,
37731207107cSStephan Mueller 		.fips_allowed = 1,
37741207107cSStephan Mueller 		.suite = {
37751207107cSStephan Mueller 			.akcipher = __VECS(pkcs1pad_rsa_tv_template)
37761207107cSStephan Mueller 		}
37771207107cSStephan Mueller 	}, {
37781207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha384)",
37791207107cSStephan Mueller 		.test = alg_test_null,
37801207107cSStephan Mueller 		.fips_allowed = 1,
37811207107cSStephan Mueller 	}, {
37821207107cSStephan Mueller 		.alg = "pkcs1pad(rsa,sha512)",
37831207107cSStephan Mueller 		.test = alg_test_null,
37841207107cSStephan Mueller 		.fips_allowed = 1,
37851207107cSStephan Mueller 	}, {
3786eee9dc61SMartin Willi 		.alg = "poly1305",
3787eee9dc61SMartin Willi 		.test = alg_test_hash,
3788eee9dc61SMartin Willi 		.suite = {
378921c8e720SArd Biesheuvel 			.hash = __VECS(poly1305_tv_template)
3790eee9dc61SMartin Willi 		}
3791eee9dc61SMartin Willi 	}, {
3792da7f033dSHerbert Xu 		.alg = "rfc3686(ctr(aes))",
37931aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3794a1915d51SJarod Wilson 		.fips_allowed = 1,
3795da7f033dSHerbert Xu 		.suite = {
379692a4c9feSEric Biggers 			.cipher = __VECS(aes_ctr_rfc3686_tv_template)
3797da7f033dSHerbert Xu 		}
3798da7f033dSHerbert Xu 	}, {
37993f31a740SHerbert Xu 		.alg = "rfc4106(gcm(aes))",
380069435b94SAdrian Hoban 		.test = alg_test_aead,
3801db71f29aSJarod Wilson 		.fips_allowed = 1,
380269435b94SAdrian Hoban 		.suite = {
3803a0d608eeSEric Biggers 			.aead = __VECS(aes_gcm_rfc4106_tv_template)
380469435b94SAdrian Hoban 		}
380569435b94SAdrian Hoban 	}, {
3806544c436aSHerbert Xu 		.alg = "rfc4309(ccm(aes))",
38075d667322SJarod Wilson 		.test = alg_test_aead,
3808a1915d51SJarod Wilson 		.fips_allowed = 1,
38095d667322SJarod Wilson 		.suite = {
3810a0d608eeSEric Biggers 			.aead = __VECS(aes_ccm_rfc4309_tv_template)
38115d667322SJarod Wilson 		}
38125d667322SJarod Wilson 	}, {
3813bb68745eSHerbert Xu 		.alg = "rfc4543(gcm(aes))",
3814e9b7441aSJussi Kivilinna 		.test = alg_test_aead,
3815e9b7441aSJussi Kivilinna 		.suite = {
3816a0d608eeSEric Biggers 			.aead = __VECS(aes_gcm_rfc4543_tv_template)
3817e9b7441aSJussi Kivilinna 		}
3818e9b7441aSJussi Kivilinna 	}, {
3819af2b76b5SMartin Willi 		.alg = "rfc7539(chacha20,poly1305)",
3820af2b76b5SMartin Willi 		.test = alg_test_aead,
3821af2b76b5SMartin Willi 		.suite = {
3822a0d608eeSEric Biggers 			.aead = __VECS(rfc7539_tv_template)
3823af2b76b5SMartin Willi 		}
3824af2b76b5SMartin Willi 	}, {
38255900758dSMartin Willi 		.alg = "rfc7539esp(chacha20,poly1305)",
38265900758dSMartin Willi 		.test = alg_test_aead,
38275900758dSMartin Willi 		.suite = {
3828a0d608eeSEric Biggers 			.aead = __VECS(rfc7539esp_tv_template)
38295900758dSMartin Willi 		}
38305900758dSMartin Willi 	}, {
3831da7f033dSHerbert Xu 		.alg = "rmd128",
3832da7f033dSHerbert Xu 		.test = alg_test_hash,
3833da7f033dSHerbert Xu 		.suite = {
383421c8e720SArd Biesheuvel 			.hash = __VECS(rmd128_tv_template)
3835da7f033dSHerbert Xu 		}
3836da7f033dSHerbert Xu 	}, {
3837da7f033dSHerbert Xu 		.alg = "rmd160",
3838da7f033dSHerbert Xu 		.test = alg_test_hash,
3839da7f033dSHerbert Xu 		.suite = {
384021c8e720SArd Biesheuvel 			.hash = __VECS(rmd160_tv_template)
3841da7f033dSHerbert Xu 		}
3842da7f033dSHerbert Xu 	}, {
3843da7f033dSHerbert Xu 		.alg = "rmd256",
3844da7f033dSHerbert Xu 		.test = alg_test_hash,
3845da7f033dSHerbert Xu 		.suite = {
384621c8e720SArd Biesheuvel 			.hash = __VECS(rmd256_tv_template)
3847da7f033dSHerbert Xu 		}
3848da7f033dSHerbert Xu 	}, {
3849da7f033dSHerbert Xu 		.alg = "rmd320",
3850da7f033dSHerbert Xu 		.test = alg_test_hash,
3851da7f033dSHerbert Xu 		.suite = {
385221c8e720SArd Biesheuvel 			.hash = __VECS(rmd320_tv_template)
3853da7f033dSHerbert Xu 		}
3854da7f033dSHerbert Xu 	}, {
3855946cc463STadeusz Struk 		.alg = "rsa",
3856946cc463STadeusz Struk 		.test = alg_test_akcipher,
3857946cc463STadeusz Struk 		.fips_allowed = 1,
3858946cc463STadeusz Struk 		.suite = {
385921c8e720SArd Biesheuvel 			.akcipher = __VECS(rsa_tv_template)
3860946cc463STadeusz Struk 		}
3861946cc463STadeusz Struk 	}, {
3862da7f033dSHerbert Xu 		.alg = "salsa20",
38631aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
3864da7f033dSHerbert Xu 		.suite = {
386592a4c9feSEric Biggers 			.cipher = __VECS(salsa20_stream_tv_template)
3866da7f033dSHerbert Xu 		}
3867da7f033dSHerbert Xu 	}, {
3868da7f033dSHerbert Xu 		.alg = "sha1",
3869da7f033dSHerbert Xu 		.test = alg_test_hash,
3870a1915d51SJarod Wilson 		.fips_allowed = 1,
3871da7f033dSHerbert Xu 		.suite = {
387221c8e720SArd Biesheuvel 			.hash = __VECS(sha1_tv_template)
3873da7f033dSHerbert Xu 		}
3874da7f033dSHerbert Xu 	}, {
3875da7f033dSHerbert Xu 		.alg = "sha224",
3876da7f033dSHerbert Xu 		.test = alg_test_hash,
3877a1915d51SJarod Wilson 		.fips_allowed = 1,
3878da7f033dSHerbert Xu 		.suite = {
387921c8e720SArd Biesheuvel 			.hash = __VECS(sha224_tv_template)
3880da7f033dSHerbert Xu 		}
3881da7f033dSHerbert Xu 	}, {
3882da7f033dSHerbert Xu 		.alg = "sha256",
3883da7f033dSHerbert Xu 		.test = alg_test_hash,
3884a1915d51SJarod Wilson 		.fips_allowed = 1,
3885da7f033dSHerbert Xu 		.suite = {
388621c8e720SArd Biesheuvel 			.hash = __VECS(sha256_tv_template)
3887da7f033dSHerbert Xu 		}
3888da7f033dSHerbert Xu 	}, {
388979cc6ab8Sraveendra padasalagi 		.alg = "sha3-224",
389079cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
389179cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
389279cc6ab8Sraveendra padasalagi 		.suite = {
389321c8e720SArd Biesheuvel 			.hash = __VECS(sha3_224_tv_template)
389479cc6ab8Sraveendra padasalagi 		}
389579cc6ab8Sraveendra padasalagi 	}, {
389679cc6ab8Sraveendra padasalagi 		.alg = "sha3-256",
389779cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
389879cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
389979cc6ab8Sraveendra padasalagi 		.suite = {
390021c8e720SArd Biesheuvel 			.hash = __VECS(sha3_256_tv_template)
390179cc6ab8Sraveendra padasalagi 		}
390279cc6ab8Sraveendra padasalagi 	}, {
390379cc6ab8Sraveendra padasalagi 		.alg = "sha3-384",
390479cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
390579cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
390679cc6ab8Sraveendra padasalagi 		.suite = {
390721c8e720SArd Biesheuvel 			.hash = __VECS(sha3_384_tv_template)
390879cc6ab8Sraveendra padasalagi 		}
390979cc6ab8Sraveendra padasalagi 	}, {
391079cc6ab8Sraveendra padasalagi 		.alg = "sha3-512",
391179cc6ab8Sraveendra padasalagi 		.test = alg_test_hash,
391279cc6ab8Sraveendra padasalagi 		.fips_allowed = 1,
391379cc6ab8Sraveendra padasalagi 		.suite = {
391421c8e720SArd Biesheuvel 			.hash = __VECS(sha3_512_tv_template)
391579cc6ab8Sraveendra padasalagi 		}
391679cc6ab8Sraveendra padasalagi 	}, {
3917da7f033dSHerbert Xu 		.alg = "sha384",
3918da7f033dSHerbert Xu 		.test = alg_test_hash,
3919a1915d51SJarod Wilson 		.fips_allowed = 1,
3920da7f033dSHerbert Xu 		.suite = {
392121c8e720SArd Biesheuvel 			.hash = __VECS(sha384_tv_template)
3922da7f033dSHerbert Xu 		}
3923da7f033dSHerbert Xu 	}, {
3924da7f033dSHerbert Xu 		.alg = "sha512",
3925da7f033dSHerbert Xu 		.test = alg_test_hash,
3926a1915d51SJarod Wilson 		.fips_allowed = 1,
3927da7f033dSHerbert Xu 		.suite = {
392821c8e720SArd Biesheuvel 			.hash = __VECS(sha512_tv_template)
3929da7f033dSHerbert Xu 		}
3930da7f033dSHerbert Xu 	}, {
3931b7e27530SGilad Ben-Yossef 		.alg = "sm3",
3932b7e27530SGilad Ben-Yossef 		.test = alg_test_hash,
3933b7e27530SGilad Ben-Yossef 		.suite = {
3934b7e27530SGilad Ben-Yossef 			.hash = __VECS(sm3_tv_template)
3935b7e27530SGilad Ben-Yossef 		}
3936b7e27530SGilad Ben-Yossef 	}, {
393725a0b9d4SVitaly Chikunov 		.alg = "streebog256",
393825a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
393925a0b9d4SVitaly Chikunov 		.suite = {
394025a0b9d4SVitaly Chikunov 			.hash = __VECS(streebog256_tv_template)
394125a0b9d4SVitaly Chikunov 		}
394225a0b9d4SVitaly Chikunov 	}, {
394325a0b9d4SVitaly Chikunov 		.alg = "streebog512",
394425a0b9d4SVitaly Chikunov 		.test = alg_test_hash,
394525a0b9d4SVitaly Chikunov 		.suite = {
394625a0b9d4SVitaly Chikunov 			.hash = __VECS(streebog512_tv_template)
394725a0b9d4SVitaly Chikunov 		}
394825a0b9d4SVitaly Chikunov 	}, {
3949da7f033dSHerbert Xu 		.alg = "tgr128",
3950da7f033dSHerbert Xu 		.test = alg_test_hash,
3951da7f033dSHerbert Xu 		.suite = {
395221c8e720SArd Biesheuvel 			.hash = __VECS(tgr128_tv_template)
3953da7f033dSHerbert Xu 		}
3954da7f033dSHerbert Xu 	}, {
3955da7f033dSHerbert Xu 		.alg = "tgr160",
3956da7f033dSHerbert Xu 		.test = alg_test_hash,
3957da7f033dSHerbert Xu 		.suite = {
395821c8e720SArd Biesheuvel 			.hash = __VECS(tgr160_tv_template)
3959da7f033dSHerbert Xu 		}
3960da7f033dSHerbert Xu 	}, {
3961da7f033dSHerbert Xu 		.alg = "tgr192",
3962da7f033dSHerbert Xu 		.test = alg_test_hash,
3963da7f033dSHerbert Xu 		.suite = {
396421c8e720SArd Biesheuvel 			.hash = __VECS(tgr192_tv_template)
3965da7f033dSHerbert Xu 		}
3966da7f033dSHerbert Xu 	}, {
3967ed331adaSEric Biggers 		.alg = "vmac64(aes)",
3968ed331adaSEric Biggers 		.test = alg_test_hash,
3969ed331adaSEric Biggers 		.suite = {
3970ed331adaSEric Biggers 			.hash = __VECS(vmac64_aes_tv_template)
3971ed331adaSEric Biggers 		}
3972ed331adaSEric Biggers 	}, {
3973da7f033dSHerbert Xu 		.alg = "wp256",
3974da7f033dSHerbert Xu 		.test = alg_test_hash,
3975da7f033dSHerbert Xu 		.suite = {
397621c8e720SArd Biesheuvel 			.hash = __VECS(wp256_tv_template)
3977da7f033dSHerbert Xu 		}
3978da7f033dSHerbert Xu 	}, {
3979da7f033dSHerbert Xu 		.alg = "wp384",
3980da7f033dSHerbert Xu 		.test = alg_test_hash,
3981da7f033dSHerbert Xu 		.suite = {
398221c8e720SArd Biesheuvel 			.hash = __VECS(wp384_tv_template)
3983da7f033dSHerbert Xu 		}
3984da7f033dSHerbert Xu 	}, {
3985da7f033dSHerbert Xu 		.alg = "wp512",
3986da7f033dSHerbert Xu 		.test = alg_test_hash,
3987da7f033dSHerbert Xu 		.suite = {
398821c8e720SArd Biesheuvel 			.hash = __VECS(wp512_tv_template)
3989da7f033dSHerbert Xu 		}
3990da7f033dSHerbert Xu 	}, {
3991da7f033dSHerbert Xu 		.alg = "xcbc(aes)",
3992da7f033dSHerbert Xu 		.test = alg_test_hash,
3993da7f033dSHerbert Xu 		.suite = {
399421c8e720SArd Biesheuvel 			.hash = __VECS(aes_xcbc128_tv_template)
3995da7f033dSHerbert Xu 		}
3996da7f033dSHerbert Xu 	}, {
3997aa762409SEric Biggers 		.alg = "xchacha12",
3998aa762409SEric Biggers 		.test = alg_test_skcipher,
3999aa762409SEric Biggers 		.suite = {
4000aa762409SEric Biggers 			.cipher = __VECS(xchacha12_tv_template)
4001aa762409SEric Biggers 		},
4002aa762409SEric Biggers 	}, {
4003de61d7aeSEric Biggers 		.alg = "xchacha20",
4004de61d7aeSEric Biggers 		.test = alg_test_skcipher,
4005de61d7aeSEric Biggers 		.suite = {
4006de61d7aeSEric Biggers 			.cipher = __VECS(xchacha20_tv_template)
4007de61d7aeSEric Biggers 		},
4008de61d7aeSEric Biggers 	}, {
4009da7f033dSHerbert Xu 		.alg = "xts(aes)",
40101aa4ecd9SHerbert Xu 		.test = alg_test_skcipher,
40112918aa8dSJarod Wilson 		.fips_allowed = 1,
4012da7f033dSHerbert Xu 		.suite = {
401392a4c9feSEric Biggers 			.cipher = __VECS(aes_xts_tv_template)
4014da7f033dSHerbert Xu 		}
40150c01aed5SGeert Uytterhoeven 	}, {
40160840605eSJussi Kivilinna 		.alg = "xts(camellia)",
40170840605eSJussi Kivilinna 		.test = alg_test_skcipher,
40180840605eSJussi Kivilinna 		.suite = {
401992a4c9feSEric Biggers 			.cipher = __VECS(camellia_xts_tv_template)
40200840605eSJussi Kivilinna 		}
40210840605eSJussi Kivilinna 	}, {
40229b8b0405SJohannes Goetzfried 		.alg = "xts(cast6)",
40239b8b0405SJohannes Goetzfried 		.test = alg_test_skcipher,
40249b8b0405SJohannes Goetzfried 		.suite = {
402592a4c9feSEric Biggers 			.cipher = __VECS(cast6_xts_tv_template)
40269b8b0405SJohannes Goetzfried 		}
40279b8b0405SJohannes Goetzfried 	}, {
402815f47ce5SGilad Ben-Yossef 		/* Same as xts(aes) except the key is stored in
402915f47ce5SGilad Ben-Yossef 		 * hardware secure memory which we reference by index
403015f47ce5SGilad Ben-Yossef 		 */
403115f47ce5SGilad Ben-Yossef 		.alg = "xts(paes)",
403215f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
403315f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
403415f47ce5SGilad Ben-Yossef 	}, {
403518be20b9SJussi Kivilinna 		.alg = "xts(serpent)",
403618be20b9SJussi Kivilinna 		.test = alg_test_skcipher,
403718be20b9SJussi Kivilinna 		.suite = {
403892a4c9feSEric Biggers 			.cipher = __VECS(serpent_xts_tv_template)
403918be20b9SJussi Kivilinna 		}
404018be20b9SJussi Kivilinna 	}, {
4041aed265b9SJussi Kivilinna 		.alg = "xts(twofish)",
4042aed265b9SJussi Kivilinna 		.test = alg_test_skcipher,
4043aed265b9SJussi Kivilinna 		.suite = {
404492a4c9feSEric Biggers 			.cipher = __VECS(tf_xts_tv_template)
4045aed265b9SJussi Kivilinna 		}
4046a368f43dSGiovanni Cabiddu 	}, {
404715f47ce5SGilad Ben-Yossef 		.alg = "xts4096(paes)",
404815f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
404915f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
405015f47ce5SGilad Ben-Yossef 	}, {
405115f47ce5SGilad Ben-Yossef 		.alg = "xts512(paes)",
405215f47ce5SGilad Ben-Yossef 		.test = alg_test_null,
405315f47ce5SGilad Ben-Yossef 		.fips_allowed = 1,
405415f47ce5SGilad Ben-Yossef 	}, {
4055a368f43dSGiovanni Cabiddu 		.alg = "zlib-deflate",
4056a368f43dSGiovanni Cabiddu 		.test = alg_test_comp,
4057a368f43dSGiovanni Cabiddu 		.fips_allowed = 1,
4058a368f43dSGiovanni Cabiddu 		.suite = {
4059a368f43dSGiovanni Cabiddu 			.comp = {
4060a368f43dSGiovanni Cabiddu 				.comp = __VECS(zlib_deflate_comp_tv_template),
4061a368f43dSGiovanni Cabiddu 				.decomp = __VECS(zlib_deflate_decomp_tv_template)
4062a368f43dSGiovanni Cabiddu 			}
4063a368f43dSGiovanni Cabiddu 		}
4064d28fc3dbSNick Terrell 	}, {
4065d28fc3dbSNick Terrell 		.alg = "zstd",
4066d28fc3dbSNick Terrell 		.test = alg_test_comp,
4067d28fc3dbSNick Terrell 		.fips_allowed = 1,
4068d28fc3dbSNick Terrell 		.suite = {
4069d28fc3dbSNick Terrell 			.comp = {
4070d28fc3dbSNick Terrell 				.comp = __VECS(zstd_comp_tv_template),
4071d28fc3dbSNick Terrell 				.decomp = __VECS(zstd_decomp_tv_template)
4072d28fc3dbSNick Terrell 			}
4073d28fc3dbSNick Terrell 		}
4074da7f033dSHerbert Xu 	}
4075da7f033dSHerbert Xu };
4076da7f033dSHerbert Xu 
40773f47a03dSEric Biggers static void alg_check_test_descs_order(void)
40785714758bSJussi Kivilinna {
40795714758bSJussi Kivilinna 	int i;
40805714758bSJussi Kivilinna 
40815714758bSJussi Kivilinna 	for (i = 1; i < ARRAY_SIZE(alg_test_descs); i++) {
40825714758bSJussi Kivilinna 		int diff = strcmp(alg_test_descs[i - 1].alg,
40835714758bSJussi Kivilinna 				  alg_test_descs[i].alg);
40845714758bSJussi Kivilinna 
40855714758bSJussi Kivilinna 		if (WARN_ON(diff > 0)) {
40865714758bSJussi Kivilinna 			pr_warn("testmgr: alg_test_descs entries in wrong order: '%s' before '%s'\n",
40875714758bSJussi Kivilinna 				alg_test_descs[i - 1].alg,
40885714758bSJussi Kivilinna 				alg_test_descs[i].alg);
40895714758bSJussi Kivilinna 		}
40905714758bSJussi Kivilinna 
40915714758bSJussi Kivilinna 		if (WARN_ON(diff == 0)) {
40925714758bSJussi Kivilinna 			pr_warn("testmgr: duplicate alg_test_descs entry: '%s'\n",
40935714758bSJussi Kivilinna 				alg_test_descs[i].alg);
40945714758bSJussi Kivilinna 		}
40955714758bSJussi Kivilinna 	}
40965714758bSJussi Kivilinna }
40975714758bSJussi Kivilinna 
40983f47a03dSEric Biggers static void alg_check_testvec_configs(void)
40993f47a03dSEric Biggers {
41003f47a03dSEric Biggers }
41013f47a03dSEric Biggers 
41023f47a03dSEric Biggers static void testmgr_onetime_init(void)
41033f47a03dSEric Biggers {
41043f47a03dSEric Biggers 	alg_check_test_descs_order();
41053f47a03dSEric Biggers 	alg_check_testvec_configs();
41063f47a03dSEric Biggers }
41073f47a03dSEric Biggers 
41081aa4ecd9SHerbert Xu static int alg_find_test(const char *alg)
4109da7f033dSHerbert Xu {
4110da7f033dSHerbert Xu 	int start = 0;
4111da7f033dSHerbert Xu 	int end = ARRAY_SIZE(alg_test_descs);
4112da7f033dSHerbert Xu 
4113da7f033dSHerbert Xu 	while (start < end) {
4114da7f033dSHerbert Xu 		int i = (start + end) / 2;
4115da7f033dSHerbert Xu 		int diff = strcmp(alg_test_descs[i].alg, alg);
4116da7f033dSHerbert Xu 
4117da7f033dSHerbert Xu 		if (diff > 0) {
4118da7f033dSHerbert Xu 			end = i;
4119da7f033dSHerbert Xu 			continue;
4120da7f033dSHerbert Xu 		}
4121da7f033dSHerbert Xu 
4122da7f033dSHerbert Xu 		if (diff < 0) {
4123da7f033dSHerbert Xu 			start = i + 1;
4124da7f033dSHerbert Xu 			continue;
4125da7f033dSHerbert Xu 		}
4126da7f033dSHerbert Xu 
41271aa4ecd9SHerbert Xu 		return i;
4128da7f033dSHerbert Xu 	}
4129da7f033dSHerbert Xu 
41301aa4ecd9SHerbert Xu 	return -1;
41311aa4ecd9SHerbert Xu }
41321aa4ecd9SHerbert Xu 
41331aa4ecd9SHerbert Xu int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
41341aa4ecd9SHerbert Xu {
41351aa4ecd9SHerbert Xu 	int i;
4136a68f6610SHerbert Xu 	int j;
4137d12d6b6dSNeil Horman 	int rc;
41381aa4ecd9SHerbert Xu 
41399e5c9fe4SRichard W.M. Jones 	if (!fips_enabled && notests) {
41409e5c9fe4SRichard W.M. Jones 		printk_once(KERN_INFO "alg: self-tests disabled\n");
41419e5c9fe4SRichard W.M. Jones 		return 0;
41429e5c9fe4SRichard W.M. Jones 	}
41439e5c9fe4SRichard W.M. Jones 
41443f47a03dSEric Biggers 	DO_ONCE(testmgr_onetime_init);
41455714758bSJussi Kivilinna 
41461aa4ecd9SHerbert Xu 	if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) {
41471aa4ecd9SHerbert Xu 		char nalg[CRYPTO_MAX_ALG_NAME];
41481aa4ecd9SHerbert Xu 
41491aa4ecd9SHerbert Xu 		if (snprintf(nalg, sizeof(nalg), "ecb(%s)", alg) >=
41501aa4ecd9SHerbert Xu 		    sizeof(nalg))
41511aa4ecd9SHerbert Xu 			return -ENAMETOOLONG;
41521aa4ecd9SHerbert Xu 
41531aa4ecd9SHerbert Xu 		i = alg_find_test(nalg);
41541aa4ecd9SHerbert Xu 		if (i < 0)
41551aa4ecd9SHerbert Xu 			goto notest;
41561aa4ecd9SHerbert Xu 
4157a3bef3a3SJarod Wilson 		if (fips_enabled && !alg_test_descs[i].fips_allowed)
4158a3bef3a3SJarod Wilson 			goto non_fips_alg;
4159a3bef3a3SJarod Wilson 
4160941fb328SJarod Wilson 		rc = alg_test_cipher(alg_test_descs + i, driver, type, mask);
4161941fb328SJarod Wilson 		goto test_done;
41621aa4ecd9SHerbert Xu 	}
41631aa4ecd9SHerbert Xu 
41641aa4ecd9SHerbert Xu 	i = alg_find_test(alg);
4165a68f6610SHerbert Xu 	j = alg_find_test(driver);
4166a68f6610SHerbert Xu 	if (i < 0 && j < 0)
41671aa4ecd9SHerbert Xu 		goto notest;
41681aa4ecd9SHerbert Xu 
4169a68f6610SHerbert Xu 	if (fips_enabled && ((i >= 0 && !alg_test_descs[i].fips_allowed) ||
4170a68f6610SHerbert Xu 			     (j >= 0 && !alg_test_descs[j].fips_allowed)))
4171a3bef3a3SJarod Wilson 		goto non_fips_alg;
4172a3bef3a3SJarod Wilson 
4173a68f6610SHerbert Xu 	rc = 0;
4174a68f6610SHerbert Xu 	if (i >= 0)
4175a68f6610SHerbert Xu 		rc |= alg_test_descs[i].test(alg_test_descs + i, driver,
41761aa4ecd9SHerbert Xu 					     type, mask);
4177032c8cacSCristian Stoica 	if (j >= 0 && j != i)
4178a68f6610SHerbert Xu 		rc |= alg_test_descs[j].test(alg_test_descs + j, driver,
4179a68f6610SHerbert Xu 					     type, mask);
4180a68f6610SHerbert Xu 
4181941fb328SJarod Wilson test_done:
4182d12d6b6dSNeil Horman 	if (fips_enabled && rc)
4183d12d6b6dSNeil Horman 		panic("%s: %s alg self test failed in fips mode!\n", driver, alg);
4184d12d6b6dSNeil Horman 
418529ecd4abSJarod Wilson 	if (fips_enabled && !rc)
41863e8cffd4SMasanari Iida 		pr_info("alg: self-tests for %s (%s) passed\n", driver, alg);
418729ecd4abSJarod Wilson 
4188d12d6b6dSNeil Horman 	return rc;
41891aa4ecd9SHerbert Xu 
41901aa4ecd9SHerbert Xu notest:
4191da7f033dSHerbert Xu 	printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);
4192da7f033dSHerbert Xu 	return 0;
4193a3bef3a3SJarod Wilson non_fips_alg:
4194a3bef3a3SJarod Wilson 	return -EINVAL;
4195da7f033dSHerbert Xu }
41960b767f96SAlexander Shishkin 
4197326a6346SHerbert Xu #endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */
41980b767f96SAlexander Shishkin 
4199da7f033dSHerbert Xu EXPORT_SYMBOL_GPL(alg_test);
4200