xref: /openbmc/linux/crypto/crypto_user_stat.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1cac5818cSCorentin Labbe // SPDX-License-Identifier: GPL-2.0
2cac5818cSCorentin Labbe /*
3cac5818cSCorentin Labbe  * Crypto user configuration API.
4cac5818cSCorentin Labbe  *
5cac5818cSCorentin Labbe  * Copyright (C) 2017-2018 Corentin Labbe <clabbe@baylibre.com>
6cac5818cSCorentin Labbe  *
7cac5818cSCorentin Labbe  */
8cac5818cSCorentin Labbe 
9*9807e49bSHerbert Xu #include <crypto/algapi.h>
10*9807e49bSHerbert Xu #include <crypto/internal/cryptouser.h>
11*9807e49bSHerbert Xu #include <linux/errno.h>
12*9807e49bSHerbert Xu #include <linux/kernel.h>
13*9807e49bSHerbert Xu #include <linux/module.h>
14*9807e49bSHerbert Xu #include <linux/string.h>
15cac5818cSCorentin Labbe #include <net/netlink.h>
1691b05a7eSOndrej Mosnacek #include <net/sock.h>
17cac5818cSCorentin Labbe 
18cac5818cSCorentin Labbe #define null_terminated(x)	(strnlen(x, sizeof(x)) < sizeof(x))
19cac5818cSCorentin Labbe 
20cac5818cSCorentin Labbe struct crypto_dump_info {
21cac5818cSCorentin Labbe 	struct sk_buff *in_skb;
22cac5818cSCorentin Labbe 	struct sk_buff *out_skb;
23cac5818cSCorentin Labbe 	u32 nlmsg_seq;
24cac5818cSCorentin Labbe 	u16 nlmsg_flags;
25cac5818cSCorentin Labbe };
26cac5818cSCorentin Labbe 
crypto_report_cipher(struct sk_buff * skb,struct crypto_alg * alg)27cac5818cSCorentin Labbe static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
28cac5818cSCorentin Labbe {
297f0a9d5cSCorentin Labbe 	struct crypto_stat_cipher rcipher;
30cac5818cSCorentin Labbe 
319f4debe3SCorentin Labbe 	memset(&rcipher, 0, sizeof(rcipher));
329f4debe3SCorentin Labbe 
3337db69e0SEric Biggers 	strscpy(rcipher.type, "cipher", sizeof(rcipher.type));
34cac5818cSCorentin Labbe 
3537db69e0SEric Biggers 	return nla_put(skb, CRYPTOCFGA_STAT_CIPHER, sizeof(rcipher), &rcipher);
36cac5818cSCorentin Labbe }
37cac5818cSCorentin Labbe 
crypto_report_comp(struct sk_buff * skb,struct crypto_alg * alg)38cac5818cSCorentin Labbe static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
39cac5818cSCorentin Labbe {
407f0a9d5cSCorentin Labbe 	struct crypto_stat_compress rcomp;
41cac5818cSCorentin Labbe 
429f4debe3SCorentin Labbe 	memset(&rcomp, 0, sizeof(rcomp));
439f4debe3SCorentin Labbe 
4437db69e0SEric Biggers 	strscpy(rcomp.type, "compression", sizeof(rcomp.type));
45cac5818cSCorentin Labbe 
4637db69e0SEric Biggers 	return nla_put(skb, CRYPTOCFGA_STAT_COMPRESS, sizeof(rcomp), &rcomp);
47cac5818cSCorentin Labbe }
48cac5818cSCorentin Labbe 
crypto_reportstat_one(struct crypto_alg * alg,struct crypto_user_alg * ualg,struct sk_buff * skb)49cac5818cSCorentin Labbe static int crypto_reportstat_one(struct crypto_alg *alg,
50cac5818cSCorentin Labbe 				 struct crypto_user_alg *ualg,
51cac5818cSCorentin Labbe 				 struct sk_buff *skb)
52cac5818cSCorentin Labbe {
539f4debe3SCorentin Labbe 	memset(ualg, 0, sizeof(*ualg));
549f4debe3SCorentin Labbe 
5537db69e0SEric Biggers 	strscpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
5637db69e0SEric Biggers 	strscpy(ualg->cru_driver_name, alg->cra_driver_name,
57cac5818cSCorentin Labbe 		sizeof(ualg->cru_driver_name));
5837db69e0SEric Biggers 	strscpy(ualg->cru_module_name, module_name(alg->cra_module),
59cac5818cSCorentin Labbe 		sizeof(ualg->cru_module_name));
60cac5818cSCorentin Labbe 
61cac5818cSCorentin Labbe 	ualg->cru_type = 0;
62cac5818cSCorentin Labbe 	ualg->cru_mask = 0;
63cac5818cSCorentin Labbe 	ualg->cru_flags = alg->cra_flags;
64cac5818cSCorentin Labbe 	ualg->cru_refcnt = refcount_read(&alg->cra_refcnt);
65cac5818cSCorentin Labbe 
66cac5818cSCorentin Labbe 	if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
67cac5818cSCorentin Labbe 		goto nla_put_failure;
68cac5818cSCorentin Labbe 	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
697f0a9d5cSCorentin Labbe 		struct crypto_stat_larval rl;
70cac5818cSCorentin Labbe 
719f4debe3SCorentin Labbe 		memset(&rl, 0, sizeof(rl));
7237db69e0SEric Biggers 		strscpy(rl.type, "larval", sizeof(rl.type));
7337db69e0SEric Biggers 		if (nla_put(skb, CRYPTOCFGA_STAT_LARVAL, sizeof(rl), &rl))
74cac5818cSCorentin Labbe 			goto nla_put_failure;
75cac5818cSCorentin Labbe 		goto out;
76cac5818cSCorentin Labbe 	}
77cac5818cSCorentin Labbe 
78ed0733eaSHerbert Xu 	if (alg->cra_type && alg->cra_type->report_stat) {
79ed0733eaSHerbert Xu 		if (alg->cra_type->report_stat(skb, alg))
80ed0733eaSHerbert Xu 			goto nla_put_failure;
81ed0733eaSHerbert Xu 		goto out;
82ed0733eaSHerbert Xu 	}
83ed0733eaSHerbert Xu 
84cac5818cSCorentin Labbe 	switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
85cac5818cSCorentin Labbe 	case CRYPTO_ALG_TYPE_CIPHER:
86cac5818cSCorentin Labbe 		if (crypto_report_cipher(skb, alg))
87cac5818cSCorentin Labbe 			goto nla_put_failure;
88cac5818cSCorentin Labbe 		break;
89cac5818cSCorentin Labbe 	case CRYPTO_ALG_TYPE_COMPRESS:
90cac5818cSCorentin Labbe 		if (crypto_report_comp(skb, alg))
91cac5818cSCorentin Labbe 			goto nla_put_failure;
92cac5818cSCorentin Labbe 		break;
93cac5818cSCorentin Labbe 	default:
94cac5818cSCorentin Labbe 		pr_err("ERROR: Unhandled alg %d in %s\n",
95cac5818cSCorentin Labbe 		       alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL),
96cac5818cSCorentin Labbe 		       __func__);
97cac5818cSCorentin Labbe 	}
98cac5818cSCorentin Labbe 
99cac5818cSCorentin Labbe out:
100cac5818cSCorentin Labbe 	return 0;
101cac5818cSCorentin Labbe 
102cac5818cSCorentin Labbe nla_put_failure:
103cac5818cSCorentin Labbe 	return -EMSGSIZE;
104cac5818cSCorentin Labbe }
105cac5818cSCorentin Labbe 
crypto_reportstat_alg(struct crypto_alg * alg,struct crypto_dump_info * info)106cac5818cSCorentin Labbe static int crypto_reportstat_alg(struct crypto_alg *alg,
107cac5818cSCorentin Labbe 				 struct crypto_dump_info *info)
108cac5818cSCorentin Labbe {
109cac5818cSCorentin Labbe 	struct sk_buff *in_skb = info->in_skb;
110cac5818cSCorentin Labbe 	struct sk_buff *skb = info->out_skb;
111cac5818cSCorentin Labbe 	struct nlmsghdr *nlh;
112cac5818cSCorentin Labbe 	struct crypto_user_alg *ualg;
113cac5818cSCorentin Labbe 	int err = 0;
114cac5818cSCorentin Labbe 
115cac5818cSCorentin Labbe 	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
116cac5818cSCorentin Labbe 			CRYPTO_MSG_GETSTAT, sizeof(*ualg), info->nlmsg_flags);
117cac5818cSCorentin Labbe 	if (!nlh) {
118cac5818cSCorentin Labbe 		err = -EMSGSIZE;
119cac5818cSCorentin Labbe 		goto out;
120cac5818cSCorentin Labbe 	}
121cac5818cSCorentin Labbe 
122cac5818cSCorentin Labbe 	ualg = nlmsg_data(nlh);
123cac5818cSCorentin Labbe 
124cac5818cSCorentin Labbe 	err = crypto_reportstat_one(alg, ualg, skb);
125cac5818cSCorentin Labbe 	if (err) {
126cac5818cSCorentin Labbe 		nlmsg_cancel(skb, nlh);
127cac5818cSCorentin Labbe 		goto out;
128cac5818cSCorentin Labbe 	}
129cac5818cSCorentin Labbe 
130cac5818cSCorentin Labbe 	nlmsg_end(skb, nlh);
131cac5818cSCorentin Labbe 
132cac5818cSCorentin Labbe out:
133cac5818cSCorentin Labbe 	return err;
134cac5818cSCorentin Labbe }
135cac5818cSCorentin Labbe 
crypto_reportstat(struct sk_buff * in_skb,struct nlmsghdr * in_nlh,struct nlattr ** attrs)136cac5818cSCorentin Labbe int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
137cac5818cSCorentin Labbe 		      struct nlattr **attrs)
138cac5818cSCorentin Labbe {
13991b05a7eSOndrej Mosnacek 	struct net *net = sock_net(in_skb->sk);
140cac5818cSCorentin Labbe 	struct crypto_user_alg *p = nlmsg_data(in_nlh);
141cac5818cSCorentin Labbe 	struct crypto_alg *alg;
142cac5818cSCorentin Labbe 	struct sk_buff *skb;
143cac5818cSCorentin Labbe 	struct crypto_dump_info info;
144cac5818cSCorentin Labbe 	int err;
145cac5818cSCorentin Labbe 
146cac5818cSCorentin Labbe 	if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
147cac5818cSCorentin Labbe 		return -EINVAL;
148cac5818cSCorentin Labbe 
149cac5818cSCorentin Labbe 	alg = crypto_alg_match(p, 0);
150cac5818cSCorentin Labbe 	if (!alg)
151cac5818cSCorentin Labbe 		return -ENOENT;
152cac5818cSCorentin Labbe 
153cac5818cSCorentin Labbe 	err = -ENOMEM;
154cac5818cSCorentin Labbe 	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
155cac5818cSCorentin Labbe 	if (!skb)
156cac5818cSCorentin Labbe 		goto drop_alg;
157cac5818cSCorentin Labbe 
158cac5818cSCorentin Labbe 	info.in_skb = in_skb;
159cac5818cSCorentin Labbe 	info.out_skb = skb;
160cac5818cSCorentin Labbe 	info.nlmsg_seq = in_nlh->nlmsg_seq;
161cac5818cSCorentin Labbe 	info.nlmsg_flags = 0;
162cac5818cSCorentin Labbe 
163cac5818cSCorentin Labbe 	err = crypto_reportstat_alg(alg, &info);
164cac5818cSCorentin Labbe 
165cac5818cSCorentin Labbe drop_alg:
166cac5818cSCorentin Labbe 	crypto_mod_put(alg);
167cac5818cSCorentin Labbe 
168c03b04dcSNavid Emamdoost 	if (err) {
169c03b04dcSNavid Emamdoost 		kfree_skb(skb);
170cac5818cSCorentin Labbe 		return err;
171c03b04dcSNavid Emamdoost 	}
172cac5818cSCorentin Labbe 
17391b05a7eSOndrej Mosnacek 	return nlmsg_unicast(net->crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
174cac5818cSCorentin Labbe }
175cac5818cSCorentin Labbe 
176cac5818cSCorentin Labbe MODULE_LICENSE("GPL");
177