1 /* SPDX-License-Identifier: GPL-2.0 */
2 
3 /*
4  * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
5  */
6 
7 #ifndef _CRYPTO_KDF_SELFTEST_H
8 #define _CRYPTO_KDF_SELFTEST_H
9 
10 #include <crypto/hash.h>
11 #include <linux/uio.h>
12 
13 struct kdf_testvec {
14 	unsigned char *key;
15 	size_t keylen;
16 	unsigned char *ikm;
17 	size_t ikmlen;
18 	struct kvec info;
19 	unsigned char *expected;
20 	size_t expectedlen;
21 };
22 
23 static inline int
kdf_test(const struct kdf_testvec * test,const char * name,int (* crypto_kdf_setkey)(struct crypto_shash * kmd,const u8 * key,size_t keylen,const u8 * ikm,size_t ikmlen),int (* crypto_kdf_generate)(struct crypto_shash * kmd,const struct kvec * info,unsigned int info_nvec,u8 * dst,unsigned int dlen))24 kdf_test(const struct kdf_testvec *test, const char *name,
25 	 int (*crypto_kdf_setkey)(struct crypto_shash *kmd,
26 				  const u8 *key, size_t keylen,
27 				  const u8 *ikm, size_t ikmlen),
28 	 int (*crypto_kdf_generate)(struct crypto_shash *kmd,
29 				    const struct kvec *info,
30 				    unsigned int info_nvec,
31 				    u8 *dst, unsigned int dlen))
32 {
33 	struct crypto_shash *kmd;
34 	int ret;
35 	u8 *buf = kzalloc(test->expectedlen, GFP_KERNEL);
36 
37 	if (!buf)
38 		return -ENOMEM;
39 
40 	kmd = crypto_alloc_shash(name, 0, 0);
41 	if (IS_ERR(kmd)) {
42 		pr_err("alg: kdf: could not allocate hash handle for %s\n",
43 		       name);
44 		kfree(buf);
45 		return -ENOMEM;
46 	}
47 
48 	ret = crypto_kdf_setkey(kmd, test->key, test->keylen,
49 				test->ikm, test->ikmlen);
50 	if (ret) {
51 		pr_err("alg: kdf: could not set key derivation key\n");
52 		goto err;
53 	}
54 
55 	ret = crypto_kdf_generate(kmd, &test->info, 1, buf, test->expectedlen);
56 	if (ret) {
57 		pr_err("alg: kdf: could not obtain key data\n");
58 		goto err;
59 	}
60 
61 	ret = memcmp(test->expected, buf, test->expectedlen);
62 	if (ret)
63 		ret = -EINVAL;
64 
65 err:
66 	crypto_free_shash(kmd);
67 	kfree(buf);
68 	return ret;
69 }
70 
71 #endif /* _CRYPTO_KDF_SELFTEST_H */
72