blob: a03f326a63d32a15536fe9a570843082288f7c0b [file] [log] [blame]
Corentin Labbecac58182018-09-19 10:10:54 +00001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Crypto user configuration API.
4 *
5 * Copyright (C) 2017-2018 Corentin Labbe <clabbe@baylibre.com>
6 *
7 */
8
9#include <linux/crypto.h>
10#include <linux/cryptouser.h>
11#include <linux/sched.h>
12#include <net/netlink.h>
13#include <crypto/internal/skcipher.h>
14#include <crypto/internal/rng.h>
15#include <crypto/akcipher.h>
16#include <crypto/kpp.h>
17#include <crypto/internal/cryptouser.h>
18
19#include "internal.h"
20
21#define null_terminated(x) (strnlen(x, sizeof(x)) < sizeof(x))
22
Corentin Labbecac58182018-09-19 10:10:54 +000023struct crypto_dump_info {
24 struct sk_buff *in_skb;
25 struct sk_buff *out_skb;
26 u32 nlmsg_seq;
27 u16 nlmsg_flags;
28};
29
30static int crypto_report_aead(struct sk_buff *skb, struct crypto_alg *alg)
31{
Corentin Labbe7f0a9d52018-11-29 14:42:19 +000032 struct crypto_stat_aead raead;
Corentin Labbecac58182018-09-19 10:10:54 +000033
Corentin Labbe9f4debe2018-11-03 14:56:01 -070034 memset(&raead, 0, sizeof(raead));
35
Eric Biggers37db69e2018-11-03 14:56:03 -070036 strscpy(raead.type, "aead", sizeof(raead.type));
Corentin Labbecac58182018-09-19 10:10:54 +000037
Corentin Labbe17c18f92018-11-29 14:42:24 +000038 raead.stat_encrypt_cnt = atomic64_read(&alg->stats.aead.encrypt_cnt);
39 raead.stat_encrypt_tlen = atomic64_read(&alg->stats.aead.encrypt_tlen);
40 raead.stat_decrypt_cnt = atomic64_read(&alg->stats.aead.decrypt_cnt);
41 raead.stat_decrypt_tlen = atomic64_read(&alg->stats.aead.decrypt_tlen);
Corentin Labbe44f13132018-11-29 14:42:25 +000042 raead.stat_err_cnt = atomic64_read(&alg->stats.aead.err_cnt);
Corentin Labbecac58182018-09-19 10:10:54 +000043
Eric Biggers37db69e2018-11-03 14:56:03 -070044 return nla_put(skb, CRYPTOCFGA_STAT_AEAD, sizeof(raead), &raead);
Corentin Labbecac58182018-09-19 10:10:54 +000045}
46
47static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
48{
Corentin Labbe7f0a9d52018-11-29 14:42:19 +000049 struct crypto_stat_cipher rcipher;
Corentin Labbecac58182018-09-19 10:10:54 +000050
Corentin Labbe9f4debe2018-11-03 14:56:01 -070051 memset(&rcipher, 0, sizeof(rcipher));
52
Eric Biggers37db69e2018-11-03 14:56:03 -070053 strscpy(rcipher.type, "cipher", sizeof(rcipher.type));
Corentin Labbecac58182018-09-19 10:10:54 +000054
Corentin Labbe17c18f92018-11-29 14:42:24 +000055 rcipher.stat_encrypt_cnt = atomic64_read(&alg->stats.cipher.encrypt_cnt);
56 rcipher.stat_encrypt_tlen = atomic64_read(&alg->stats.cipher.encrypt_tlen);
57 rcipher.stat_decrypt_cnt = atomic64_read(&alg->stats.cipher.decrypt_cnt);
58 rcipher.stat_decrypt_tlen = atomic64_read(&alg->stats.cipher.decrypt_tlen);
Corentin Labbe44f13132018-11-29 14:42:25 +000059 rcipher.stat_err_cnt = atomic64_read(&alg->stats.cipher.err_cnt);
Corentin Labbecac58182018-09-19 10:10:54 +000060
Eric Biggers37db69e2018-11-03 14:56:03 -070061 return nla_put(skb, CRYPTOCFGA_STAT_CIPHER, sizeof(rcipher), &rcipher);
Corentin Labbecac58182018-09-19 10:10:54 +000062}
63
64static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
65{
Corentin Labbe7f0a9d52018-11-29 14:42:19 +000066 struct crypto_stat_compress rcomp;
Corentin Labbecac58182018-09-19 10:10:54 +000067
Corentin Labbe9f4debe2018-11-03 14:56:01 -070068 memset(&rcomp, 0, sizeof(rcomp));
69
Eric Biggers37db69e2018-11-03 14:56:03 -070070 strscpy(rcomp.type, "compression", sizeof(rcomp.type));
Corentin Labbe17c18f92018-11-29 14:42:24 +000071 rcomp.stat_compress_cnt = atomic64_read(&alg->stats.compress.compress_cnt);
72 rcomp.stat_compress_tlen = atomic64_read(&alg->stats.compress.compress_tlen);
73 rcomp.stat_decompress_cnt = atomic64_read(&alg->stats.compress.decompress_cnt);
74 rcomp.stat_decompress_tlen = atomic64_read(&alg->stats.compress.decompress_tlen);
Corentin Labbe44f13132018-11-29 14:42:25 +000075 rcomp.stat_err_cnt = atomic64_read(&alg->stats.compress.err_cnt);
Corentin Labbecac58182018-09-19 10:10:54 +000076
Eric Biggers37db69e2018-11-03 14:56:03 -070077 return nla_put(skb, CRYPTOCFGA_STAT_COMPRESS, sizeof(rcomp), &rcomp);
Corentin Labbecac58182018-09-19 10:10:54 +000078}
79
80static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
81{
Corentin Labbe7f0a9d52018-11-29 14:42:19 +000082 struct crypto_stat_compress racomp;
Corentin Labbecac58182018-09-19 10:10:54 +000083
Corentin Labbe9f4debe2018-11-03 14:56:01 -070084 memset(&racomp, 0, sizeof(racomp));
85
Eric Biggers37db69e2018-11-03 14:56:03 -070086 strscpy(racomp.type, "acomp", sizeof(racomp.type));
Corentin Labbe17c18f92018-11-29 14:42:24 +000087 racomp.stat_compress_cnt = atomic64_read(&alg->stats.compress.compress_cnt);
88 racomp.stat_compress_tlen = atomic64_read(&alg->stats.compress.compress_tlen);
89 racomp.stat_decompress_cnt = atomic64_read(&alg->stats.compress.decompress_cnt);
90 racomp.stat_decompress_tlen = atomic64_read(&alg->stats.compress.decompress_tlen);
Corentin Labbe44f13132018-11-29 14:42:25 +000091 racomp.stat_err_cnt = atomic64_read(&alg->stats.compress.err_cnt);
Corentin Labbecac58182018-09-19 10:10:54 +000092
Eric Biggers37db69e2018-11-03 14:56:03 -070093 return nla_put(skb, CRYPTOCFGA_STAT_ACOMP, sizeof(racomp), &racomp);
Corentin Labbecac58182018-09-19 10:10:54 +000094}
95
96static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
97{
Corentin Labbe7f0a9d52018-11-29 14:42:19 +000098 struct crypto_stat_akcipher rakcipher;
Corentin Labbecac58182018-09-19 10:10:54 +000099
Corentin Labbe9f4debe2018-11-03 14:56:01 -0700100 memset(&rakcipher, 0, sizeof(rakcipher));
101
Eric Biggers37db69e2018-11-03 14:56:03 -0700102 strscpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
Corentin Labbe17c18f92018-11-29 14:42:24 +0000103 rakcipher.stat_encrypt_cnt = atomic64_read(&alg->stats.akcipher.encrypt_cnt);
104 rakcipher.stat_encrypt_tlen = atomic64_read(&alg->stats.akcipher.encrypt_tlen);
105 rakcipher.stat_decrypt_cnt = atomic64_read(&alg->stats.akcipher.decrypt_cnt);
106 rakcipher.stat_decrypt_tlen = atomic64_read(&alg->stats.akcipher.decrypt_tlen);
107 rakcipher.stat_sign_cnt = atomic64_read(&alg->stats.akcipher.sign_cnt);
108 rakcipher.stat_verify_cnt = atomic64_read(&alg->stats.akcipher.verify_cnt);
Corentin Labbe44f13132018-11-29 14:42:25 +0000109 rakcipher.stat_err_cnt = atomic64_read(&alg->stats.akcipher.err_cnt);
Corentin Labbecac58182018-09-19 10:10:54 +0000110
Eric Biggers37db69e2018-11-03 14:56:03 -0700111 return nla_put(skb, CRYPTOCFGA_STAT_AKCIPHER,
112 sizeof(rakcipher), &rakcipher);
Corentin Labbecac58182018-09-19 10:10:54 +0000113}
114
115static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
116{
Corentin Labbe7f0a9d52018-11-29 14:42:19 +0000117 struct crypto_stat_kpp rkpp;
Corentin Labbecac58182018-09-19 10:10:54 +0000118
Corentin Labbe9f4debe2018-11-03 14:56:01 -0700119 memset(&rkpp, 0, sizeof(rkpp));
120
Eric Biggers37db69e2018-11-03 14:56:03 -0700121 strscpy(rkpp.type, "kpp", sizeof(rkpp.type));
Corentin Labbecac58182018-09-19 10:10:54 +0000122
Corentin Labbe17c18f92018-11-29 14:42:24 +0000123 rkpp.stat_setsecret_cnt = atomic64_read(&alg->stats.kpp.setsecret_cnt);
124 rkpp.stat_generate_public_key_cnt = atomic64_read(&alg->stats.kpp.generate_public_key_cnt);
125 rkpp.stat_compute_shared_secret_cnt = atomic64_read(&alg->stats.kpp.compute_shared_secret_cnt);
Corentin Labbe44f13132018-11-29 14:42:25 +0000126 rkpp.stat_err_cnt = atomic64_read(&alg->stats.kpp.err_cnt);
Corentin Labbecac58182018-09-19 10:10:54 +0000127
Eric Biggers37db69e2018-11-03 14:56:03 -0700128 return nla_put(skb, CRYPTOCFGA_STAT_KPP, sizeof(rkpp), &rkpp);
Corentin Labbecac58182018-09-19 10:10:54 +0000129}
130
131static int crypto_report_ahash(struct sk_buff *skb, struct crypto_alg *alg)
132{
Corentin Labbe7f0a9d52018-11-29 14:42:19 +0000133 struct crypto_stat_hash rhash;
Corentin Labbecac58182018-09-19 10:10:54 +0000134
Corentin Labbe9f4debe2018-11-03 14:56:01 -0700135 memset(&rhash, 0, sizeof(rhash));
136
Eric Biggers37db69e2018-11-03 14:56:03 -0700137 strscpy(rhash.type, "ahash", sizeof(rhash.type));
Corentin Labbecac58182018-09-19 10:10:54 +0000138
Corentin Labbe17c18f92018-11-29 14:42:24 +0000139 rhash.stat_hash_cnt = atomic64_read(&alg->stats.hash.hash_cnt);
140 rhash.stat_hash_tlen = atomic64_read(&alg->stats.hash.hash_tlen);
Corentin Labbe44f13132018-11-29 14:42:25 +0000141 rhash.stat_err_cnt = atomic64_read(&alg->stats.hash.err_cnt);
Corentin Labbecac58182018-09-19 10:10:54 +0000142
Eric Biggers37db69e2018-11-03 14:56:03 -0700143 return nla_put(skb, CRYPTOCFGA_STAT_HASH, sizeof(rhash), &rhash);
Corentin Labbecac58182018-09-19 10:10:54 +0000144}
145
146static int crypto_report_shash(struct sk_buff *skb, struct crypto_alg *alg)
147{
Corentin Labbe7f0a9d52018-11-29 14:42:19 +0000148 struct crypto_stat_hash rhash;
Corentin Labbecac58182018-09-19 10:10:54 +0000149
Corentin Labbe9f4debe2018-11-03 14:56:01 -0700150 memset(&rhash, 0, sizeof(rhash));
151
Eric Biggers37db69e2018-11-03 14:56:03 -0700152 strscpy(rhash.type, "shash", sizeof(rhash.type));
Corentin Labbecac58182018-09-19 10:10:54 +0000153
Corentin Labbe17c18f92018-11-29 14:42:24 +0000154 rhash.stat_hash_cnt = atomic64_read(&alg->stats.hash.hash_cnt);
155 rhash.stat_hash_tlen = atomic64_read(&alg->stats.hash.hash_tlen);
Corentin Labbe44f13132018-11-29 14:42:25 +0000156 rhash.stat_err_cnt = atomic64_read(&alg->stats.hash.err_cnt);
Corentin Labbecac58182018-09-19 10:10:54 +0000157
Eric Biggers37db69e2018-11-03 14:56:03 -0700158 return nla_put(skb, CRYPTOCFGA_STAT_HASH, sizeof(rhash), &rhash);
Corentin Labbecac58182018-09-19 10:10:54 +0000159}
160
161static int crypto_report_rng(struct sk_buff *skb, struct crypto_alg *alg)
162{
Corentin Labbe7f0a9d52018-11-29 14:42:19 +0000163 struct crypto_stat_rng rrng;
Corentin Labbecac58182018-09-19 10:10:54 +0000164
Corentin Labbe9f4debe2018-11-03 14:56:01 -0700165 memset(&rrng, 0, sizeof(rrng));
166
Eric Biggers37db69e2018-11-03 14:56:03 -0700167 strscpy(rrng.type, "rng", sizeof(rrng.type));
Corentin Labbecac58182018-09-19 10:10:54 +0000168
Corentin Labbe17c18f92018-11-29 14:42:24 +0000169 rrng.stat_generate_cnt = atomic64_read(&alg->stats.rng.generate_cnt);
170 rrng.stat_generate_tlen = atomic64_read(&alg->stats.rng.generate_tlen);
171 rrng.stat_seed_cnt = atomic64_read(&alg->stats.rng.seed_cnt);
Corentin Labbe44f13132018-11-29 14:42:25 +0000172 rrng.stat_err_cnt = atomic64_read(&alg->stats.rng.err_cnt);
Corentin Labbecac58182018-09-19 10:10:54 +0000173
Eric Biggers37db69e2018-11-03 14:56:03 -0700174 return nla_put(skb, CRYPTOCFGA_STAT_RNG, sizeof(rrng), &rrng);
Corentin Labbecac58182018-09-19 10:10:54 +0000175}
176
177static int crypto_reportstat_one(struct crypto_alg *alg,
178 struct crypto_user_alg *ualg,
179 struct sk_buff *skb)
180{
Corentin Labbe9f4debe2018-11-03 14:56:01 -0700181 memset(ualg, 0, sizeof(*ualg));
182
Eric Biggers37db69e2018-11-03 14:56:03 -0700183 strscpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
184 strscpy(ualg->cru_driver_name, alg->cra_driver_name,
Corentin Labbecac58182018-09-19 10:10:54 +0000185 sizeof(ualg->cru_driver_name));
Eric Biggers37db69e2018-11-03 14:56:03 -0700186 strscpy(ualg->cru_module_name, module_name(alg->cra_module),
Corentin Labbecac58182018-09-19 10:10:54 +0000187 sizeof(ualg->cru_module_name));
188
189 ualg->cru_type = 0;
190 ualg->cru_mask = 0;
191 ualg->cru_flags = alg->cra_flags;
192 ualg->cru_refcnt = refcount_read(&alg->cra_refcnt);
193
194 if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
195 goto nla_put_failure;
196 if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
Corentin Labbe7f0a9d52018-11-29 14:42:19 +0000197 struct crypto_stat_larval rl;
Corentin Labbecac58182018-09-19 10:10:54 +0000198
Corentin Labbe9f4debe2018-11-03 14:56:01 -0700199 memset(&rl, 0, sizeof(rl));
Eric Biggers37db69e2018-11-03 14:56:03 -0700200 strscpy(rl.type, "larval", sizeof(rl.type));
201 if (nla_put(skb, CRYPTOCFGA_STAT_LARVAL, sizeof(rl), &rl))
Corentin Labbecac58182018-09-19 10:10:54 +0000202 goto nla_put_failure;
203 goto out;
204 }
205
206 switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
207 case CRYPTO_ALG_TYPE_AEAD:
208 if (crypto_report_aead(skb, alg))
209 goto nla_put_failure;
210 break;
211 case CRYPTO_ALG_TYPE_SKCIPHER:
212 if (crypto_report_cipher(skb, alg))
213 goto nla_put_failure;
214 break;
215 case CRYPTO_ALG_TYPE_BLKCIPHER:
216 if (crypto_report_cipher(skb, alg))
217 goto nla_put_failure;
218 break;
219 case CRYPTO_ALG_TYPE_CIPHER:
220 if (crypto_report_cipher(skb, alg))
221 goto nla_put_failure;
222 break;
223 case CRYPTO_ALG_TYPE_COMPRESS:
224 if (crypto_report_comp(skb, alg))
225 goto nla_put_failure;
226 break;
227 case CRYPTO_ALG_TYPE_ACOMPRESS:
228 if (crypto_report_acomp(skb, alg))
229 goto nla_put_failure;
230 break;
231 case CRYPTO_ALG_TYPE_SCOMPRESS:
232 if (crypto_report_acomp(skb, alg))
233 goto nla_put_failure;
234 break;
235 case CRYPTO_ALG_TYPE_AKCIPHER:
236 if (crypto_report_akcipher(skb, alg))
237 goto nla_put_failure;
238 break;
239 case CRYPTO_ALG_TYPE_KPP:
240 if (crypto_report_kpp(skb, alg))
241 goto nla_put_failure;
242 break;
243 case CRYPTO_ALG_TYPE_AHASH:
244 if (crypto_report_ahash(skb, alg))
245 goto nla_put_failure;
246 break;
247 case CRYPTO_ALG_TYPE_HASH:
248 if (crypto_report_shash(skb, alg))
249 goto nla_put_failure;
250 break;
251 case CRYPTO_ALG_TYPE_RNG:
252 if (crypto_report_rng(skb, alg))
253 goto nla_put_failure;
254 break;
255 default:
256 pr_err("ERROR: Unhandled alg %d in %s\n",
257 alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL),
258 __func__);
259 }
260
261out:
262 return 0;
263
264nla_put_failure:
265 return -EMSGSIZE;
266}
267
268static int crypto_reportstat_alg(struct crypto_alg *alg,
269 struct crypto_dump_info *info)
270{
271 struct sk_buff *in_skb = info->in_skb;
272 struct sk_buff *skb = info->out_skb;
273 struct nlmsghdr *nlh;
274 struct crypto_user_alg *ualg;
275 int err = 0;
276
277 nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
278 CRYPTO_MSG_GETSTAT, sizeof(*ualg), info->nlmsg_flags);
279 if (!nlh) {
280 err = -EMSGSIZE;
281 goto out;
282 }
283
284 ualg = nlmsg_data(nlh);
285
286 err = crypto_reportstat_one(alg, ualg, skb);
287 if (err) {
288 nlmsg_cancel(skb, nlh);
289 goto out;
290 }
291
292 nlmsg_end(skb, nlh);
293
294out:
295 return err;
296}
297
298int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
299 struct nlattr **attrs)
300{
301 struct crypto_user_alg *p = nlmsg_data(in_nlh);
302 struct crypto_alg *alg;
303 struct sk_buff *skb;
304 struct crypto_dump_info info;
305 int err;
306
307 if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
308 return -EINVAL;
309
310 alg = crypto_alg_match(p, 0);
311 if (!alg)
312 return -ENOENT;
313
314 err = -ENOMEM;
315 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
316 if (!skb)
317 goto drop_alg;
318
319 info.in_skb = in_skb;
320 info.out_skb = skb;
321 info.nlmsg_seq = in_nlh->nlmsg_seq;
322 info.nlmsg_flags = 0;
323
324 err = crypto_reportstat_alg(alg, &info);
325
326drop_alg:
327 crypto_mod_put(alg);
328
329 if (err)
330 return err;
331
332 return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
333}
334
Corentin Labbecac58182018-09-19 10:10:54 +0000335MODULE_LICENSE("GPL");