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